mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
Some checks are pending
CodeQL / codeql (push) Waiting to run
Docker Check / lint (push) Waiting to run
Docker Check / build (push) Waiting to run
Gateway Conformance / gateway-conformance (push) Waiting to run
Gateway Conformance / gateway-conformance-libp2p-experiment (push) Waiting to run
Go Build / go-build (push) Waiting to run
Go Check / go-check (push) Waiting to run
Go Lint / go-lint (push) Waiting to run
Go Test / go-test (push) Waiting to run
Interop / interop-prep (push) Waiting to run
Interop / helia-interop (push) Blocked by required conditions
Interop / ipfs-webui (push) Blocked by required conditions
Sharness / sharness-test (push) Waiting to run
Spell Check / spellcheck (push) Waiting to run
adds Gateway.MaxRangeRequestFileSize configuration to protect against CDN bugs where range requests over certain sizes return entire files instead of requested byte ranges, causing unexpected bandwidth costs. - default: 0 (no limit) - returns 501 Not Implemented for oversized range requests - protects against CDNs like Cloudflare that ignore range requests over 5GiB also introduces OptionalBytes type to reduce code duplication when handling byte-size configuration values, replacing manual string parsing with humanize.ParseBytes. migrates existing byte-size configs to use this new type. Fixes: https://github.com/ipfs/boxo/issues/856
637 lines
16 KiB
Go
637 lines
16 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOptionalBytes(t *testing.T) {
|
|
makeStringPointer := func(v string) *string { return &v }
|
|
|
|
t.Run("default value", func(t *testing.T) {
|
|
var b OptionalBytes
|
|
assert.True(t, b.IsDefault())
|
|
assert.Equal(t, uint64(0), b.WithDefault(0))
|
|
assert.Equal(t, uint64(1024), b.WithDefault(1024))
|
|
assert.Equal(t, "default", b.String())
|
|
})
|
|
|
|
t.Run("non-default value", func(t *testing.T) {
|
|
b := OptionalBytes{OptionalString{value: makeStringPointer("1MiB")}}
|
|
assert.False(t, b.IsDefault())
|
|
assert.Equal(t, uint64(1048576), b.WithDefault(512))
|
|
assert.Equal(t, "1MiB", b.String())
|
|
})
|
|
|
|
t.Run("JSON roundtrip", func(t *testing.T) {
|
|
testCases := []struct {
|
|
jsonInput string
|
|
jsonOutput string
|
|
expectedValue string
|
|
}{
|
|
{"null", "null", ""},
|
|
{"\"256KiB\"", "\"256KiB\"", "256KiB"},
|
|
{"\"1MiB\"", "\"1MiB\"", "1MiB"},
|
|
{"\"5GiB\"", "\"5GiB\"", "5GiB"},
|
|
{"\"256KB\"", "\"256KB\"", "256KB"},
|
|
{"1048576", "\"1048576\"", "1048576"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.jsonInput, func(t *testing.T) {
|
|
var b OptionalBytes
|
|
err := json.Unmarshal([]byte(tc.jsonInput), &b)
|
|
require.NoError(t, err)
|
|
|
|
if tc.expectedValue == "" {
|
|
assert.Nil(t, b.value)
|
|
} else {
|
|
require.NotNil(t, b.value)
|
|
assert.Equal(t, tc.expectedValue, *b.value)
|
|
}
|
|
|
|
out, err := json.Marshal(b)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tc.jsonOutput, string(out))
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("parsing byte sizes", func(t *testing.T) {
|
|
testCases := []struct {
|
|
input string
|
|
expected uint64
|
|
}{
|
|
{"256KiB", 262144},
|
|
{"1MiB", 1048576},
|
|
{"5GiB", 5368709120},
|
|
{"256KB", 256000},
|
|
{"1048576", 1048576},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.input, func(t *testing.T) {
|
|
var b OptionalBytes
|
|
err := json.Unmarshal([]byte("\""+tc.input+"\""), &b)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tc.expected, b.WithDefault(0))
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("omitempty", func(t *testing.T) {
|
|
type Foo struct {
|
|
B *OptionalBytes `json:",omitempty"`
|
|
}
|
|
|
|
out, err := json.Marshal(new(Foo))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "{}", string(out))
|
|
|
|
var foo2 Foo
|
|
err = json.Unmarshal(out, &foo2)
|
|
require.NoError(t, err)
|
|
|
|
if foo2.B != nil {
|
|
assert.Equal(t, uint64(1024), foo2.B.WithDefault(1024))
|
|
assert.True(t, foo2.B.IsDefault())
|
|
} else {
|
|
// When field is omitted, pointer is nil which is also considered default
|
|
t.Log("B is nil, which is acceptable for omitempty")
|
|
}
|
|
})
|
|
|
|
t.Run("invalid values", func(t *testing.T) {
|
|
invalidInputs := []string{
|
|
"\"5XiB\"", "\"invalid\"", "\"\"", "[]", "{}",
|
|
}
|
|
|
|
for _, invalid := range invalidInputs {
|
|
t.Run(invalid, func(t *testing.T) {
|
|
var b OptionalBytes
|
|
err := json.Unmarshal([]byte(invalid), &b)
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("panic on invalid stored value", func(t *testing.T) {
|
|
// This tests that if somehow an invalid value gets stored
|
|
// (bypassing UnmarshalJSON validation), WithDefault will panic
|
|
invalidValue := "invalid-size"
|
|
b := OptionalBytes{OptionalString{value: &invalidValue}}
|
|
|
|
assert.Panics(t, func() {
|
|
b.WithDefault(1024)
|
|
}, "should panic on invalid stored value")
|
|
})
|
|
}
|