From 1465e4cc4c7badf9a2c97dd24c43c1bf1c236c32 Mon Sep 17 00:00:00 2001 From: Dmitry Fedotov Date: Wed, 9 Apr 2025 14:20:43 +0300 Subject: [PATCH] bump test coverage to 87.2% --- conf_test.go | 60 +++++++++++ value.go | 4 +- value_test.go | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 value_test.go diff --git a/conf_test.go b/conf_test.go index d4b48b2..75bb4e7 100644 --- a/conf_test.go +++ b/conf_test.go @@ -3,6 +3,8 @@ package conf import ( "bytes" "errors" + "fmt" + "os" "reflect" "slices" "testing" @@ -75,6 +77,18 @@ func TestRead(t *testing.T) { }, err: nil, }, + { + name: "incorrect k/v separator", + in: []byte("key ! value \n"), + res: nil, + err: ErrFormat, + }, + { + name: "duplicate key", + in: []byte("key=value1\nkey=value2\n"), + res: nil, + err: ErrDuplicateKey, + }, } for _, c := range tc { @@ -111,6 +125,52 @@ func TestOpen(t *testing.T) { } } +func TestMainMethods(t *testing.T) { + key := "key" + value := "value" + b := []byte(fmt.Sprintf("%s = %s", key, value)) + r := bytes.NewReader(b) + + c := new(Conf) + if err := c.Read(r); err != nil { + t.Fatal(err) + } + + if c.Get(key).String() != value { + t.Error("Get fails for existing key") + } + + if v, ok := c.Find("key"); !ok || v.String() != value { + t.Error("Find fails for existing key") + } + + if c.GetDefault(key, "none").String() != value { + t.Error("GetDafault fails on existing value") + } + + if c.GetDefault("unknown", value).String() != value { + t.Error("GetDafault fails to supply default") + } +} + +func TestReadReadFile(t *testing.T) { + conf := new(Conf) + if err := conf.ReadFile("./testdata/test.conf"); err != nil { + t.Fatal(err) + } + + f, err := os.Open("./testdata/test.conf") + if err != nil { + t.Fatal(err) + } + defer f.Close() + + conf = new(Conf) + if err := conf.Read(f); err != nil { + t.Fatal(err) + } +} + func TestKeys(t *testing.T) { c := Conf{ values: []*kv{ diff --git a/value.go b/value.go index a9f813a..2606b40 100644 --- a/value.go +++ b/value.go @@ -88,7 +88,7 @@ func parseSlice[T any, S ~string](s S, f func(string) (T, error)) ([]T, error) { for _, str := range split { v, err := parseValue(str, f) if err != nil { - return list, err + return nil, err } list = append(list, v) @@ -109,7 +109,7 @@ func parseValue[T any, S ~string](s S, f func(string) (T, error)) (T, error) { func tidySplit[S ~string](s S, sep string) []string { splitted := strings.Split(string(s), sep) for i, str := range splitted { - splitted[i] = strings.TrimSpace(str) + splitted[i] = trim(str) } return splitted } diff --git a/value_test.go b/value_test.go new file mode 100644 index 0000000..5c9aeeb --- /dev/null +++ b/value_test.go @@ -0,0 +1,291 @@ +package conf + +import ( + "slices" + "testing" +) + +func TestValueMethods(t *testing.T) { + tc := []struct { + name string + f func(t *testing.T) + }{ + { + name: "string", + f: func(t *testing.T) { + s := Value("test").String() + if s != "test" { + t.Fatalf("want: %s, have: %s", "test", s) + } + }, + }, + { + name: "int", + f: func(t *testing.T) { + x, err := Value("10").Int() + if err != nil { + t.Fatal(err) + } + + if x != 10 { + t.Fatalf("want: %v, have: %v", 10, x) + } + }, + }, + { + name: "negative int", + f: func(t *testing.T) { + x, err := Value("-10").Int() + if err != nil { + t.Fatal(err) + } + + if x != -10 { + t.Fatalf("want: %v, have: %v", -10, x) + } + }, + }, + { + name: "bad int", + f: func(t *testing.T) { + x, err := Value("1a").Int() + if err == nil { + t.Fatal("int does not fail on incorrect input") + } + + if x != 0 { + t.Fatalf("want: %v, have: %v", 0, x) + } + }, + }, + { + name: "bad int", + f: func(t *testing.T) { + x, err := Value("NaN").Int() + if err == nil { + t.Fatal("int does not fail on incorrect input") + } + + if x != 0 { + t.Fatalf("want: %v, have: %v", 0, x) + } + }, + }, + { + name: "float64", + f: func(t *testing.T) { + x, err := Value("0.05").Float64() + if err != nil { + t.Fatal(err) + } + + if x != 0.05 { + t.Fatalf("want: %v, have: %v", 0.05, x) + } + }, + }, + { + name: "negative float64", + f: func(t *testing.T) { + x, err := Value("-0.05").Float64() + if err != nil { + t.Fatal(err) + } + + if x != -0.05 { + t.Fatalf("want: %v, have: %v", -0.05, x) + } + }, + }, + { + name: "bad float64", + f: func(t *testing.T) { + x, err := Value("0,05").Float64() + if err == nil { + t.Fatal("float does not fail on incorrect input") + } + + if x != 0 { + t.Fatalf("want: %v, have: %v", 0, x) + } + }, + }, + { + name: "bad float64", + f: func(t *testing.T) { + x, err := Value("0,05").Float64() + if err == nil { + t.Fatal("float does not fail on incorrect input") + } + + if x != 0 { + t.Fatalf("want: %v, have: %v", 0, x) + } + }, + }, + { + name: "bool", + f: func(t *testing.T) { + x, err := Value("t").Bool() + if err != nil { + t.Fatal(err) + } + + if x != true { + t.Fatalf("want: %v, have: %v", true, x) + } + }, + }, + { + name: "bool", + f: func(t *testing.T) { + x, err := Value("true").Bool() + if err != nil { + t.Fatal(err) + } + + if x != true { + t.Fatalf("want: %v, have: %v", true, x) + } + }, + }, + { + name: "bool", + f: func(t *testing.T) { + x, err := Value("T").Bool() + if err != nil { + t.Fatal(err) + } + + if x != true { + t.Fatalf("want: %v, have: %v", true, x) + } + }, + }, + { + name: "bool", + f: func(t *testing.T) { + x, err := Value("True").Bool() + if err != nil { + t.Fatal(err) + } + + if x != true { + t.Fatalf("want: %v, have: %v", true, x) + } + }, + }, + { + name: "bool", + f: func(t *testing.T) { + x, err := Value("TRUE").Bool() + if err != nil { + t.Fatal(err) + } + + if x != true { + t.Fatalf("want: %v, have: %v", true, x) + } + }, + }, + { + name: "bool", + f: func(t *testing.T) { + x, err := Value("unknown").Bool() + if err == nil { + t.Fatal("bool doe not fail on incorrect values") + } + + if x != false { + t.Fatalf("want: %v, have: %v", false, x) + } + }, + }, + { + name: "string slice", + f: func(t *testing.T) { + s := Value("a, b, c").StringSlice() + want := []string{"a", "b", "c"} + if !slices.Equal(s, want) { + t.Fatalf("want: %v, have: %v", want, s) + } + }, + }, + { + name: "int slice", + f: func(t *testing.T) { + x, err := Value("1, 2, 3").IntSlice() + if err != nil { + t.Fatal(err) + } + + want := []int{1, 2, 3} + if !slices.Equal(x, want) { + t.Fatalf("want: %v, have: %v", want, x) + } + }, + }, + { + name: "int slice", + f: func(t *testing.T) { + x, err := Value("1,2, 3").IntSlice() + if err != nil { + t.Fatal(err) + } + + want := []int{1, 2, 3} + if !slices.Equal(x, want) { + t.Fatalf("want: %v, have: %v", want, x) + } + }, + }, + { + name: "bad int slice", + f: func(t *testing.T) { + x, err := Value("1, a, 3").IntSlice() + if err == nil { + t.Fatal("int slice does not fail on incorrect value") + } + + var want []int + if !slices.Equal(x, want) { + t.Fatalf("want: %v, have: %v", want, x) + } + }, + }, + { + name: "float64 slice", + f: func(t *testing.T) { + x, err := Value("0.1, 0.2, 0.3").Float64Slice() + if err != nil { + t.Fatal(err) + } + + want := []float64{0.1, 0.2, 0.3} + if !slices.Equal(x, want) { + t.Fatalf("want: %v, have: %v", want, x) + } + }, + }, + { + name: "bad float64 slice", + f: func(t *testing.T) { + x, err := Value("0.1, a, 0.3").Float64Slice() + if err == nil { + t.Fatal("float slice doe not fail on incorrect value") + } + + var want []float64 + if !slices.Equal(x, want) { + t.Fatalf("want: %v, have: %v", want, x) + } + }, + }, + } + + for _, c := range tc { + t.Run(c.name, func(t *testing.T) { + c.f(t) + }) + } +}