mirror of
https://github.com/ipfs/kubo.git
synced 2025-05-17 15:06:47 +08:00
512 lines
13 KiB
Go
512 lines
13 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestOptionalDuration(t *testing.T) {
|
|
makeDurationPointer := func(d time.Duration) *time.Duration { return &d }
|
|
|
|
t.Run("marshalling and unmarshalling", func(t *testing.T) {
|
|
out, err := json.Marshal(OptionalDuration{value: makeDurationPointer(time.Second)})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "\"1s\""
|
|
if string(out) != expected {
|
|
t.Fatalf("expected %s, got %s", expected, string(out))
|
|
}
|
|
var d OptionalDuration
|
|
|
|
if err := json.Unmarshal(out, &d); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if *d.value != time.Second {
|
|
t.Fatal("expected a second")
|
|
}
|
|
})
|
|
|
|
t.Run("default value", func(t *testing.T) {
|
|
for _, jsonStr := range []string{"null", "\"null\"", "\"\"", "\"default\""} {
|
|
var d OptionalDuration
|
|
if !d.IsDefault() {
|
|
t.Fatal("expected value to be the default initially")
|
|
}
|
|
if err := json.Unmarshal([]byte(jsonStr), &d); err != nil {
|
|
t.Fatalf("%s failed to unmarshall with %s", jsonStr, err)
|
|
}
|
|
if dur := d.WithDefault(time.Hour); dur != time.Hour {
|
|
t.Fatalf("expected default value to be used, got %s", dur)
|
|
}
|
|
if !d.IsDefault() {
|
|
t.Fatal("expected value to be the default")
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("omitempty with default value", func(t *testing.T) {
|
|
type Foo struct {
|
|
D *OptionalDuration `json:",omitempty"`
|
|
}
|
|
// marshall to JSON without empty field
|
|
out, err := json.Marshal(new(Foo))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(out) != "{}" {
|
|
t.Fatalf("expected omitempty to omit the duration, got %s", out)
|
|
}
|
|
// unmarshall missing value and get the default
|
|
var foo2 Foo
|
|
if err := json.Unmarshal(out, &foo2); err != nil {
|
|
t.Fatalf("%s failed to unmarshall with %s", string(out), err)
|
|
}
|
|
if dur := foo2.D.WithDefault(time.Hour); dur != time.Hour {
|
|
t.Fatalf("expected default value to be used, got %s", dur)
|
|
}
|
|
if !foo2.D.IsDefault() {
|
|
t.Fatal("expected value to be the default")
|
|
}
|
|
})
|
|
|
|
t.Run("roundtrip including the default values", func(t *testing.T) {
|
|
for jsonStr, goValue := range map[string]OptionalDuration{
|
|
// there are various footguns user can hit, normalize them to the canonical default
|
|
"null": {}, // JSON null → default value
|
|
"\"null\"": {}, // JSON string "null" sent/set by "ipfs config" cli → default value
|
|
"\"default\"": {}, // explicit "default" as string
|
|
"\"\"": {}, // user removed custom value, empty string should also parse as default
|
|
"\"1s\"": {value: makeDurationPointer(time.Second)},
|
|
"\"42h1m3s\"": {value: makeDurationPointer(42*time.Hour + 1*time.Minute + 3*time.Second)},
|
|
} {
|
|
var d OptionalDuration
|
|
err := json.Unmarshal([]byte(jsonStr), &d)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if goValue.value == nil && d.value == nil {
|
|
} else if goValue.value == nil && d.value != nil {
|
|
t.Errorf("expected nil for %s, got %s", jsonStr, d)
|
|
} else if *d.value != *goValue.value {
|
|
t.Fatalf("expected %s for %s, got %s", goValue, jsonStr, d)
|
|
}
|
|
|
|
// Test Reverse
|
|
out, err := json.Marshal(goValue)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if goValue.value == nil {
|
|
if !bytes.Equal(out, []byte("null")) {
|
|
t.Fatalf("expected JSON null for %s, got %s", jsonStr, string(out))
|
|
}
|
|
continue
|
|
}
|
|
if string(out) != jsonStr {
|
|
t.Fatalf("expected %s, got %s", jsonStr, string(out))
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("invalid duration values", func(t *testing.T) {
|
|
for _, invalid := range []string{
|
|
"\"s\"", "\"1ę\"", "\"-1\"", "\"1H\"", "\"day\"",
|
|
} {
|
|
var d OptionalDuration
|
|
err := json.Unmarshal([]byte(invalid), &d)
|
|
if err == nil {
|
|
t.Errorf("expected to fail to decode %s as an OptionalDuration, got %s instead", invalid, d)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestOneStrings(t *testing.T) {
|
|
out, err := json.Marshal(Strings{"one"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "\"one\""
|
|
if string(out) != expected {
|
|
t.Fatalf("expected %s, got %s", expected, string(out))
|
|
}
|
|
}
|
|
|
|
func TestNoStrings(t *testing.T) {
|
|
out, err := json.Marshal(Strings{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "null"
|
|
if string(out) != expected {
|
|
t.Fatalf("expected %s, got %s", expected, string(out))
|
|
}
|
|
}
|
|
|
|
func TestManyStrings(t *testing.T) {
|
|
out, err := json.Marshal(Strings{"one", "two"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "[\"one\",\"two\"]"
|
|
if string(out) != expected {
|
|
t.Fatalf("expected %s, got %s", expected, string(out))
|
|
}
|
|
}
|
|
|
|
func TestFunkyStrings(t *testing.T) {
|
|
toParse := " [ \"one\", \"two\" ] "
|
|
var s Strings
|
|
if err := json.Unmarshal([]byte(toParse), &s); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(s) != 2 || s[0] != "one" && s[1] != "two" {
|
|
t.Fatalf("unexpected result: %v", s)
|
|
}
|
|
}
|
|
|
|
func TestFlag(t *testing.T) {
|
|
// make sure we have the right zero value.
|
|
var defaultFlag Flag
|
|
if defaultFlag != Default {
|
|
t.Errorf("expected default flag to be %q, got %q", Default, defaultFlag)
|
|
}
|
|
|
|
if defaultFlag.WithDefault(true) != true {
|
|
t.Error("expected default & true to be true")
|
|
}
|
|
|
|
if defaultFlag.WithDefault(false) != false {
|
|
t.Error("expected default & false to be false")
|
|
}
|
|
|
|
if True.WithDefault(false) != true {
|
|
t.Error("default should only apply to default")
|
|
}
|
|
|
|
if False.WithDefault(true) != false {
|
|
t.Error("default should only apply to default")
|
|
}
|
|
|
|
if True.WithDefault(true) != true {
|
|
t.Error("true & true is true")
|
|
}
|
|
|
|
if False.WithDefault(true) != false {
|
|
t.Error("false & false is false")
|
|
}
|
|
|
|
for jsonStr, goValue := range map[string]Flag{
|
|
"null": Default,
|
|
"true": True,
|
|
"false": False,
|
|
} {
|
|
var d Flag
|
|
err := json.Unmarshal([]byte(jsonStr), &d)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if d != goValue {
|
|
t.Fatalf("expected %s, got %s", goValue, d)
|
|
}
|
|
|
|
// Reverse
|
|
out, err := json.Marshal(goValue)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(out) != jsonStr {
|
|
t.Fatalf("expected %s, got %s", jsonStr, string(out))
|
|
}
|
|
}
|
|
|
|
type Foo struct {
|
|
F Flag `json:",omitempty"`
|
|
}
|
|
out, err := json.Marshal(new(Foo))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "{}"
|
|
if string(out) != expected {
|
|
t.Fatal("expected omitempty to omit the flag")
|
|
}
|
|
}
|
|
|
|
func TestPriority(t *testing.T) {
|
|
// make sure we have the right zero value.
|
|
var defaultPriority Priority
|
|
if defaultPriority != DefaultPriority {
|
|
t.Errorf("expected default priority to be %q, got %q", DefaultPriority, defaultPriority)
|
|
}
|
|
|
|
if _, ok := defaultPriority.WithDefault(Disabled); ok {
|
|
t.Error("should have been disabled")
|
|
}
|
|
|
|
if p, ok := defaultPriority.WithDefault(1); !ok || p != 1 {
|
|
t.Errorf("priority should have been 1, got %d", p)
|
|
}
|
|
|
|
if p, ok := defaultPriority.WithDefault(DefaultPriority); !ok || p != 0 {
|
|
t.Errorf("priority should have been 0, got %d", p)
|
|
}
|
|
|
|
for jsonStr, goValue := range map[string]Priority{
|
|
"null": DefaultPriority,
|
|
"false": Disabled,
|
|
"1": 1,
|
|
"2": 2,
|
|
"100": 100,
|
|
} {
|
|
var d Priority
|
|
err := json.Unmarshal([]byte(jsonStr), &d)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if d != goValue {
|
|
t.Fatalf("expected %s, got %s", goValue, d)
|
|
}
|
|
|
|
// Reverse
|
|
out, err := json.Marshal(goValue)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(out) != jsonStr {
|
|
t.Fatalf("expected %s, got %s", jsonStr, string(out))
|
|
}
|
|
}
|
|
|
|
type Foo struct {
|
|
P Priority `json:",omitempty"`
|
|
}
|
|
out, err := json.Marshal(new(Foo))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "{}"
|
|
if string(out) != expected {
|
|
t.Fatal("expected omitempty to omit the flag")
|
|
}
|
|
for _, invalid := range []string{
|
|
"0", "-1", "-2", "1.1", "0.0",
|
|
} {
|
|
var p Priority
|
|
err := json.Unmarshal([]byte(invalid), &p)
|
|
if err == nil {
|
|
t.Errorf("expected to fail to decode %s as a priority", invalid)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOptionalInteger(t *testing.T) {
|
|
makeInt64Pointer := func(v int64) *int64 {
|
|
return &v
|
|
}
|
|
|
|
var defaultOptionalInt OptionalInteger
|
|
if !defaultOptionalInt.IsDefault() {
|
|
t.Fatal("should be the default")
|
|
}
|
|
if val := defaultOptionalInt.WithDefault(0); val != 0 {
|
|
t.Errorf("optional integer should have been 0, got %d", val)
|
|
}
|
|
|
|
if val := defaultOptionalInt.WithDefault(1); val != 1 {
|
|
t.Errorf("optional integer should have been 1, got %d", val)
|
|
}
|
|
|
|
if val := defaultOptionalInt.WithDefault(-1); val != -1 {
|
|
t.Errorf("optional integer should have been -1, got %d", val)
|
|
}
|
|
|
|
var filledInt OptionalInteger
|
|
filledInt = OptionalInteger{value: makeInt64Pointer(1)}
|
|
if filledInt.IsDefault() {
|
|
t.Fatal("should not be the default")
|
|
}
|
|
if val := filledInt.WithDefault(0); val != 1 {
|
|
t.Errorf("optional integer should have been 1, got %d", val)
|
|
}
|
|
|
|
if val := filledInt.WithDefault(-1); val != 1 {
|
|
t.Errorf("optional integer should have been 1, got %d", val)
|
|
}
|
|
|
|
filledInt = OptionalInteger{value: makeInt64Pointer(0)}
|
|
if val := filledInt.WithDefault(1); val != 0 {
|
|
t.Errorf("optional integer should have been 0, got %d", val)
|
|
}
|
|
|
|
for jsonStr, goValue := range map[string]OptionalInteger{
|
|
"null": {},
|
|
"0": {value: makeInt64Pointer(0)},
|
|
"1": {value: makeInt64Pointer(1)},
|
|
"-1": {value: makeInt64Pointer(-1)},
|
|
} {
|
|
var d OptionalInteger
|
|
err := json.Unmarshal([]byte(jsonStr), &d)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if goValue.value == nil && d.value == nil {
|
|
} else if goValue.value == nil && d.value != nil {
|
|
t.Errorf("expected default, got %s", d)
|
|
} else if *d.value != *goValue.value {
|
|
t.Fatalf("expected %s, got %s", goValue, d)
|
|
}
|
|
|
|
// Reverse
|
|
out, err := json.Marshal(goValue)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(out) != jsonStr {
|
|
t.Fatalf("expected %s, got %s", jsonStr, string(out))
|
|
}
|
|
}
|
|
|
|
// marshal with omitempty
|
|
type Foo struct {
|
|
I *OptionalInteger `json:",omitempty"`
|
|
}
|
|
out, err := json.Marshal(new(Foo))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "{}"
|
|
if string(out) != expected {
|
|
t.Fatal("expected omitempty to omit the optional integer")
|
|
}
|
|
|
|
// unmarshal from omitempty output and get default value
|
|
var foo2 Foo
|
|
if err := json.Unmarshal(out, &foo2); err != nil {
|
|
t.Fatalf("%s failed to unmarshall with %s", string(out), err)
|
|
}
|
|
if i := foo2.I.WithDefault(42); i != 42 {
|
|
t.Fatalf("expected default value to be used, got %d", i)
|
|
}
|
|
if !foo2.I.IsDefault() {
|
|
t.Fatal("expected value to be the default")
|
|
}
|
|
|
|
// test invalid values
|
|
for _, invalid := range []string{
|
|
"foo", "-1.1", "1.1", "0.0", "[]",
|
|
} {
|
|
var p OptionalInteger
|
|
err := json.Unmarshal([]byte(invalid), &p)
|
|
if err == nil {
|
|
t.Errorf("expected to fail to decode %s as a priority", invalid)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOptionalString(t *testing.T) {
|
|
makeStringPointer := func(v string) *string {
|
|
return &v
|
|
}
|
|
|
|
var defaultOptionalString OptionalString
|
|
if !defaultOptionalString.IsDefault() {
|
|
t.Fatal("should be the default")
|
|
}
|
|
if val := defaultOptionalString.WithDefault(""); val != "" {
|
|
t.Errorf("optional string should have been empty, got %s", val)
|
|
}
|
|
if val := defaultOptionalString.String(); val != "default" {
|
|
t.Fatalf("default optional string should be the 'default' string, got %s", val)
|
|
}
|
|
if val := defaultOptionalString.WithDefault("foo"); val != "foo" {
|
|
t.Errorf("optional string should have been foo, got %s", val)
|
|
}
|
|
|
|
var filledStr OptionalString
|
|
filledStr = OptionalString{value: makeStringPointer("foo")}
|
|
if filledStr.IsDefault() {
|
|
t.Fatal("should not be the default")
|
|
}
|
|
if val := filledStr.WithDefault("bar"); val != "foo" {
|
|
t.Errorf("optional string should have been foo, got %s", val)
|
|
}
|
|
if val := filledStr.String(); val != "foo" {
|
|
t.Fatalf("optional string should have been foo, got %s", val)
|
|
}
|
|
filledStr = OptionalString{value: makeStringPointer("")}
|
|
if val := filledStr.WithDefault("foo"); val != "" {
|
|
t.Errorf("optional string should have been 0, got %s", val)
|
|
}
|
|
|
|
for jsonStr, goValue := range map[string]OptionalString{
|
|
"null": {},
|
|
"\"0\"": {value: makeStringPointer("0")},
|
|
"\"\"": {value: makeStringPointer("")},
|
|
`"1"`: {value: makeStringPointer("1")},
|
|
`"-1"`: {value: makeStringPointer("-1")},
|
|
`"qwerty"`: {value: makeStringPointer("qwerty")},
|
|
} {
|
|
var d OptionalString
|
|
err := json.Unmarshal([]byte(jsonStr), &d)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if goValue.value == nil && d.value == nil {
|
|
} else if goValue.value == nil && d.value != nil {
|
|
t.Errorf("expected default, got %s", d)
|
|
} else if *d.value != *goValue.value {
|
|
t.Fatalf("expected %s, got %s", goValue, d)
|
|
}
|
|
|
|
// Reverse
|
|
out, err := json.Marshal(goValue)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(out) != jsonStr {
|
|
t.Fatalf("expected %s, got %s", jsonStr, string(out))
|
|
}
|
|
}
|
|
|
|
// marshal with omitempty
|
|
type Foo struct {
|
|
S *OptionalString `json:",omitempty"`
|
|
}
|
|
out, err := json.Marshal(new(Foo))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := "{}"
|
|
if string(out) != expected {
|
|
t.Fatal("expected omitempty to omit the optional integer")
|
|
}
|
|
// unmarshal from omitempty output and get default value
|
|
var foo2 Foo
|
|
if err := json.Unmarshal(out, &foo2); err != nil {
|
|
t.Fatalf("%s failed to unmarshall with %s", string(out), err)
|
|
}
|
|
if s := foo2.S.WithDefault("foo"); s != "foo" {
|
|
t.Fatalf("expected default value to be used, got %s", s)
|
|
}
|
|
if !foo2.S.IsDefault() {
|
|
t.Fatal("expected value to be the default")
|
|
}
|
|
|
|
for _, invalid := range []string{
|
|
"[]", "{}", "0", "a", "'b'",
|
|
} {
|
|
var p OptionalString
|
|
err := json.Unmarshal([]byte(invalid), &p)
|
|
if err == nil {
|
|
t.Errorf("expected to fail to decode %s as an optional string", invalid)
|
|
}
|
|
}
|
|
}
|