package json import ( "bytes" "os" "path/filepath" "strings" "testing" ) type testStruct struct { Name string `json:"name"` Value int `json:"value"` } func TestEncoder(t *testing.T) { t.Run("successful encode", func(t *testing.T) { var buf bytes.Buffer data := testStruct{Name: "test", Value: 42} err := Encoder(&buf, data) if err != nil { t.Fatalf("expected no error, got %v", err) } expected := `{"name":"test","value":42}` result := strings.TrimSpace(buf.String()) if result != expected { t.Errorf("expected %q, got %q", expected, result) } }) t.Run("encode nil", func(t *testing.T) { var buf bytes.Buffer err := Encoder(&buf, nil) if err != nil { t.Fatalf("expected no error encoding nil, got %v", err) } result := strings.TrimSpace(buf.String()) if result != "null" { t.Errorf("expected 'null', got %q", result) } }) t.Run("encode slice", func(t *testing.T) { var buf bytes.Buffer data := []int{1, 2, 3} err := Encoder(&buf, data) if err != nil { t.Fatalf("expected no error, got %v", err) } expected := `[1,2,3]` result := strings.TrimSpace(buf.String()) if result != expected { t.Errorf("expected %q, got %q", expected, result) } }) t.Run("encode map", func(t *testing.T) { var buf bytes.Buffer data := map[string]string{"key": "value"} err := Encoder(&buf, data) if err != nil { t.Fatalf("expected no error, got %v", err) } expected := `{"key":"value"}` result := strings.TrimSpace(buf.String()) if result != expected { t.Errorf("expected %q, got %q", expected, result) } }) } func TestDecoder(t *testing.T) { t.Run("successful decode", func(t *testing.T) { input := `{"name":"test","value":42}` reader := strings.NewReader(input) var result testStruct err := Decoder(reader, &result) if err != nil { t.Fatalf("expected no error, got %v", err) } if result.Name != "test" { t.Errorf("expected name 'test', got %q", result.Name) } if result.Value != 42 { t.Errorf("expected value 42, got %d", result.Value) } }) t.Run("decode empty object", func(t *testing.T) { input := `{}` reader := strings.NewReader(input) var result testStruct err := Decoder(reader, &result) if err != nil { t.Fatalf("expected no error, got %v", err) } if result.Name != "" { t.Errorf("expected empty name, got %q", result.Name) } if result.Value != 0 { t.Errorf("expected zero value, got %d", result.Value) } }) t.Run("decode array", func(t *testing.T) { input := `[1,2,3]` reader := strings.NewReader(input) var result []int err := Decoder(reader, &result) if err != nil { t.Fatalf("expected no error, got %v", err) } if len(result) != 3 { t.Fatalf("expected 3 elements, got %d", len(result)) } for i, expected := range []int{1, 2, 3} { if result[i] != expected { t.Errorf("element %d: expected %d, got %d", i, expected, result[i]) } } }) t.Run("decode invalid JSON", func(t *testing.T) { input := `{invalid json}` reader := strings.NewReader(input) var result testStruct err := Decoder(reader, &result) if err == nil { t.Fatal("expected error for invalid JSON, got nil") } }) t.Run("decode empty input", func(t *testing.T) { reader := strings.NewReader("") var result testStruct err := Decoder(reader, &result) if err == nil { t.Fatal("expected error for empty input, got nil") } }) } func TestUnknown(t *testing.T) { t.Run("unmarshal object", func(t *testing.T) { data := []byte(`{"key":"value"}`) var u Unknown err := u.UnmarshalJSON(data) if err != nil { t.Fatalf("expected no error, got %v", err) } if u.Object == nil { t.Fatal("expected Object to be set") } if u.Array != nil { t.Error("expected Array to be nil") } obj := *u.Object if obj["key"] != "value" { t.Errorf("expected key='value', got %v", obj["key"]) } }) t.Run("unmarshal array", func(t *testing.T) { data := []byte(`[1,2,3]`) var u Unknown err := u.UnmarshalJSON(data) if err != nil { t.Fatalf("expected no error, got %v", err) } if u.Array == nil { t.Fatal("expected Array to be set") } if u.Object != nil { t.Error("expected Object to be nil") } arr := *u.Array if len(arr) != 3 { t.Errorf("expected 3 elements, got %d", len(arr)) } }) t.Run("resolve object", func(t *testing.T) { obj := Object{"test": "value"} u := Unknown{Object: &obj} result := u.Resolve() if result == nil { t.Fatal("expected non-nil result") } resolved, ok := result.(*Object) if !ok { t.Fatal("expected result to be *Object") } if (*resolved)["test"] != "value" { t.Error("unexpected resolved value") } }) t.Run("resolve array", func(t *testing.T) { arr := Array{1, 2, 3} u := Unknown{Array: &arr} result := u.Resolve() if result == nil { t.Fatal("expected non-nil result") } resolved, ok := result.(*Array) if !ok { t.Fatal("expected result to be *Array") } if len(*resolved) != 3 { t.Error("unexpected resolved length") } }) t.Run("resolve uninitialized panics", func(t *testing.T) { u := Unknown{} defer func() { if r := recover(); r == nil { t.Fatal("expected panic for uninitialized Unknown") } }() u.Resolve() }) } func TestLoadJSONFromReader(t *testing.T) { t.Run("successful load", func(t *testing.T) { input := `{"name":"test","value":42}` reader := strings.NewReader(input) data, err := LoadJSONFromReader(reader) if err != nil { t.Fatalf("expected no error, got %v", err) } if string(data) != input { t.Errorf("expected %q, got %q", input, string(data)) } }) t.Run("empty input", func(t *testing.T) { reader := strings.NewReader("") data, err := LoadJSONFromReader(reader) if err != nil { t.Fatalf("expected no error, got %v", err) } if len(data) != 0 { t.Errorf("expected empty data, got %d bytes", len(data)) } }) } func TestLoadJSONFromFile(t *testing.T) { t.Run("successful load", func(t *testing.T) { tmpDir := t.TempDir() filePath := filepath.Join(tmpDir, "test.json") content := `{"name":"test","value":42}` err := os.WriteFile(filePath, []byte(content), 0644) if err != nil { t.Fatalf("failed to create test file: %v", err) } file, err := os.Open(filePath) if err != nil { t.Fatalf("failed to open test file: %v", err) } data, err := LoadJSONFromFile(file) if err != nil { t.Fatalf("expected no error, got %v", err) } if string(data) != content { t.Errorf("expected %q, got %q", content, string(data)) } }) t.Run("empty file", func(t *testing.T) { tmpDir := t.TempDir() filePath := filepath.Join(tmpDir, "empty.json") err := os.WriteFile(filePath, []byte(""), 0644) if err != nil { t.Fatalf("failed to create test file: %v", err) } file, err := os.Open(filePath) if err != nil { t.Fatalf("failed to open test file: %v", err) } data, err := LoadJSONFromFile(file) if err != nil { t.Fatalf("expected no error, got %v", err) } if len(data) != 0 { t.Errorf("expected empty data, got %d bytes", len(data)) } }) } func TestLoadJSONFromFileToType(t *testing.T) { t.Run("successful load and unmarshal", func(t *testing.T) { tmpDir := t.TempDir() filePath := filepath.Join(tmpDir, "test.json") content := `{"name":"test","value":42}` err := os.WriteFile(filePath, []byte(content), 0644) if err != nil { t.Fatalf("failed to create test file: %v", err) } file, err := os.Open(filePath) if err != nil { t.Fatalf("failed to open test file: %v", err) } var result testStruct err = LoadJSONFromFileToType(file, &result) if err != nil { t.Fatalf("expected no error, got %v", err) } if result.Name != "test" { t.Errorf("expected name 'test', got %q", result.Name) } if result.Value != 42 { t.Errorf("expected value 42, got %d", result.Value) } }) t.Run("invalid JSON", func(t *testing.T) { tmpDir := t.TempDir() filePath := filepath.Join(tmpDir, "invalid.json") content := `{invalid json}` err := os.WriteFile(filePath, []byte(content), 0644) if err != nil { t.Fatalf("failed to create test file: %v", err) } file, err := os.Open(filePath) if err != nil { t.Fatalf("failed to open test file: %v", err) } var result testStruct err = LoadJSONFromFileToType(file, &result) if err == nil { t.Fatal("expected error for invalid JSON, got nil") } }) t.Run("empty file", func(t *testing.T) { tmpDir := t.TempDir() filePath := filepath.Join(tmpDir, "empty.json") err := os.WriteFile(filePath, []byte(""), 0644) if err != nil { t.Fatalf("failed to create test file: %v", err) } file, err := os.Open(filePath) if err != nil { t.Fatalf("failed to open test file: %v", err) } var result testStruct err = LoadJSONFromFileToType(file, &result) if err == nil { t.Fatal("expected error for empty JSON, got nil") } }) }