fix: resolved comments
This commit is contained in:
10
.gitignore
vendored
10
.gitignore
vendored
@@ -129,3 +129,13 @@ dist
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# Ignore compiled shared object files
|
||||
*.so
|
||||
|
||||
# Ignore coverage output files
|
||||
coverage.out
|
||||
coverage.html
|
||||
|
||||
# Ignore the schema directory used for testing
|
||||
/schemas/
|
||||
20
go.mod
20
go.mod
@@ -1,12 +1,14 @@
|
||||
module github.com/beckn/beckn-onix
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.7
|
||||
|
||||
require golang.org/x/crypto v0.36.0
|
||||
go 1.24.1
|
||||
|
||||
require (
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
|
||||
golang.org/x/crypto v0.36.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
@@ -37,15 +39,9 @@ require (
|
||||
golang.org/x/oauth2 v0.28.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
google.golang.org/api v0.224.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e // indirect
|
||||
google.golang.org/grpc v1.71.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
)
|
||||
|
||||
require golang.org/x/sys v0.31.0 // indirect
|
||||
require (
|
||||
cloud.google.com/go/pubsub v1.48.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
|
||||
32
go.sum
32
go.sum
@@ -1,3 +1,9 @@
|
||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||
github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 h1:m1h+vudopHsI67FPT9MOncyndWhTcdUoBtI1R1uajGY=
|
||||
github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03/go.mod h1:8sheVFH84v3PCyFY/O02mIgSQY9I6wMYPWsq7mDnEZY=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.119.0 h1:tw7OjErMzJKbbjaEHkrt60KQrK5Wus/boCZ7tm5/RNE=
|
||||
cloud.google.com/go v0.119.0/go.mod h1:fwB8QLzTcNevxqi8dcpR+hoMIs3jBherGS9VUBDAW08=
|
||||
@@ -87,34 +93,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
|
||||
@@ -94,7 +94,8 @@ func TestBadReqErr_BecknError(t *testing.T) {
|
||||
|
||||
expectedMsg := "BAD Request: invalid input"
|
||||
if beErr.Message != expectedMsg {
|
||||
t.Errorf("expected %s, got %s", expectedMsg, beErr.Message)
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
beErr.Message, expectedMsg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +103,8 @@ func TestNewBadReqErrf(t *testing.T) {
|
||||
badReqErr := NewBadReqErrf("invalid field %s", "name")
|
||||
expected := "invalid field name"
|
||||
if badReqErr.Error() != expected {
|
||||
t.Errorf("expected %s, got %s", expected, badReqErr.Error())
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
badReqErr, expected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +113,10 @@ func TestNewBadReqErr(t *testing.T) {
|
||||
badReqErr := NewBadReqErr(err)
|
||||
|
||||
if badReqErr.Error() != err.Error() {
|
||||
t.Errorf("expected %s, got %s", err.Error(), badReqErr.Error())
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
badReqErr.Error(), err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNotFoundErr_BecknError(t *testing.T) {
|
||||
@@ -121,7 +125,8 @@ func TestNotFoundErr_BecknError(t *testing.T) {
|
||||
|
||||
expectedMsg := "Endpoint not found: resource not found"
|
||||
if beErr.Message != expectedMsg {
|
||||
t.Errorf("expected %s, got %s", expectedMsg, beErr.Message)
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
beErr.Message, expectedMsg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +134,8 @@ func TestNewNotFoundErrf(t *testing.T) {
|
||||
notFoundErr := NewNotFoundErrf("resource %s not found", "user")
|
||||
expected := "resource user not found"
|
||||
if notFoundErr.Error() != expected {
|
||||
t.Errorf("expected %s, got %s", expected, notFoundErr.Error())
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
notFoundErr.Error(), expected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +144,8 @@ func TestNewNotFoundErr(t *testing.T) {
|
||||
notFoundErr := NewNotFoundErr(err)
|
||||
|
||||
if notFoundErr.Error() != err.Error() {
|
||||
t.Errorf("expected %s, got %s", err.Error(), notFoundErr.Error())
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
notFoundErr.Error(), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
16
pkg/plugin/definition/schemaValidator.go
Normal file
16
pkg/plugin/definition/schemaValidator.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package definition
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// SchemaValidator interface for schema validation.
|
||||
type SchemaValidator interface {
|
||||
Validate(ctx context.Context, url *url.URL, payload []byte) error
|
||||
}
|
||||
|
||||
// SchemaValidatorProvider interface for creating validators.
|
||||
type SchemaValidatorProvider interface {
|
||||
New(ctx context.Context, config map[string]string) (SchemaValidator, func() error, error)
|
||||
}
|
||||
33
pkg/plugin/implementation/schemaValidator/cmd/plugin.go
Normal file
33
pkg/plugin/implementation/schemaValidator/cmd/plugin.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
definition "github.com/beckn/beckn-onix/pkg/plugin/definition"
|
||||
schemaValidator "github.com/beckn/beckn-onix/pkg/plugin/implementation/schemaValidator"
|
||||
)
|
||||
|
||||
// schemaValidatorProvider provides instances of schemaValidator.
|
||||
type schemaValidatorProvider struct{}
|
||||
|
||||
// New initializes a new Verifier instance.
|
||||
func (vp schemaValidatorProvider) New(ctx context.Context, config map[string]string) (definition.SchemaValidator, func() error, error) {
|
||||
if ctx == nil {
|
||||
return nil, nil, errors.New("context cannot be nil")
|
||||
}
|
||||
|
||||
// Extract schemaDir from the config map
|
||||
schemaDir, ok := config["schemaDir"]
|
||||
if !ok || schemaDir == "" {
|
||||
return nil, nil, errors.New("config must contain 'schemaDir'")
|
||||
}
|
||||
|
||||
// Create a new schemaValidator instance with the provided configuration
|
||||
return schemaValidator.New(ctx, &schemaValidator.Config{
|
||||
SchemaDir: schemaDir,
|
||||
})
|
||||
}
|
||||
|
||||
// Provider is the exported symbol that the plugin manager will look for.
|
||||
var Provider definition.SchemaValidatorProvider = schemaValidatorProvider{}
|
||||
150
pkg/plugin/implementation/schemaValidator/cmd/plugin_test.go
Normal file
150
pkg/plugin/implementation/schemaValidator/cmd/plugin_test.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// setupTestSchema creates a temporary directory and writes a sample schema file.
|
||||
func setupTestSchema(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
// Create a temporary directory for the schema
|
||||
schemaDir, err := os.MkdirTemp("", "schemas")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
|
||||
// Create the directory structure for the schema file
|
||||
schemaFilePath := filepath.Join(schemaDir, "example", "1.0", "test_schema.json")
|
||||
if err := os.MkdirAll(filepath.Dir(schemaFilePath), 0755); err != nil {
|
||||
t.Fatalf("Failed to create schema directory structure: %v", err)
|
||||
}
|
||||
|
||||
// Define a sample schema
|
||||
schemaContent := `{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"domain": {"type": "string"},
|
||||
"version": {"type": "string"}
|
||||
},
|
||||
"required": ["domain", "version"]
|
||||
}
|
||||
},
|
||||
"required": ["context"]
|
||||
}`
|
||||
|
||||
// Write the schema to the file
|
||||
if err := os.WriteFile(schemaFilePath, []byte(schemaContent), 0644); err != nil {
|
||||
t.Fatalf("Failed to write schema file: %v", err)
|
||||
}
|
||||
|
||||
return schemaDir
|
||||
}
|
||||
|
||||
// TestValidatorProviderSuccess tests successful ValidatorProvider implementation.
|
||||
func TestValidatorProviderSuccess(t *testing.T) {
|
||||
schemaDir := setupTestSchema(t)
|
||||
defer os.RemoveAll(schemaDir)
|
||||
|
||||
// Define test cases.
|
||||
tests := []struct {
|
||||
name string
|
||||
ctx context.Context
|
||||
config map[string]string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "Valid schema directory",
|
||||
ctx: context.Background(), // Valid context
|
||||
config: map[string]string{"schemaDir": schemaDir},
|
||||
expectedError: "",
|
||||
},
|
||||
}
|
||||
|
||||
// Test using table-driven tests
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
vp := schemaValidatorProvider{}
|
||||
schemaValidator, _, err := vp.New(tt.ctx, tt.config)
|
||||
|
||||
// Ensure no error occurred
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure the schemaValidator is not nil
|
||||
if schemaValidator == nil {
|
||||
t.Error("expected a non-nil schemaValidator, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidatorProviderSuccess tests cases where ValidatorProvider creation should fail.
|
||||
func TestValidatorProviderFailure(t *testing.T) {
|
||||
schemaDir := setupTestSchema(t)
|
||||
defer os.RemoveAll(schemaDir)
|
||||
|
||||
// Define test cases.
|
||||
tests := []struct {
|
||||
name string
|
||||
ctx context.Context
|
||||
config map[string]string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "Config is empty",
|
||||
ctx: context.Background(),
|
||||
config: map[string]string{},
|
||||
expectedError: "config must contain 'schemaDir'",
|
||||
},
|
||||
{
|
||||
name: "schemaDir is empty",
|
||||
ctx: context.Background(),
|
||||
config: map[string]string{"schemaDir": ""},
|
||||
expectedError: "config must contain 'schemaDir'",
|
||||
},
|
||||
{
|
||||
name: "Invalid schema directory",
|
||||
ctx: context.Background(), // Valid context
|
||||
config: map[string]string{"schemaDir": "/invalid/dir"},
|
||||
expectedError: "failed to initialise schemaValidator: schema directory does not exist: /invalid/dir",
|
||||
},
|
||||
{
|
||||
name: "Nil context",
|
||||
ctx: nil, // Nil context
|
||||
config: map[string]string{"schemaDir": schemaDir},
|
||||
expectedError: "context cannot be nil",
|
||||
},
|
||||
}
|
||||
|
||||
// Test using table-driven tests
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
vp := schemaValidatorProvider{}
|
||||
_, _, err := vp.New(tt.ctx, tt.config)
|
||||
|
||||
// Check for expected error
|
||||
if tt.expectedError != "" {
|
||||
if err == nil || !strings.Contains(err.Error(), tt.expectedError) {
|
||||
t.Errorf("expected error %q, got %v", tt.expectedError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure no error occurred
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
197
pkg/plugin/implementation/schemaValidator/schemaValidator.go
Normal file
197
pkg/plugin/implementation/schemaValidator/schemaValidator.go
Normal file
@@ -0,0 +1,197 @@
|
||||
package schemaValidator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
response "github.com/beckn/beckn-onix/pkg/response"
|
||||
|
||||
"github.com/santhosh-tekuri/jsonschema/v6"
|
||||
)
|
||||
|
||||
// Payload represents the structure of the data payload with context information.
|
||||
type payload struct {
|
||||
Context struct {
|
||||
Domain string `json:"domain"`
|
||||
Version string `json:"version"`
|
||||
} `json:"context"`
|
||||
}
|
||||
|
||||
// SchemaValidator implements the Validator interface.
|
||||
type SchemaValidator struct {
|
||||
config *Config
|
||||
schemaCache map[string]*jsonschema.Schema
|
||||
}
|
||||
|
||||
// Config struct for SchemaValidator.
|
||||
type Config struct {
|
||||
SchemaDir string
|
||||
}
|
||||
|
||||
// New creates a new ValidatorProvider instance.
|
||||
func New(ctx context.Context, config *Config) (*SchemaValidator, func() error, error) {
|
||||
// Check if config is nil
|
||||
if config == nil {
|
||||
return nil, nil, fmt.Errorf("config cannot be nil")
|
||||
}
|
||||
v := &SchemaValidator{
|
||||
config: config,
|
||||
schemaCache: make(map[string]*jsonschema.Schema),
|
||||
}
|
||||
|
||||
// Call Initialise function to load schemas and get validators
|
||||
if err := v.initialise(); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to initialise schemaValidator: %v", err)
|
||||
}
|
||||
return v, nil, nil
|
||||
}
|
||||
|
||||
// Validate validates the given data against the schema.
|
||||
func (v *SchemaValidator) Validate(ctx context.Context, url *url.URL, data []byte) error {
|
||||
var payloadData payload
|
||||
err := json.Unmarshal(data, &payloadData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse JSON payload: %v", err)
|
||||
}
|
||||
|
||||
// Extract domain, version, and endpoint from the payload and uri.
|
||||
cxt_domain := payloadData.Context.Domain
|
||||
version := payloadData.Context.Version
|
||||
version = fmt.Sprintf("v%s", version)
|
||||
|
||||
endpoint := path.Base(url.String())
|
||||
// ToDo Add debug log here
|
||||
fmt.Println("Handling request for endpoint:", endpoint)
|
||||
domain := strings.ToLower(cxt_domain)
|
||||
domain = strings.ReplaceAll(domain, ":", "_")
|
||||
|
||||
// Construct the schema file name.
|
||||
schemaFileName := fmt.Sprintf("%s_%s_%s", domain, version, endpoint)
|
||||
|
||||
// Retrieve the schema from the cache.
|
||||
schema, exists := v.schemaCache[schemaFileName]
|
||||
if !exists {
|
||||
return fmt.Errorf("schema not found for domain: %s", schemaFileName)
|
||||
}
|
||||
|
||||
var jsonData any
|
||||
if err := json.Unmarshal(data, &jsonData); err != nil {
|
||||
return fmt.Errorf("failed to parse JSON data: %v", err)
|
||||
}
|
||||
err = schema.Validate(jsonData)
|
||||
if err != nil {
|
||||
// Handle schema validation errors
|
||||
if validationErr, ok := err.(*jsonschema.ValidationError); ok {
|
||||
// Convert validation errors into an array of SchemaValError
|
||||
var schemaErrors []response.Error
|
||||
for _, cause := range validationErr.Causes {
|
||||
// Extract the path and message from the validation error
|
||||
path := strings.Join(cause.InstanceLocation, ".") // JSON path to the invalid field
|
||||
message := cause.Error() // Validation error message
|
||||
|
||||
// Append the error to the schemaErrors array
|
||||
schemaErrors = append(schemaErrors, response.Error{
|
||||
Paths: path,
|
||||
Message: message,
|
||||
})
|
||||
}
|
||||
// Return the array of schema validation errors
|
||||
return &response.SchemaValidationErr{Errors: schemaErrors}
|
||||
}
|
||||
// Return a generic error for non-validation errors
|
||||
return fmt.Errorf("validation failed: %v", err)
|
||||
}
|
||||
|
||||
// Return nil if validation succeeds
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidatorProvider provides instances of Validator.
|
||||
type ValidatorProvider struct{}
|
||||
|
||||
// Initialise initialises the validator provider by compiling all the JSON schema files
|
||||
// from the specified directory and storing them in a cache indexed by their schema filenames.
|
||||
func (v *SchemaValidator) initialise() error {
|
||||
schemaDir := v.config.SchemaDir
|
||||
// Check if the directory exists and is accessible.
|
||||
info, err := os.Stat(schemaDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("schema directory does not exist: %s", schemaDir)
|
||||
}
|
||||
return fmt.Errorf("failed to access schema directory: %v", err)
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("provided schema path is not a directory: %s", schemaDir)
|
||||
}
|
||||
|
||||
compiler := jsonschema.NewCompiler()
|
||||
|
||||
// Helper function to process directories recursively.
|
||||
var processDir func(dir string) error
|
||||
processDir = func(dir string) error {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read directory: %v", err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
path := filepath.Join(dir, entry.Name())
|
||||
if entry.IsDir() {
|
||||
// Recursively process subdirectories.
|
||||
if err := processDir(path); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if filepath.Ext(entry.Name()) == ".json" {
|
||||
// Process JSON files.
|
||||
compiledSchema, err := compiler.Compile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compile JSON schema from file %s: %v", entry.Name(), err)
|
||||
}
|
||||
|
||||
// Use relative path from schemaDir to avoid absolute paths and make schema keys domain/version specific.
|
||||
relativePath, err := filepath.Rel(schemaDir, path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get relative path for file %s: %v", entry.Name(), err)
|
||||
}
|
||||
// Split the relative path to get domain, version, and schema.
|
||||
parts := strings.Split(relativePath, string(os.PathSeparator))
|
||||
|
||||
// Ensure that the file path has at least 3 parts: domain, version, and schema file.
|
||||
if len(parts) < 3 {
|
||||
return fmt.Errorf("invalid schema file structure, expected domain/version/schema.json but got: %s", relativePath)
|
||||
}
|
||||
|
||||
// Extract domain, version, and schema filename from the parts.
|
||||
// Validate that the extracted parts are non-empty.
|
||||
domain := strings.TrimSpace(parts[0])
|
||||
version := strings.TrimSpace(parts[1])
|
||||
schemaFileName := strings.TrimSpace(parts[2])
|
||||
schemaFileName = strings.TrimSuffix(schemaFileName, ".json")
|
||||
|
||||
if domain == "" || version == "" || schemaFileName == "" {
|
||||
return fmt.Errorf("invalid schema file structure, one or more components are empty. Relative path: %s", relativePath)
|
||||
}
|
||||
|
||||
// Construct a unique key combining domain, version, and schema name (e.g., ondc_trv10_v2.0.0_schema).
|
||||
uniqueKey := fmt.Sprintf("%s_%s_%s", domain, version, schemaFileName)
|
||||
// Store the compiled schema in the SchemaCache using the unique key.
|
||||
v.schemaCache[uniqueKey] = compiledSchema
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start processing from the root schema directory.
|
||||
if err := processDir(schemaDir); err != nil {
|
||||
return fmt.Errorf("failed to read schema directory: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
package schemaValidator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/santhosh-tekuri/jsonschema/v6"
|
||||
)
|
||||
|
||||
// setupTestSchema creates a temporary directory and writes a sample schema file.
|
||||
func setupTestSchema(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
// Create a temporary directory for the schema
|
||||
schemaDir, err := os.MkdirTemp("", "schemas")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
|
||||
// Create the directory structure for the schema file
|
||||
schemaFilePath := filepath.Join(schemaDir, "example", "v1.0", "endpoint.json")
|
||||
if err := os.MkdirAll(filepath.Dir(schemaFilePath), 0755); err != nil {
|
||||
t.Fatalf("Failed to create schema directory structure: %v", err)
|
||||
}
|
||||
|
||||
// Define a sample schema
|
||||
schemaContent := `{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"domain": {"type": "string"},
|
||||
"version": {"type": "string"},
|
||||
"action": {"type": "string"}
|
||||
},
|
||||
"required": ["domain", "version", "action"]
|
||||
}
|
||||
},
|
||||
"required": ["context"]
|
||||
}`
|
||||
|
||||
// Write the schema to the file
|
||||
if err := os.WriteFile(schemaFilePath, []byte(schemaContent), 0644); err != nil {
|
||||
t.Fatalf("Failed to write schema file: %v", err)
|
||||
}
|
||||
|
||||
return schemaDir
|
||||
}
|
||||
|
||||
func TestValidator_Validate_Success(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
payload string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Valid payload",
|
||||
url: "http://example.com/endpoint",
|
||||
payload: `{"context": {"domain": "example", "version": "1.0", "action": "endpoint"}}`,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Setup a temporary schema directory for testing
|
||||
schemaDir := setupTestSchema(t)
|
||||
defer os.RemoveAll(schemaDir)
|
||||
|
||||
config := &Config{SchemaDir: schemaDir}
|
||||
v, _, err := New(context.Background(), config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create validator: %v", err)
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
u, _ := url.Parse(tt.url)
|
||||
err := v.Validate(context.Background(), u, []byte(tt.payload))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
} else {
|
||||
t.Logf("Test %s passed with no errors", tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidator_Validate_Failure(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
payload string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "Invalid JSON payload",
|
||||
url: "http://example.com/endpoint",
|
||||
payload: `{"context": {"domain": "example", "version": "1.0"`,
|
||||
wantErr: "failed to parse JSON payload",
|
||||
},
|
||||
{
|
||||
name: "Schema validation failure",
|
||||
url: "http://example.com/endpoint",
|
||||
payload: `{"context": {"domain": "example", "version": "1.0"}}`,
|
||||
wantErr: "context: at '/context': missing property 'action'",
|
||||
},
|
||||
{
|
||||
name: "Schema not found",
|
||||
url: "http://example.com/unknown_endpoint",
|
||||
payload: `{"context": {"domain": "example", "version": "1.0"}}`,
|
||||
wantErr: "schema not found for domain",
|
||||
},
|
||||
}
|
||||
|
||||
// Setup a temporary schema directory for testing
|
||||
schemaDir := setupTestSchema(t)
|
||||
defer os.RemoveAll(schemaDir)
|
||||
|
||||
config := &Config{SchemaDir: schemaDir}
|
||||
v, _, err := New(context.Background(), config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create validator: %v", err)
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
u, _ := url.Parse(tt.url)
|
||||
err := v.Validate(context.Background(), u, []byte(tt.payload))
|
||||
if tt.wantErr != "" {
|
||||
if err == nil {
|
||||
t.Errorf("Expected error containing '%s', but got nil", tt.wantErr)
|
||||
} else if !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Errorf("Expected error containing '%s', but got '%v'", tt.wantErr, err)
|
||||
} else {
|
||||
t.Logf("Test %s passed with expected error: %v", tt.name, err)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
} else {
|
||||
t.Logf("Test %s passed with no errors", tt.name)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidator_Initialise(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
setupFunc func(schemaDir string) error
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "Schema directory does not exist",
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Do not create the schema directory
|
||||
return nil
|
||||
|
||||
},
|
||||
wantErr: "schema directory does not exist",
|
||||
},
|
||||
{
|
||||
name: "Schema path is not a directory",
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Create a file instead of a directory
|
||||
return os.WriteFile(schemaDir, []byte{}, 0644)
|
||||
},
|
||||
wantErr: "provided schema path is not a directory",
|
||||
},
|
||||
{
|
||||
name: "Invalid schema file structure",
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Create an invalid schema file structure
|
||||
invalidSchemaFile := filepath.Join(schemaDir, "invalid_schema.json")
|
||||
if err := os.MkdirAll(filepath.Dir(invalidSchemaFile), 0755); err != nil {
|
||||
t.Fatalf("Failed to create directory: %v", err)
|
||||
}
|
||||
return os.WriteFile(invalidSchemaFile, []byte(`{}`), 0644)
|
||||
},
|
||||
wantErr: "invalid schema file structure",
|
||||
},
|
||||
{
|
||||
name: "Failed to compile JSON schema",
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Create a schema file with invalid JSON
|
||||
invalidSchemaFile := filepath.Join(schemaDir, "example", "1.0", "endpoint.json")
|
||||
if err := os.MkdirAll(filepath.Dir(invalidSchemaFile), 0755); err != nil {
|
||||
t.Fatalf("Failed to create directory: %v", err)
|
||||
}
|
||||
return os.WriteFile(invalidSchemaFile, []byte(`{invalid json}`), 0644)
|
||||
},
|
||||
wantErr: "failed to compile JSON schema",
|
||||
},
|
||||
{
|
||||
name: "Invalid schema file structure with empty components",
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Create a schema file with empty domain, version, or schema name
|
||||
invalidSchemaFile := filepath.Join(schemaDir, "", "1.0", "endpoint.json")
|
||||
if err := os.MkdirAll(filepath.Dir(invalidSchemaFile), 0755); err != nil {
|
||||
t.Fatalf("Failed to create directory: %v", err)
|
||||
}
|
||||
return os.WriteFile(invalidSchemaFile, []byte(`{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"domain": {"type": "string"},
|
||||
"version": {"type": "string"}
|
||||
},
|
||||
"required": ["domain", "version"]
|
||||
}
|
||||
},
|
||||
"required": ["context"]
|
||||
}`), 0644)
|
||||
},
|
||||
wantErr: "failed to read schema directory: invalid schema file structure, expected domain/version/schema.json but got: 1.0/endpoint.json",
|
||||
},
|
||||
{
|
||||
name: "Failed to read directory",
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Create a directory and remove read permissions
|
||||
if err := os.MkdirAll(schemaDir, 0000); err != nil {
|
||||
t.Fatalf("Failed to create directory: %v", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
wantErr: "failed to read directory",
|
||||
},
|
||||
{
|
||||
name: "Valid schema directory",
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Create a valid schema file
|
||||
validSchemaFile := filepath.Join(schemaDir, "example", "1.0", "endpoint.json")
|
||||
if err := os.MkdirAll(filepath.Dir(validSchemaFile), 0755); err != nil {
|
||||
t.Fatalf("Failed to create directory: %v", err)
|
||||
}
|
||||
return os.WriteFile(validSchemaFile, []byte(`{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"domain": {"type": "string"},
|
||||
"version": {"type": "string"}
|
||||
},
|
||||
"required": ["domain", "version"]
|
||||
}
|
||||
},
|
||||
"required": ["context"]
|
||||
}`), 0644)
|
||||
},
|
||||
wantErr: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Setup a temporary schema directory for testing
|
||||
schemaDir := filepath.Join(os.TempDir(), "schemas")
|
||||
defer os.RemoveAll(schemaDir)
|
||||
|
||||
// Run the setup function to prepare the test case
|
||||
if err := tt.setupFunc(schemaDir); err != nil {
|
||||
t.Fatalf("setupFunc() error = %v", err)
|
||||
}
|
||||
|
||||
config := &Config{SchemaDir: schemaDir}
|
||||
v := &SchemaValidator{
|
||||
config: config,
|
||||
schemaCache: make(map[string]*jsonschema.Schema),
|
||||
}
|
||||
|
||||
err := v.initialise()
|
||||
if (err != nil && !strings.Contains(err.Error(), tt.wantErr)) || (err == nil && tt.wantErr != "") {
|
||||
t.Errorf("Error: initialise() returned error = %v, expected error = %v", err, tt.wantErr)
|
||||
} else if err == nil {
|
||||
t.Logf("Test %s passed: validator initialized successfully", tt.name)
|
||||
} else {
|
||||
t.Logf("Test %s passed with expected error: %v", tt.name, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatorNew_Success(t *testing.T) {
|
||||
schemaDir := setupTestSchema(t)
|
||||
defer os.RemoveAll(schemaDir)
|
||||
|
||||
config := &Config{SchemaDir: schemaDir}
|
||||
_, _, err := New(context.Background(), config)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatorNewFailure(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
config *Config
|
||||
setupFunc func(schemaDir string) error
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "Config is nil",
|
||||
config: nil,
|
||||
setupFunc: func(schemaDir string) error {
|
||||
return nil
|
||||
},
|
||||
wantErr: "config cannot be nil",
|
||||
},
|
||||
{
|
||||
name: "Failed to initialise validators",
|
||||
config: &Config{
|
||||
SchemaDir: "/invalid/path",
|
||||
},
|
||||
setupFunc: func(schemaDir string) error {
|
||||
// Do not create the schema directory
|
||||
return nil
|
||||
},
|
||||
wantErr: "ailed to initialise schemaValidator: schema directory does not exist: /invalid/path",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Run the setup function if provided
|
||||
if tt.setupFunc != nil {
|
||||
schemaDir := ""
|
||||
if tt.config != nil {
|
||||
schemaDir = tt.config.SchemaDir
|
||||
}
|
||||
if err := tt.setupFunc(schemaDir); err != nil {
|
||||
t.Fatalf("Setup function failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Call the New function with the test config
|
||||
_, _, err := New(context.Background(), tt.config)
|
||||
if (err != nil && !strings.Contains(err.Error(), tt.wantErr)) || (err == nil && tt.wantErr != "") {
|
||||
t.Errorf("Error: New() returned error = %v, expected error = %v", err, tt.wantErr)
|
||||
} else {
|
||||
t.Logf("Test %s passed with expected error: %v", tt.name, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/beckn/beckn-onix/pkg/model"
|
||||
)
|
||||
|
||||
@@ -14,16 +16,40 @@ type ErrorType string
|
||||
|
||||
type errorResponseWriter struct{}
|
||||
|
||||
func (e *errorResponseWriter) Header() http.Header {
|
||||
return http.Header{}
|
||||
}
|
||||
|
||||
func (e *errorResponseWriter) Write([]byte) (int, error) {
|
||||
return 0, errors.New("write error")
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
Code string `json:"code,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Paths string `json:"paths,omitempty"`
|
||||
}
|
||||
|
||||
func (e *errorResponseWriter) WriteHeader(statusCode int) {}
|
||||
|
||||
// SchemaValidationErr represents a collection of schema validation failures.
|
||||
type SchemaValidationErr struct {
|
||||
Errors []Error
|
||||
}
|
||||
|
||||
// Error implements the error interface for SchemaValidationErr.
|
||||
func (e *SchemaValidationErr) Error() string {
|
||||
var errorMessages []string
|
||||
for _, err := range e.Errors {
|
||||
errorMessages = append(errorMessages, fmt.Sprintf("%s: %s", err.Paths, err.Message))
|
||||
}
|
||||
return strings.Join(errorMessages, "; ")
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Ack struct {
|
||||
Status string `json:"status,omitempty"`
|
||||
} `json:"ack,omitempty"`
|
||||
Error *Error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func SendAck(w http.ResponseWriter) {
|
||||
resp := &model.Response{
|
||||
Message: model.Message{
|
||||
|
||||
@@ -12,6 +12,10 @@ import (
|
||||
"github.com/beckn/beckn-onix/pkg/model"
|
||||
)
|
||||
|
||||
func (e *errorResponseWriter) Header() http.Header {
|
||||
return http.Header{}
|
||||
}
|
||||
|
||||
func TestSendAck(t *testing.T) {
|
||||
_, err := http.NewRequest("GET", "/", nil)
|
||||
if err != nil {
|
||||
@@ -22,12 +26,14 @@ func TestSendAck(t *testing.T) {
|
||||
SendAck(rr)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Errorf("expected status code %d, got %d", http.StatusOK, rr.Code)
|
||||
t.Errorf("wanted status code %d, got %d", http.StatusOK, rr.Code)
|
||||
}
|
||||
|
||||
expected := `{"message":{"ack":{"status":"ACK"}}}`
|
||||
if rr.Body.String() != expected {
|
||||
t.Errorf("expected body %s, got %s", expected, rr.Body.String())
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
rr.Body.String(), expected)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +94,7 @@ func TestSendNack(t *testing.T) {
|
||||
SendNack(ctx, rr, tt.err)
|
||||
|
||||
if rr.Code != tt.status {
|
||||
t.Errorf("expected status code %d, got %d", tt.status, rr.Code)
|
||||
t.Errorf("wanted status code %d, got %d", tt.status, rr.Code)
|
||||
}
|
||||
|
||||
var actual map[string]interface{}
|
||||
@@ -104,12 +110,29 @@ func TestSendNack(t *testing.T) {
|
||||
}
|
||||
|
||||
if !compareJSON(expected, actual) {
|
||||
t.Errorf("expected body %s, got %s", tt.expected, rr.Body.String())
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
actual, expected)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchemaValidationErr_Error(t *testing.T) {
|
||||
// Create sample validation errors
|
||||
validationErrors := []Error{
|
||||
{Paths: "name", Message: "Name is required"},
|
||||
{Paths: "email", Message: "Invalid email format"},
|
||||
}
|
||||
err := SchemaValidationErr{Errors: validationErrors}
|
||||
expected := "name: Name is required; email: Invalid email format"
|
||||
if err.Error() != expected {
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
err.Error(), expected)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func compareJSON(expected, actual map[string]interface{}) bool {
|
||||
expectedBytes, _ := json.Marshal(expected)
|
||||
actualBytes, _ := json.Marshal(actual)
|
||||
@@ -128,7 +151,6 @@ func (b *badMessage) MarshalJSON() ([]byte, error) {
|
||||
return nil, errors.New("marshal error")
|
||||
}
|
||||
|
||||
|
||||
func TestNack_1(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -158,14 +180,14 @@ func TestNack_1(t *testing.T) {
|
||||
expected: `{"message":{"ack":{"status":"NACK"},"error":{"code":"INTERNAL_SERVER_ERROR","message":"Something went wrong"}}}`,
|
||||
},
|
||||
{
|
||||
name: "JSON Marshal Error",
|
||||
err: nil, // This will be overridden to cause marshaling error
|
||||
status: http.StatusInternalServerError,
|
||||
expected: `Internal server error, MessageID: 12345`,
|
||||
useBadJSON: true,
|
||||
name: "JSON Marshal Error",
|
||||
err: nil, // This will be overridden to cause marshaling error
|
||||
status: http.StatusInternalServerError,
|
||||
expected: `Internal server error, MessageID: 12345`,
|
||||
useBadJSON: true,
|
||||
},
|
||||
{
|
||||
name: "Write Error",
|
||||
name: "Write Error",
|
||||
err: &model.Error{
|
||||
Code: "WRITE_ERROR",
|
||||
Message: "Failed to write response",
|
||||
@@ -201,8 +223,6 @@ func TestNack_1(t *testing.T) {
|
||||
}
|
||||
|
||||
nack(w, tt.err, tt.status, ctx)
|
||||
|
||||
// Skip verification if using errorResponseWriter
|
||||
if !tt.useBadWrite {
|
||||
recorder, ok := w.(*httptest.ResponseRecorder)
|
||||
if !ok {
|
||||
@@ -210,12 +230,13 @@ func TestNack_1(t *testing.T) {
|
||||
}
|
||||
|
||||
if recorder.Code != tt.status {
|
||||
t.Errorf("expected status code %d, got %d", tt.status, recorder.Code)
|
||||
t.Errorf("wanted status code %d, got %d", tt.status, recorder.Code)
|
||||
}
|
||||
|
||||
body := recorder.Body.String()
|
||||
if body != tt.expected {
|
||||
t.Errorf("expected body %s, got %s", tt.expected, body)
|
||||
t.Errorf("err.Error() = %s, want %s",
|
||||
body, tt.expected)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
BIN
schemas.zip
Normal file
BIN
schemas.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user