refactor: ♻️ change resolvspec types to build in sqltypes
This commit is contained in:
commit
66abc7efd6
9 files changed
+4775
No files matched your search
@@ -0,0 +1,164 @@
|
||||
package sqltypes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// record mimics a typical DB model composed of sqltypes fields, exercising
|
||||
// marshalling/unmarshalling of the whole set together as encoding/json would
|
||||
// when used on a real struct (not just the individual types in isolation).
|
||||
type record struct {
|
||||
ID SqlUUID `json:"id"`
|
||||
Name SqlString `json:"name"`
|
||||
Bio SqlString `json:"bio"`
|
||||
Age SqlInt32 `json:"age"`
|
||||
Score SqlFloat64 `json:"score"`
|
||||
Active SqlBool `json:"active"`
|
||||
CreatedAt SqlTimeStamp `json:"created_at"`
|
||||
BirthDate SqlDate `json:"birth_date"`
|
||||
Avatar SqlByteArray `json:"avatar"`
|
||||
Tags SqlStringArray `json:"tags"`
|
||||
Scores SqlInt32Array `json:"scores"`
|
||||
Metadata SqlJSONB `json:"metadata"`
|
||||
Embedding SqlVector `json:"embedding"`
|
||||
Extras []uuid.UUID `json:"-"`
|
||||
}
|
||||
|
||||
func TestStruct_JSON_RoundTrip_AllFieldsPresent(t *testing.T) {
|
||||
id := uuid.New()
|
||||
createdAt := time.Date(2024, 3, 10, 12, 30, 0, 0, time.UTC)
|
||||
birthDate := time.Date(1990, 5, 20, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
original := record{
|
||||
ID: NewSqlUUID(id),
|
||||
Name: NewSqlString("Ada Lovelace"),
|
||||
Bio: SqlString{}, // intentionally null
|
||||
Age: NewSqlInt32(36),
|
||||
Score: NewSqlFloat64(98.6),
|
||||
Active: NewSqlBool(true),
|
||||
CreatedAt: NewSqlTimeStamp(createdAt),
|
||||
BirthDate: NewSqlDate(birthDate),
|
||||
Avatar: NewSqlByteArray([]byte{0xDE, 0xAD, 0xBE, 0xEF}),
|
||||
Tags: NewSqlStringArray([]string{"engineer", "mathematician"}),
|
||||
Scores: NewSqlInt32Array([]int32{10, 20, 30}),
|
||||
Metadata: SqlJSONB(`{"role":"admin"}`),
|
||||
Embedding: NewSqlVector([]float32{0.1, 0.2, 0.3}),
|
||||
}
|
||||
|
||||
data, err := json.Marshal(original)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal failed: %v", err)
|
||||
}
|
||||
|
||||
var decoded record
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("Unmarshal failed: %v", err)
|
||||
}
|
||||
|
||||
if decoded.ID.UUID() != id {
|
||||
t.Errorf("ID: expected %v, got %v", id, decoded.ID.UUID())
|
||||
}
|
||||
if decoded.Name.String() != "Ada Lovelace" {
|
||||
t.Errorf("Name: expected Ada Lovelace, got %q", decoded.Name.String())
|
||||
}
|
||||
if decoded.Bio.Valid {
|
||||
t.Errorf("Bio: expected invalid/null, got %v", decoded.Bio)
|
||||
}
|
||||
if decoded.Age.Int64() != 36 {
|
||||
t.Errorf("Age: expected 36, got %d", decoded.Age.Int64())
|
||||
}
|
||||
if decoded.Score.Float64() != 98.6 {
|
||||
t.Errorf("Score: expected 98.6, got %v", decoded.Score.Float64())
|
||||
}
|
||||
if !decoded.Active.Bool() {
|
||||
t.Errorf("Active: expected true")
|
||||
}
|
||||
if decoded.CreatedAt.Time().Format("2006-01-02T15:04:05") != createdAt.Format("2006-01-02T15:04:05") {
|
||||
t.Errorf("CreatedAt: expected %v, got %v", createdAt, decoded.CreatedAt.Time())
|
||||
}
|
||||
if decoded.BirthDate.String() != "1990-05-20" {
|
||||
t.Errorf("BirthDate: expected 1990-05-20, got %q", decoded.BirthDate.String())
|
||||
}
|
||||
if string(decoded.Avatar.Val) != string(original.Avatar.Val) {
|
||||
t.Errorf("Avatar: expected %v, got %v", original.Avatar.Val, decoded.Avatar.Val)
|
||||
}
|
||||
if len(decoded.Tags.Val) != 2 || decoded.Tags.Val[0] != "engineer" {
|
||||
t.Errorf("Tags: unexpected value %v", decoded.Tags.Val)
|
||||
}
|
||||
if len(decoded.Scores.Val) != 3 || decoded.Scores.Val[2] != 30 {
|
||||
t.Errorf("Scores: unexpected value %v", decoded.Scores.Val)
|
||||
}
|
||||
m, err := decoded.Metadata.AsMap()
|
||||
if err != nil || m["role"] != "admin" {
|
||||
t.Errorf("Metadata: expected role=admin, got %v (err=%v)", m, err)
|
||||
}
|
||||
if len(decoded.Embedding.Val) != 3 || decoded.Embedding.Val[1] != 0.2 {
|
||||
t.Errorf("Embedding: unexpected value %v", decoded.Embedding.Val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStruct_JSON_RoundTrip_AllNull(t *testing.T) {
|
||||
var original record
|
||||
|
||||
data, err := json.Marshal(original)
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal failed: %v", err)
|
||||
}
|
||||
|
||||
var decoded record
|
||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
||||
t.Fatalf("Unmarshal failed: %v", err)
|
||||
}
|
||||
|
||||
if decoded.ID.Valid || decoded.Name.Valid || decoded.Age.Valid || decoded.Score.Valid ||
|
||||
decoded.Active.Valid || decoded.CreatedAt.Valid || decoded.BirthDate.Valid ||
|
||||
decoded.Avatar.Valid || decoded.Tags.Valid || decoded.Scores.Valid || decoded.Embedding.Valid {
|
||||
t.Errorf("expected all fields invalid/null after round-trip, got %+v", decoded)
|
||||
}
|
||||
if decoded.Metadata != nil {
|
||||
t.Errorf("expected nil Metadata, got %v", decoded.Metadata)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStruct_JSON_UnmarshalFromRawJSON(t *testing.T) {
|
||||
raw := `{
|
||||
"id": "3e843d4e-6b3c-4f2e-9a1e-6f0b2f3c9d10",
|
||||
"name": "Grace Hopper",
|
||||
"bio": null,
|
||||
"age": 85,
|
||||
"score": 100,
|
||||
"active": false,
|
||||
"created_at": "2023-12-01T08:00:00",
|
||||
"birth_date": "1906-12-09",
|
||||
"avatar": "AQIDBA==",
|
||||
"tags": ["navy", "compiler"],
|
||||
"scores": [1, 2, 3],
|
||||
"metadata": {"key": "value"},
|
||||
"embedding": [1.0, 2.0]
|
||||
}`
|
||||
|
||||
var decoded record
|
||||
if err := json.Unmarshal([]byte(raw), &decoded); err != nil {
|
||||
t.Fatalf("Unmarshal failed: %v", err)
|
||||
}
|
||||
|
||||
if decoded.Name.String() != "Grace Hopper" {
|
||||
t.Errorf("expected Grace Hopper, got %q", decoded.Name.String())
|
||||
}
|
||||
if decoded.Age.Int64() != 85 {
|
||||
t.Errorf("expected age 85, got %d", decoded.Age.Int64())
|
||||
}
|
||||
if decoded.Active.Valid && decoded.Active.Bool() {
|
||||
t.Errorf("expected active=false")
|
||||
}
|
||||
if string(decoded.Avatar.Val) != string([]byte{1, 2, 3, 4}) {
|
||||
t.Errorf("expected avatar bytes [1 2 3 4], got %v", decoded.Avatar.Val)
|
||||
}
|
||||
if len(decoded.Tags.Val) != 2 || decoded.Tags.Val[1] != "compiler" {
|
||||
t.Errorf("unexpected tags %v", decoded.Tags.Val)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user