156 lines
4.6 KiB
Go
156 lines
4.6 KiB
Go
// Copyright (C) 2017 Michael J. Fromberger. All Rights Reserved.
|
|
|
|
package jctx
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var bicent = time.Date(1976, 7, 4, 1, 2, 3, 4, time.UTC)
|
|
|
|
func TestEncoding(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
deadline time.Time
|
|
params, want string
|
|
}{
|
|
{"zero-void", time.Time{}, "", `{"jctx":"1"}`},
|
|
|
|
{"zero-payload", time.Time{},
|
|
"[1,2,3]", `{"jctx":"1","payload":[1,2,3]}`},
|
|
|
|
{"bicentennial-void", bicent.In(time.Local),
|
|
"", `{"jctx":"1","deadline":"1976-07-04T01:02:03.000000004Z"}`,
|
|
},
|
|
|
|
{"bicentennial-payload", bicent,
|
|
`{"apple":"pear"}`,
|
|
`{"jctx":"1","deadline":"1976-07-04T01:02:03.000000004Z","payload":{"apple":"pear"}}`,
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
ctx := context.Background()
|
|
if !test.deadline.IsZero() {
|
|
var cancel context.CancelFunc
|
|
ctx, cancel = context.WithDeadline(ctx, test.deadline)
|
|
defer cancel()
|
|
}
|
|
raw, err := Encode(ctx, "dummy", json.RawMessage(test.params))
|
|
if err != nil {
|
|
t.Errorf("Encoding %q failed: %v", test.params, err)
|
|
} else if got := string(raw); got != test.want {
|
|
t.Errorf("Encoding %q: got %#q, want %#q", test.params, got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDecoding(t *testing.T) {
|
|
tests := []struct {
|
|
desc, input string
|
|
deadline time.Time
|
|
want string
|
|
}{
|
|
{"empty context", "", time.Time{}, ""},
|
|
{"empty parameters", `{"jctx":"1"}`, time.Time{}, ""},
|
|
{"non-object input", `[1, 5]`, time.Time{}, `[1, 5]`},
|
|
{"non-context empty object", `{}`, time.Time{}, `{}`},
|
|
{"non-context object", `{"kiss":"me"}`, time.Time{}, `{"kiss":"me"}`},
|
|
{"invalid context", `{"jctx":2, "ok":true}`, time.Time{}, `{"jctx":2, "ok":true}`},
|
|
|
|
{"zero-payload", `{"jctx":"1","payload":["a","b","c"]}`, time.Time{}, `["a","b","c"]`},
|
|
{"zero-payload-naked", `["a", "b", "c"]`, time.Time{}, `["a", "b", "c"]`},
|
|
|
|
{"bicentennial-void", `{"jctx":"1","deadline":"1976-07-04T01:02:03.000000004Z"}`, bicent, ""},
|
|
|
|
{"bicentennial-payload", `{
|
|
"jctx":"1",
|
|
"deadline":"1976-07-04T01:02:03.000000004Z",
|
|
"payload":{"lhs":1,"rhs":2}
|
|
}`, bicent, `{"lhs":1,"rhs":2}`},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
ctx := context.Background()
|
|
gotctx, params, err := Decode(ctx, "dummy", json.RawMessage(test.input))
|
|
if err != nil {
|
|
t.Fatalf("Decode(_, %q): error: %v", test.input, err)
|
|
}
|
|
if !test.deadline.IsZero() {
|
|
dl, ok := gotctx.Deadline()
|
|
if !ok {
|
|
t.Error("Decode: missing expected deadline")
|
|
} else if !dl.Equal(test.deadline) {
|
|
t.Errorf("Decode deadline: got %v, want %v", dl, test.deadline)
|
|
}
|
|
}
|
|
if got := string(params); got != test.want {
|
|
t.Errorf("Decode params: got %#q, want %#q", got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMetadata(t *testing.T) {
|
|
type value struct {
|
|
Name string `json:"name,omitempty"`
|
|
Marbles int `json:"marbles,omitempty"`
|
|
}
|
|
input := value{Name: "Hieronymus Bosch", Marbles: 3}
|
|
|
|
base := context.Background()
|
|
ctx, err := WithMetadata(base, input)
|
|
if err != nil {
|
|
t.Fatalf("WithMetadata(base, %+v) failed: %v", input, err)
|
|
}
|
|
|
|
var output value
|
|
|
|
// The base value does not contain the value.
|
|
if err := UnmarshalMetadata(base, &output); err != ErrNoMetadata {
|
|
t.Logf("Base metadata decoded value: %+v", output)
|
|
t.Errorf("UnmarshalMetadata(base): got error %v, want %v", err, ErrNoMetadata)
|
|
}
|
|
|
|
// The attached context does contain the value (prior to transmission).
|
|
output = value{}
|
|
if err := UnmarshalMetadata(ctx, &output); err != nil {
|
|
t.Errorf("UnmarshalMetadata(ctx): unexpected error: %v", err)
|
|
} else if output != input {
|
|
t.Errorf("UnmarshalMetadata(ctx): got %+v, want %+v", output, input)
|
|
}
|
|
|
|
// Simulate transmission -- encode, then decode.
|
|
var dec context.Context
|
|
if enc, err := Encode(ctx, "dummy", nil); err != nil {
|
|
t.Fatalf("Encoding context failed: %v", err)
|
|
} else {
|
|
t.Logf("Encoded context is: %#q", string(enc))
|
|
if dec, _, err = Decode(base, "dummy", enc); err != nil {
|
|
t.Fatalf("Decoding context failed: %v", err)
|
|
}
|
|
}
|
|
|
|
// The decoded context does contain the value (after receipt).
|
|
output = value{}
|
|
if err := UnmarshalMetadata(dec, &output); err != nil {
|
|
t.Errorf("Metadata(dec): unexpected error: %v", err)
|
|
} else if output != input {
|
|
t.Errorf("Metadata(dec): got %+v, want %+v", output, input)
|
|
}
|
|
|
|
// "Attaching" nil removes the metadata.
|
|
clr, err := WithMetadata(ctx, nil)
|
|
if err != nil {
|
|
t.Fatalf("WithMetadata(ctx, nil): unexpected error: %v", err)
|
|
}
|
|
var bad interface{}
|
|
if err := UnmarshalMetadata(clr, &bad); err != ErrNoMetadata {
|
|
t.Errorf("Metadata(clr): got %+v, %v; want %v", bad, err, ErrNoMetadata)
|
|
}
|
|
}
|