Files
yutu/pkg/utils/utils_test.go
T

531 lines
9.7 KiB
Go

// Copyright 2025 eat-pray-ai & OpenWaygate
// SPDX-License-Identifier: Apache-2.0
package utils
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"reflect"
"strings"
"testing"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
func TestStrToBoolPtr(t *testing.T) {
type args struct {
b *string
}
tests := []struct {
name string
args args
want *bool
}{
{
name: "true",
args: args{b: new("true")},
want: func() *bool {
b := true
return &b
}(),
},
{
name: "false",
args: args{b: new("false")},
want: func() *bool {
b := false
return &b
}(),
},
{
name: "empty",
args: args{b: new("")},
want: nil,
},
{
name: "null",
args: args{b: new("null")},
want: nil,
},
{
name: "NULL",
args: args{b: new("NULL")},
want: nil,
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
if got := StrToBoolPtr(tt.args.b); !reflect.DeepEqual(got, tt.want) {
t.Errorf("BoolPtr() = %v, want %v", got, tt.want)
}
},
)
}
}
func TestGetFileName(t *testing.T) {
type args struct {
file string
}
tests := []struct {
name string
args args
want string
}{
{
name: "with extension",
args: args{file: "example.txt"},
want: "example",
},
{
name: "without extension",
args: args{file: "example"},
want: "example",
},
{
name: "with path",
args: args{file: "/foo/bar/example.txt"},
want: "example",
},
{
name: "double extension",
args: args{file: "archive.tar.gz"},
want: "archive.tar",
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
if got := GetFileName(tt.args.file); got != tt.want {
t.Errorf("GetFileName() = %v, want %v", got, tt.want)
}
},
)
}
}
func TestIsJson(t *testing.T) {
type args struct {
s string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "valid json",
args: args{s: `{"key": "value"}`},
want: true,
},
{
name: "invalid json",
args: args{s: `{"key": "value"`},
want: false,
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
if got := IsJson(tt.args.s); got != tt.want {
t.Errorf("IsJson() = %v, want %v", got, tt.want)
}
},
)
}
}
func TestIsInteractive(t *testing.T) {
devNull, _ := os.Open(os.DevNull)
defer func() { _ = devNull.Close() }()
tests := []struct {
name string
writer io.Writer
ci string
want bool
}{
{
name: "bytes.Buffer is non-interactive",
writer: &bytes.Buffer{},
want: false,
},
{
name: "os.File without TTY is non-interactive",
writer: devNull,
want: false,
},
{
name: "CI env forces non-interactive",
writer: os.Stdout,
ci: "true",
want: false,
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
if tt.ci != "" {
t.Setenv("CI", tt.ci)
}
if got := IsInteractive(tt.writer); got != tt.want {
t.Errorf("IsInteractive() = %v, want %v", got, tt.want)
}
},
)
}
}
func TestPrintJSON(t *testing.T) {
tests := []struct {
name string
data any
interactive bool
wantWriter string
}{
{
name: "interactive indented json",
data: map[string]string{"key": "value"},
interactive: true,
wantWriter: "{\n \"key\": \"value\"\n}\n",
},
{
name: "non-interactive compact json",
data: map[string]string{"key": "value"},
interactive: false,
wantWriter: "{\"key\":\"value\"}\n",
},
{
name: "nil data interactive",
data: nil,
interactive: true,
wantWriter: "null\n",
},
{
name: "nil data non-interactive",
data: nil,
interactive: false,
wantWriter: "null\n",
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
orig := IsInteractive
IsInteractive = func(any) bool { return tt.interactive }
defer func() { IsInteractive = orig }()
writer := &bytes.Buffer{}
PrintJSON(tt.data, writer)
if gotWriter := writer.String(); gotWriter != tt.wantWriter {
t.Errorf("PrintJSON() = %v, want %v", gotWriter, tt.wantWriter)
}
},
)
}
}
func TestPrintYAML(t *testing.T) {
tests := []struct {
name string
data any
wantWriter string
}{
{
name: "simple yaml",
data: map[string]string{"key": "value"},
wantWriter: "key: value\n\n",
},
{
name: "nil data",
data: nil,
wantWriter: "null\n\n",
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
writer := &bytes.Buffer{}
PrintYAML(tt.data, writer)
if gotWriter := writer.String(); gotWriter != tt.wantWriter {
t.Errorf("PrintYAML() = %v, want %v", gotWriter, tt.wantWriter)
}
},
)
}
}
func TestResetBool(t *testing.T) {
type args struct {
m map[string]**bool
flagSet *pflag.FlagSet
}
b := new(true)
cmd := &cobra.Command{}
cmd.Flags().BoolVar(b, "flag", false, "")
tests := []struct {
name string
args args
}{
{
name: "reset bool flags",
args: args{
m: map[string]**bool{
"flag": &b,
},
flagSet: cmd.Flags(),
},
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
ResetBool(tt.args.m, tt.args.flagSet)
if b != nil {
t.Errorf("ResetBool() = %v, want nil", *b)
}
},
)
}
}
func TestExtractHl(t *testing.T) {
type args struct {
uri string
}
tests := []struct {
name string
args args
want string
}{
{
name: "valid language uri with hl",
args: args{uri: "i18n://language/zh-CN"},
want: "zh-CN",
},
{
name: "valid region uri with hl",
args: args{uri: "i18n://region/zh-CN"},
want: "zh-CN",
},
{
name: "valid language uri without hl",
args: args{uri: "i18n://language/"},
want: "",
},
{
name: "valid region uri without hl",
args: args{uri: "i18n://region/"},
want: "",
},
{
name: "invalid uri",
args: args{uri: "i18n://invalid/zh-CN"},
want: "",
},
{
name: "empty uri",
args: args{uri: ""},
want: "",
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
if got := ExtractHl(tt.args.uri); got != tt.want {
t.Errorf("ExtractHl() = %v, want %v", got, tt.want)
}
},
)
}
}
func TestBoolToStrPtr(t *testing.T) {
bTrue := true
bFalse := false
type args struct {
b *bool
}
tests := []struct {
name string
args args
want *string
}{
{
name: "true",
args: args{b: &bTrue},
want: new("true"),
},
{
name: "false",
args: args{b: &bFalse},
want: new("false"),
},
{
name: "nil",
args: args{b: nil},
want: new(""),
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
if got := BoolToStrPtr(tt.args.b); !reflect.DeepEqual(got, tt.want) {
t.Errorf("BoolToStrPtr() = %v, want %v", got, tt.want)
}
},
)
}
}
func TestRandomStage(t *testing.T) {
s1 := RandomStage()
s2 := RandomStage()
if s1 == "" {
t.Error("RandomStage() returned empty string")
}
if s1 == s2 {
t.Error("RandomStage() returned same value twice")
}
}
func TestConfirmPreRun(t *testing.T) {
tests := []struct {
name string
yes bool
input string
interactive bool
wantErr error
}{
{
name: "yes flag bypasses prompt",
yes: true,
wantErr: nil,
},
{
name: "non-interactive without yes flag",
yes: false,
interactive: false,
wantErr: ErrNotConfirmed,
},
{
name: "interactive confirm with y",
yes: false,
interactive: true,
input: "y\n",
wantErr: nil,
},
{
name: "interactive confirm with Y",
yes: false,
interactive: true,
input: "Y\n",
wantErr: nil,
},
{
name: "interactive deny with n",
yes: false,
interactive: true,
input: "n\n",
wantErr: ErrNotConfirmed,
},
{
name: "interactive deny with empty",
yes: false,
interactive: true,
input: "\n",
wantErr: ErrNotConfirmed,
},
{
name: "interactive deny with EOF",
yes: false,
interactive: true,
input: "",
wantErr: ErrNotConfirmed,
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
orig := IsInteractive
IsInteractive = func(any) bool { return tt.interactive }
defer func() { IsInteractive = orig }()
cmd := &cobra.Command{Use: "test"}
cmd.Flags().Bool("yes", false, "")
if tt.yes {
_ = cmd.Flags().Set("yes", "true")
}
var errBuf bytes.Buffer
cmd.SetErr(&errBuf)
cmd.SetIn(strings.NewReader(tt.input))
err := ConfirmPreRun(cmd, "Would do something")
if !errors.Is(err, tt.wantErr) {
t.Errorf("ConfirmPreRun() error = %v, want %v", err, tt.wantErr)
}
},
)
}
}
func TestHandleCmdError(t *testing.T) {
tests := []struct {
name string
input error
wantOut string
wantErr string
}{
{
name: "with error",
input: fmt.Errorf("some error"),
wantOut: "help called",
wantErr: "Error: some error\n",
},
{
name: "without error",
input: nil,
wantOut: "",
wantErr: "",
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
cmd := &cobra.Command{Use: "test"}
var outBuf, errBuf bytes.Buffer
cmd.SetOut(&outBuf)
cmd.SetErr(&errBuf)
cmd.SetHelpFunc(
func(c *cobra.Command, _ []string) {
_, _ = fmt.Fprint(c.OutOrStdout(), "help called")
},
)
HandleCmdError(tt.input, cmd)
if gotOut := outBuf.String(); gotOut != tt.wantOut {
t.Fatalf(
"unexpected stdout output, got %q, want %q", gotOut, tt.wantOut,
)
}
if gotErr := errBuf.String(); gotErr != tt.wantErr {
t.Fatalf(
"unexpected stderr output, got %q, want %q", gotErr, tt.wantErr,
)
}
},
)
}
}