chore: import upstream snapshot with attribution
govulncheck / govulncheck (push) Has been cancelled
Lint / golangci-lint (push) Has been cancelled
Run Tests / Unit Tests (push) Has been cancelled
Run Tests / Etcd Integration Tests (push) Has been cancelled
Harness (E2E) / Harnesses (mock LLM) (push) Has been cancelled
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Has been cancelled
govulncheck / govulncheck (push) Has been cancelled
Lint / golangci-lint (push) Has been cancelled
Run Tests / Unit Tests (push) Has been cancelled
Run Tests / Etcd Integration Tests (push) Has been cancelled
Harness (E2E) / Harnesses (mock LLM) (push) Has been cancelled
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
// TestAnyTypeMarshaling tests that google.protobuf.Any types are properly marshaled with @type field
|
||||
func TestAnyTypeMarshaling(t *testing.T) {
|
||||
marshaler := Marshaler{}
|
||||
|
||||
// Create a StringValue message
|
||||
stringValue := wrapperspb.String("test value")
|
||||
|
||||
// Wrap it in an Any message
|
||||
anyMsg, err := anypb.New(stringValue)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create Any message: %v", err)
|
||||
}
|
||||
|
||||
// Marshal using our JSON marshaler
|
||||
data, err := marshaler.Marshal(anyMsg)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal Any message: %v", err)
|
||||
}
|
||||
|
||||
// Unmarshal into a map to check for @type field
|
||||
var result map[string]interface{}
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
t.Fatalf("Failed to unmarshal JSON: %v", err)
|
||||
}
|
||||
|
||||
// Check that @type field exists
|
||||
typeURL, ok := result["@type"].(string)
|
||||
if !ok {
|
||||
t.Fatalf("@type field not found in JSON output. Got: %v", string(data))
|
||||
}
|
||||
|
||||
// Verify the type URL is correct
|
||||
expectedTypeURL := "type.googleapis.com/google.protobuf.StringValue"
|
||||
if typeURL != expectedTypeURL {
|
||||
t.Errorf("Expected @type to be %s, got %s", expectedTypeURL, typeURL)
|
||||
}
|
||||
|
||||
// Verify the value field exists
|
||||
if _, ok := result["value"]; !ok {
|
||||
t.Errorf("value field not found in JSON output. Got: %v", string(data))
|
||||
}
|
||||
|
||||
t.Logf("Successfully marshaled Any type with @type field: %s", string(data))
|
||||
}
|
||||
|
||||
// TestAnyTypeUnmarshaling tests that JSON with @type field can be unmarshaled into google.protobuf.Any
|
||||
func TestAnyTypeUnmarshaling(t *testing.T) {
|
||||
marshaler := Marshaler{}
|
||||
|
||||
// JSON representation of an Any message with @type field
|
||||
jsonData := []byte(`{
|
||||
"@type": "type.googleapis.com/google.protobuf.StringValue",
|
||||
"value": "test value"
|
||||
}`)
|
||||
|
||||
// Unmarshal into an Any message
|
||||
anyMsg := &anypb.Any{}
|
||||
if err := marshaler.Unmarshal(jsonData, anyMsg); err != nil {
|
||||
t.Fatalf("Failed to unmarshal Any message: %v", err)
|
||||
}
|
||||
|
||||
// Verify the type URL is set
|
||||
expectedTypeURL := "type.googleapis.com/google.protobuf.StringValue"
|
||||
if anyMsg.TypeUrl != expectedTypeURL {
|
||||
t.Errorf("Expected TypeUrl to be %s, got %s", expectedTypeURL, anyMsg.TypeUrl)
|
||||
}
|
||||
|
||||
// Unmarshal the contained message
|
||||
stringValue := &wrapperspb.StringValue{}
|
||||
if err := anyMsg.UnmarshalTo(stringValue); err != nil {
|
||||
t.Fatalf("Failed to unmarshal contained message: %v", err)
|
||||
}
|
||||
|
||||
// Verify the value
|
||||
expectedValue := "test value"
|
||||
if stringValue.Value != expectedValue {
|
||||
t.Errorf("Expected value to be %s, got %s", expectedValue, stringValue.Value)
|
||||
}
|
||||
|
||||
t.Logf("Successfully unmarshaled Any type from JSON with @type field")
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"go-micro.dev/v6/codec"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
// mockReadWriteCloser implements io.ReadWriteCloser for testing
|
||||
type mockReadWriteCloser struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
func (m *mockReadWriteCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TestCodecAnyTypeWrite tests that google.protobuf.Any types are properly written with @type field
|
||||
func TestCodecAnyTypeWrite(t *testing.T) {
|
||||
buf := &mockReadWriteCloser{Buffer: bytes.NewBuffer(nil)}
|
||||
c := NewCodec(buf).(*Codec)
|
||||
|
||||
// Create a StringValue message
|
||||
stringValue := wrapperspb.String("test value")
|
||||
|
||||
// Wrap it in an Any message
|
||||
anyMsg, err := anypb.New(stringValue)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create Any message: %v", err)
|
||||
}
|
||||
|
||||
// Write the message
|
||||
msg := &codec.Message{
|
||||
Type: codec.Response,
|
||||
}
|
||||
if err := c.Write(msg, anyMsg); err != nil {
|
||||
t.Fatalf("Failed to write Any message: %v", err)
|
||||
}
|
||||
|
||||
// Parse the written JSON
|
||||
var result map[string]interface{}
|
||||
if err := json.Unmarshal(buf.Bytes(), &result); err != nil {
|
||||
t.Fatalf("Failed to unmarshal JSON: %v", err)
|
||||
}
|
||||
|
||||
// Check that @type field exists
|
||||
typeURL, ok := result["@type"].(string)
|
||||
if !ok {
|
||||
t.Fatalf("@type field not found in JSON output. Got: %v", buf.String())
|
||||
}
|
||||
|
||||
// Verify the type URL is correct
|
||||
expectedTypeURL := "type.googleapis.com/google.protobuf.StringValue"
|
||||
if typeURL != expectedTypeURL {
|
||||
t.Errorf("Expected @type to be %s, got %s", expectedTypeURL, typeURL)
|
||||
}
|
||||
|
||||
t.Logf("Successfully wrote Any type with @type field: %s", buf.String())
|
||||
}
|
||||
|
||||
// TestCodecAnyTypeRead tests that JSON with @type field can be read into google.protobuf.Any
|
||||
func TestCodecAnyTypeRead(t *testing.T) {
|
||||
// JSON representation of an Any message with @type field
|
||||
jsonData := `{"@type":"type.googleapis.com/google.protobuf.StringValue","value":"test value"}`
|
||||
|
||||
buf := &mockReadWriteCloser{Buffer: bytes.NewBufferString(jsonData + "\n")}
|
||||
c := NewCodec(buf).(*Codec)
|
||||
|
||||
// Read into an Any message
|
||||
anyMsg := &anypb.Any{}
|
||||
if err := c.ReadBody(anyMsg); err != nil {
|
||||
t.Fatalf("Failed to read Any message: %v", err)
|
||||
}
|
||||
|
||||
// Verify the type URL is set
|
||||
expectedTypeURL := "type.googleapis.com/google.protobuf.StringValue"
|
||||
if anyMsg.TypeUrl != expectedTypeURL {
|
||||
t.Errorf("Expected TypeUrl to be %s, got %s", expectedTypeURL, anyMsg.TypeUrl)
|
||||
}
|
||||
|
||||
// Unmarshal the contained message
|
||||
stringValue := &wrapperspb.StringValue{}
|
||||
if err := anyMsg.UnmarshalTo(stringValue); err != nil {
|
||||
t.Fatalf("Failed to unmarshal contained message: %v", err)
|
||||
}
|
||||
|
||||
// Verify the value
|
||||
expectedValue := "test value"
|
||||
if stringValue.Value != expectedValue {
|
||||
t.Errorf("Expected value to be %s, got %s", expectedValue, stringValue.Value)
|
||||
}
|
||||
|
||||
t.Logf("Successfully read Any type from JSON with @type field")
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Package json provides a json codec
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"go-micro.dev/v6/codec"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type Codec struct {
|
||||
Conn io.ReadWriteCloser
|
||||
Encoder *json.Encoder
|
||||
Decoder *json.Decoder
|
||||
}
|
||||
|
||||
func (c *Codec) ReadHeader(m *codec.Message, t codec.MessageType) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Codec) ReadBody(b interface{}) error {
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
if pb, ok := b.(proto.Message); ok {
|
||||
// Read all JSON data from decoder
|
||||
var raw json.RawMessage
|
||||
if err := c.Decoder.Decode(&raw); err != nil {
|
||||
return err
|
||||
}
|
||||
return protojson.Unmarshal(raw, pb)
|
||||
}
|
||||
return c.Decoder.Decode(b)
|
||||
}
|
||||
|
||||
func (c *Codec) Write(m *codec.Message, b interface{}) error {
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
if pb, ok := b.(proto.Message); ok {
|
||||
data, err := protojson.Marshal(pb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write the marshaled data to the encoder
|
||||
var raw json.RawMessage = data
|
||||
return c.Encoder.Encode(raw)
|
||||
}
|
||||
return c.Encoder.Encode(b)
|
||||
}
|
||||
|
||||
func (c *Codec) Close() error {
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
func (c *Codec) String() string {
|
||||
return "json"
|
||||
}
|
||||
|
||||
func NewCodec(c io.ReadWriteCloser) codec.Codec {
|
||||
return &Codec{
|
||||
Conn: c,
|
||||
Decoder: json.NewDecoder(c),
|
||||
Encoder: json.NewEncoder(c),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var protojsonMarshaler = protojson.MarshalOptions{
|
||||
EmitUnpopulated: false,
|
||||
}
|
||||
|
||||
type Marshaler struct{}
|
||||
|
||||
func (j Marshaler) Marshal(v interface{}) ([]byte, error) {
|
||||
if pb, ok := v.(proto.Message); ok {
|
||||
return protojsonMarshaler.Marshal(pb)
|
||||
}
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
func (j Marshaler) Unmarshal(d []byte, v interface{}) error {
|
||||
if pb, ok := v.(proto.Message); ok {
|
||||
return protojson.Unmarshal(d, pb)
|
||||
}
|
||||
return json.Unmarshal(d, v)
|
||||
}
|
||||
|
||||
func (j Marshaler) String() string {
|
||||
return "json"
|
||||
}
|
||||
Reference in New Issue
Block a user