diff --git a/internal/codec/decoder.go b/internal/codec/decoder.go index 9a03a03..730b411 100644 --- a/internal/codec/decoder.go +++ b/internal/codec/decoder.go @@ -59,7 +59,9 @@ type ProtoDecoder struct { func (p *ProtoDecoder) Decode(v any) (err error) { var protoData []byte protoData, err = io.ReadAll(p.reader) - err = proto.Unmarshal(protoData, v.(proto.Message)) + if err == nil { + err = proto.Unmarshal(protoData, v.(proto.Message)) + } return } diff --git a/internal/codec/encoder_test.go b/internal/codec/encoder_test.go index 4fddea2..b9db4a5 100644 --- a/internal/codec/encoder_test.go +++ b/internal/codec/encoder_test.go @@ -82,7 +82,7 @@ state: present encoder := NewEncoder(v.writer, v.format) assert.NotNil(t, encoder) assert.Nil(t, encoder.Encode(v.testuser)) - assert.Equal(t, string(v.expected), string(v.writer.(*bytes.Buffer).Bytes())) + assert.Equal(t, string(v.expected), v.writer.(*bytes.Buffer).String()) assert.Equal(t, v.expected, v.writer.(*bytes.Buffer).Bytes()) assert.Nil(t, encoder.Close()) } diff --git a/internal/schema/schema.go b/internal/schema/schema.go new file mode 100644 index 0000000..62cf9e3 --- /dev/null +++ b/internal/schema/schema.go @@ -0,0 +1,58 @@ +// Copyright 2024 Matthew Rich . All rights reserved. + +package schema + +import ( + "errors" + "fmt" + "github.com/xeipuuv/gojsonschema" + "strings" + "embed" + "net/http" + "log/slog" + "io/fs" +) + +//go:embed schemas/*.schema.json +var schemaFiles embed.FS + +type Schema struct { + schema gojsonschema.JSONLoader +} + +func New(name string, fs fs.FS) *Schema { + path := fmt.Sprintf("file://schemas/%s.schema.json", name) + + return &Schema{schema: gojsonschema.NewReferenceLoaderFileSystem(path, http.FS(fs))} + //return &Schema{schema: gojsonschema.NewReferenceLoader(path)} +} + +func (s *Schema) Validate(source string) error { + // loader := gojsonschema.NewGoLoader(source) + loader := gojsonschema.NewStringLoader(source) + result, err := gojsonschema.Validate(s.schema, loader) + + if err != nil { + slog.Info("schema error", "source", source, "schema", s.schema, "result", result, "err", err) + return err + } + slog.Info("schema.Validate()", "schema", s.schema, "result", result, "err", err) + + if !result.Valid() { + schemaErrors := strings.Builder{} + for _, err := range result.Errors() { + schemaErrors.WriteString(err.String() + "\n") + } + schemaErrors.WriteString(source) + return errors.New(schemaErrors.String()) + } + return nil +} + +func (s *Schema) ValidateSchema() error { + sl := gojsonschema.NewSchemaLoader() + sl.Validate = true + schemaErr := sl.AddSchemas(s.schema) + slog.Info("validate schema definition", "schemaloader", sl, "err", schemaErr) + return schemaErr +} diff --git a/internal/schema/schema_test.go b/internal/schema/schema_test.go new file mode 100644 index 0000000..dc73dd3 --- /dev/null +++ b/internal/schema/schema_test.go @@ -0,0 +1,66 @@ +// Copyright 2024 Matthew Rich . All rights reserved. + +package schema + +import ( + "encoding/json" +_ "fmt" + "github.com/stretchr/testify/assert" +_ "gopkg.in/yaml.v3" +_ "io" +_ "log" +_ "net/http" +_ "net/http/httptest" +_ "net/url" +_ "path/filepath" +_ "strings" + "testing" + "time" +) + +type TestData struct { + Name string `json:"name"` + Len int `json:"len"` + Date time.Time `json:"date"` +} + +func TestNewSchema(t *testing.T) { + s := New("testdata", schemaFiles) + assert.NotNil(t, s) +} + +func TestSchemaValidateJSON(t *testing.T) { + s := New("testdata", schemaFiles) + assert.NotNil(t, s) + +// file, _ := filepath.Abs(filepath.Join(TempDir, "fooread.txt")) + + expectedAtime, atimeErr := time.Parse(time.RFC3339Nano, "2001-12-15T01:01:01.000000001Z") + assert.Nil(t, atimeErr) +// expectedTime := expectedAtime.Local().Format(time.RFC3339Nano) + +/* + declarationAttributes := ` + name: "%s" + date: %s + len: 15 +` + + decl := fmt.Sprintf(declarationAttributes, file, expectedTime) +*/ + + testData := &TestData{ Name: "foo", Len: 20, Date: expectedAtime } + + jsonDoc, jsonErr := json.Marshal(testData) + assert.Nil(t, jsonErr) + + schemaErr := s.Validate(string(jsonDoc)) + assert.Nil(t, schemaErr) +} + +func TestSchemaValidateSchema(t *testing.T) { + s := New("testdata", schemaFiles) + assert.NotNil(t, s) + + assert.Nil(t, s.ValidateSchema()) +} diff --git a/internal/schema/schemas/testdata.schema.json b/internal/schema/schemas/testdata.schema.json new file mode 100644 index 0000000..897b93d --- /dev/null +++ b/internal/schema/schemas/testdata.schema.json @@ -0,0 +1,19 @@ +{ + "$id": "testdata.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "testdata", + "type": "object", + "required": [ "name" ], + "properties": { + "name": { + "type": "string", + "description": "test name" + }, + "len": { + "type": "integer", + "description": "test number", + "minimum": 5 + } + } +} +