From 528a4a5d908796ae540e867317ac79a7d2e1bb03 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 6 Aug 2024 14:59:18 +0200 Subject: [PATCH 1/8] feat: compact details --- doc/ld/validator/validate.go | 44 +++++++------------------------ doc/ld/validator/validate_test.go | 8 +++--- go.mod | 1 + 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/doc/ld/validator/validate.go b/doc/ld/validator/validate.go index b99a72b..df965fc 100644 --- a/doc/ld/validator/validate.go +++ b/doc/ld/validator/validate.go @@ -11,6 +11,8 @@ import ( "reflect" "strings" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/piprate/json-gold/ld" "github.com/trustbloc/did-go/doc/ld/processor" @@ -92,8 +94,9 @@ func ValidateJSONLDMap(docMap map[string]interface{}, options ...ValidateOpts) e return fmt.Errorf("compact JSON-LD document: %w", err) } - if opts.strict && !mapsHaveSameStructure(docMap, docCompactedMap) { - return errors.New("JSON-LD doc has different structure after compaction") + mapDiff := findMapDiff(docMap, docCompactedMap) + if opts.strict && mapDiff != "" { + return fmt.Errorf("JSON-LD doc has different structure after compaction. Details: %v", mapDiff) } err = validateContextURIPosition(opts.contextURIPositions, docMap) @@ -136,40 +139,11 @@ func validateContextURIPosition(contextURIPositions []string, docMap map[string] return nil } -func mapsHaveSameStructure(originalMap, compactedMap map[string]interface{}) bool { - original := compactMap(originalMap) - compacted := compactMap(compactedMap) +func findMapDiff(originalMap, compactedMap map[string]interface{}) string { + originalMap = compactMap(originalMap) + compactedMap = compactMap(compactedMap) - if reflect.DeepEqual(original, compacted) { - return true - } - - if len(original) != len(compacted) { - return false - } - - for k, v1 := range original { - v1Map, isMap := v1.(map[string]interface{}) - if !isMap { - continue - } - - v2, present := compacted[k] - if !present { // special case - the name of the map was mapped, cannot guess what's a new name - continue - } - - v2Map, isMap := v2.(map[string]interface{}) - if !isMap { - return false - } - - if !mapsHaveSameStructure(v1Map, v2Map) { - return false - } - } - - return true + return cmp.Diff(originalMap, compactedMap, cmpopts.IgnoreUnexported()) } func compactMap(m map[string]interface{}) map[string]interface{} { diff --git a/doc/ld/validator/validate_test.go b/doc/ld/validator/validate_test.go index 47338e3..12616ff 100644 --- a/doc/ld/validator/validate_test.go +++ b/doc/ld/validator/validate_test.go @@ -173,7 +173,7 @@ func Test_ValidateJSONLDWithExtraUndefinedFields(t *testing.T) { err := ValidateJSONLD(vc, WithDocumentLoader(loader)) require.Error(t, err) - require.EqualError(t, err, "JSON-LD doc has different structure after compaction") + require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") } func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { @@ -215,7 +215,7 @@ func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { err := ValidateJSONLD(vcJSON, WithDocumentLoader(loader)) require.Error(t, err) - require.EqualError(t, err, "JSON-LD doc has different structure after compaction") + require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") }) t.Run("Extended basic VC model, credentialSubject is defined as array - undefined fields present", func(t *testing.T) { @@ -248,7 +248,7 @@ func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { err := ValidateJSONLD(vcJSON, WithDocumentLoader(loader)) require.Error(t, err) - require.EqualError(t, err, "JSON-LD doc has different structure after compaction") + require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") }) } @@ -311,7 +311,7 @@ func Test_ValidateJSONLD_WithExtraUndefinedFieldsInProof(t *testing.T) { err = ValidateJSONLD(vcJSONWithInvalidProof, WithDocumentLoader(createTestDocumentLoader(t))) require.Error(t, err) - require.EqualError(t, err, "JSON-LD doc has different structure after compaction") + require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") } func Test_ValidateJSONLD_CornerErrorCases(t *testing.T) { diff --git a/go.mod b/go.mod index f59d9cd..0ad7283 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/cenkalti/backoff/v4 v4.1.3 github.com/go-jose/go-jose/v3 v3.0.1 + github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.0 github.com/mitchellh/mapstructure v1.5.0 github.com/multiformats/go-multibase v0.1.1 From b08fb5beb908a6c37000d91b4b10bb012bc3eabe Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 6 Aug 2024 15:00:09 +0200 Subject: [PATCH 2/8] fix: go mod --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index 0ad7283..396b477 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,6 @@ require ( github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect From 5ca7a88add4652dc646afdfd341833eb8373bde2 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 6 Aug 2024 15:32:33 +0200 Subject: [PATCH 3/8] feat: manual compare --- doc/ld/validator/validate.go | 80 +++++++++++++++++++++++++++++++++--- go.mod | 2 +- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/doc/ld/validator/validate.go b/doc/ld/validator/validate.go index df965fc..ad2066d 100644 --- a/doc/ld/validator/validate.go +++ b/doc/ld/validator/validate.go @@ -6,13 +6,12 @@ SPDX-License-Identifier: Apache-2.0 package validator import ( + json2 "encoding/json" "errors" "fmt" "reflect" "strings" - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" "github.com/piprate/json-gold/ld" "github.com/trustbloc/did-go/doc/ld/processor" @@ -95,8 +94,9 @@ func ValidateJSONLDMap(docMap map[string]interface{}, options ...ValidateOpts) e } mapDiff := findMapDiff(docMap, docCompactedMap) - if opts.strict && mapDiff != "" { - return fmt.Errorf("JSON-LD doc has different structure after compaction. Details: %v", mapDiff) + if opts.strict && len(mapDiff) != 0 { + diff, _ := json2.Marshal(mapDiff) + return fmt.Errorf("JSON-LD doc has different structure after compaction. Details: %v", string(diff)) } err = validateContextURIPosition(opts.contextURIPositions, docMap) @@ -139,11 +139,79 @@ func validateContextURIPosition(contextURIPositions []string, docMap map[string] return nil } -func findMapDiff(originalMap, compactedMap map[string]interface{}) string { +type Diff struct { + OriginalValue interface{} + CompactedValue interface{} +} + +func mapsHaveSameStructure( + originalMap, + compactedMap map[string]interface{}, + path string, +) map[string][]*Diff { + original := compactMap(originalMap) + compacted := compactMap(compactedMap) + + if reflect.DeepEqual(original, compacted) { + return nil + } + + diffs := make(map[string][]*Diff) + + if len(original) != len(compacted) { + for k, v := range original { + diffKey := path + "." + k + if _, ok := compacted[k]; !ok { + diffs[diffKey] = append(diffs[diffKey], &Diff{OriginalValue: v, CompactedValue: "!missing!"}) + } + } + + for k, v := range compacted { + diffKey := path + "." + k + + if _, ok := original[k]; !ok { + diffs[diffKey] = append(diffs[diffKey], &Diff{OriginalValue: "!missing!", CompactedValue: v}) + } + } + + return diffs + } + + for k, v1 := range original { + diffKey := path + "." + k + + v1Map, isMap := v1.(map[string]interface{}) + if !isMap { + continue + } + + v2, present := compacted[k] + if !present { // special case - the name of the map was mapped, cannot guess what's a new name + diffs[diffKey] = append(diffs[diffKey], &Diff{OriginalValue: v1, CompactedValue: "!missing!"}) + continue + } + + v2Map, isMap := v2.(map[string]interface{}) + if !isMap { + diffs[diffKey] = append(diffs[diffKey], &Diff{OriginalValue: v1, CompactedValue: v2}) + } + + mp := mapsHaveSameStructure(v1Map, v2Map, diffKey) + for m1, m2 := range mp { + diffs[m1] = append(diffs[m1], m2...) + } + } + + return diffs +} + +func findMapDiff(originalMap, compactedMap map[string]interface{}) map[string][]*Diff { originalMap = compactMap(originalMap) compactedMap = compactMap(compactedMap) - return cmp.Diff(originalMap, compactedMap, cmpopts.IgnoreUnexported()) + return mapsHaveSameStructure(originalMap, compactedMap, "$") + //fmt.Println(diff) + //return cmp.Diff(originalMap, compactedMap, cmpopts.IgnoreUnexported()) } func compactMap(m map[string]interface{}) map[string]interface{} { diff --git a/go.mod b/go.mod index 396b477..f59d9cd 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/cenkalti/backoff/v4 v4.1.3 github.com/go-jose/go-jose/v3 v3.0.1 - github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.0 github.com/mitchellh/mapstructure v1.5.0 github.com/multiformats/go-multibase v0.1.1 @@ -28,6 +27,7 @@ require ( github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect From 99319d0e5d310916311f1dade4e9092dd9a073a2 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 6 Aug 2024 15:46:15 +0200 Subject: [PATCH 4/8] feat: include detailed error --- doc/ld/validator/validate.go | 28 +++++++++++++++------ doc/ld/validator/validate_test.go | 42 ++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/doc/ld/validator/validate.go b/doc/ld/validator/validate.go index ad2066d..9e815c8 100644 --- a/doc/ld/validator/validate.go +++ b/doc/ld/validator/validate.go @@ -19,10 +19,11 @@ import ( ) type validateOpts struct { - strict bool - jsonldDocumentLoader ld.DocumentLoader - externalContext []string - contextURIPositions []string + strict bool + jsonldDocumentLoader ld.DocumentLoader + externalContext []string + contextURIPositions []string + jsonldIncludeDetailedStructureDiffOnError bool } // ValidateOpts sets jsonld validation options. @@ -35,6 +36,12 @@ func WithDocumentLoader(jsonldDocumentLoader ld.DocumentLoader) ValidateOpts { } } +func WithJSONLDIncludeDetailedStructureDiffOnError() ValidateOpts { + return func(opts *validateOpts) { + opts.jsonldIncludeDetailedStructureDiffOnError = true + } +} + // WithExternalContext option is for definition of external context when doing JSON-LD operations. func WithExternalContext(externalContext []string) ValidateOpts { return func(opts *validateOpts) { @@ -95,8 +102,15 @@ func ValidateJSONLDMap(docMap map[string]interface{}, options ...ValidateOpts) e mapDiff := findMapDiff(docMap, docCompactedMap) if opts.strict && len(mapDiff) != 0 { - diff, _ := json2.Marshal(mapDiff) - return fmt.Errorf("JSON-LD doc has different structure after compaction. Details: %v", string(diff)) + errText := "JSON-LD doc has different structure after compaction" + + if opts.jsonldIncludeDetailedStructureDiffOnError { + diff, _ := json2.Marshal(mapDiff) + + errText = fmt.Sprintf("%s. Details: %v", errText, string(diff)) + } + + return errors.New(errText) } err = validateContextURIPosition(opts.contextURIPositions, docMap) @@ -210,8 +224,6 @@ func findMapDiff(originalMap, compactedMap map[string]interface{}) map[string][] compactedMap = compactMap(compactedMap) return mapsHaveSameStructure(originalMap, compactedMap, "$") - //fmt.Println(diff) - //return cmp.Diff(originalMap, compactedMap, cmpopts.IgnoreUnexported()) } func compactMap(m map[string]interface{}) map[string]interface{} { diff --git a/doc/ld/validator/validate_test.go b/doc/ld/validator/validate_test.go index 12616ff..8578ef8 100644 --- a/doc/ld/validator/validate_test.go +++ b/doc/ld/validator/validate_test.go @@ -173,7 +173,7 @@ func Test_ValidateJSONLDWithExtraUndefinedFields(t *testing.T) { err := ValidateJSONLD(vc, WithDocumentLoader(loader)) require.Error(t, err) - require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") + require.EqualError(t, err, "JSON-LD doc has different structure after compaction") } func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { @@ -215,7 +215,41 @@ func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { err := ValidateJSONLD(vcJSON, WithDocumentLoader(loader)) require.Error(t, err) - require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") + require.EqualError(t, err, "JSON-LD doc has different structure after compaction") + }) + + t.Run("Extended basic VC model, credentialSubject is defined as object - undefined fields present and details", + func(t *testing.T) { + // Use a different VC to verify the case when credentialSubject is an array. + vcJSONTemplate := ` +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "%s" + ], + "id": "http://example.com/credentials/4643", + "type": [ + "VerifiableCredential", + "CustomExt12" + ], + "issuer": "https://example.com/issuers/14", + "issuanceDate": "2018-02-24T05:28:04Z", + "referenceNumber": 83294847, + "credentialSubject": [ + { + "id": "did:example:abcdef1234567", + "name": "Jane Doe", + "favoriteFood": "Papaya" + } + ] +} +` + + vcJSON := fmt.Sprintf(vcJSONTemplate, contextURL) + + err := ValidateJSONLD(vcJSON, WithDocumentLoader(loader), WithJSONLDIncludeDetailedStructureDiffOnError()) + require.Error(t, err) + require.EqualError(t, err, "JSON-LD doc has different structure after compaction. Details: {\"$.credentialSubject\":[{\"OriginalValue\":{\"favoriteFood\":\"Papaya\",\"id\":\"did:example:abcdef1234567\",\"name\":\"Jane Doe\"},\"CompactedValue\":\"did:example:abcdef1234567\"}],\"$.credentialSubject.favoriteFood\":[{\"OriginalValue\":\"Papaya\",\"CompactedValue\":\"!missing!\"}],\"$.credentialSubject.id\":[{\"OriginalValue\":\"did:example:abcdef1234567\",\"CompactedValue\":\"!missing!\"}],\"$.credentialSubject.name\":[{\"OriginalValue\":\"Jane Doe\",\"CompactedValue\":\"!missing!\"}]}") //nolint:lll }) t.Run("Extended basic VC model, credentialSubject is defined as array - undefined fields present", func(t *testing.T) { @@ -248,7 +282,7 @@ func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { err := ValidateJSONLD(vcJSON, WithDocumentLoader(loader)) require.Error(t, err) - require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") + require.EqualError(t, err, "JSON-LD doc has different structure after compaction") }) } @@ -311,7 +345,7 @@ func Test_ValidateJSONLD_WithExtraUndefinedFieldsInProof(t *testing.T) { err = ValidateJSONLD(vcJSONWithInvalidProof, WithDocumentLoader(createTestDocumentLoader(t))) require.Error(t, err) - require.ErrorContains(t, err, "JSON-LD doc has different structure after compaction") + require.EqualError(t, err, "JSON-LD doc has different structure after compaction") } func Test_ValidateJSONLD_CornerErrorCases(t *testing.T) { From 6babea0e69c1da5b9877db2d4bf2aa6a122952a4 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 6 Aug 2024 15:50:31 +0200 Subject: [PATCH 5/8] fix: lint --- doc/ld/validator/testdata/extended_model.json | 21 ++++++ doc/ld/validator/types.go | 12 +++ doc/ld/validator/validate.go | 9 +-- doc/ld/validator/validate_test.go | 75 ++----------------- 4 files changed, 42 insertions(+), 75 deletions(-) create mode 100644 doc/ld/validator/testdata/extended_model.json create mode 100644 doc/ld/validator/types.go diff --git a/doc/ld/validator/testdata/extended_model.json b/doc/ld/validator/testdata/extended_model.json new file mode 100644 index 0000000..2ff44d7 --- /dev/null +++ b/doc/ld/validator/testdata/extended_model.json @@ -0,0 +1,21 @@ +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "%s" + ], + "id": "http://example.com/credentials/4643", + "type": [ + "VerifiableCredential", + "CustomExt12" + ], + "issuer": "https://example.com/issuers/14", + "issuanceDate": "2018-02-24T05:28:04Z", + "referenceNumber": 83294847, + "credentialSubject": [ + { + "id": "did:example:abcdef1234567", + "name": "Jane Doe", + "favoriteFood": "Papaya" + } + ] +} \ No newline at end of file diff --git a/doc/ld/validator/types.go b/doc/ld/validator/types.go new file mode 100644 index 0000000..7e51467 --- /dev/null +++ b/doc/ld/validator/types.go @@ -0,0 +1,12 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package validator + +// Diff represents the difference between two objects. +type Diff struct { + OriginalValue interface{} + CompactedValue interface{} +} diff --git a/doc/ld/validator/validate.go b/doc/ld/validator/validate.go index 9e815c8..27e4ef7 100644 --- a/doc/ld/validator/validate.go +++ b/doc/ld/validator/validate.go @@ -36,6 +36,7 @@ func WithDocumentLoader(jsonldDocumentLoader ld.DocumentLoader) ValidateOpts { } } +// WithJSONLDIncludeDetailedStructureDiffOnError option is for including detailed structure diff in error message. func WithJSONLDIncludeDetailedStructureDiffOnError() ValidateOpts { return func(opts *validateOpts) { opts.jsonldIncludeDetailedStructureDiffOnError = true @@ -105,7 +106,7 @@ func ValidateJSONLDMap(docMap map[string]interface{}, options ...ValidateOpts) e errText := "JSON-LD doc has different structure after compaction" if opts.jsonldIncludeDetailedStructureDiffOnError { - diff, _ := json2.Marshal(mapDiff) + diff, _ := json2.Marshal(mapDiff) // nolint:errcheck errText = fmt.Sprintf("%s. Details: %v", errText, string(diff)) } @@ -153,11 +154,7 @@ func validateContextURIPosition(contextURIPositions []string, docMap map[string] return nil } -type Diff struct { - OriginalValue interface{} - CompactedValue interface{} -} - +// nolint: gocyclo func mapsHaveSameStructure( originalMap, compactedMap map[string]interface{}, diff --git a/doc/ld/validator/validate_test.go b/doc/ld/validator/validate_test.go index 8578ef8..1c905aa 100644 --- a/doc/ld/validator/validate_test.go +++ b/doc/ld/validator/validate_test.go @@ -30,6 +30,9 @@ var ( //go:embed testdata/context/wallet_v1.jsonld walletV1Context []byte + + //go:embed testdata/extended_model.json + extendedModel string ) func Test_ValidateJSONLD(t *testing.T) { @@ -187,29 +190,7 @@ func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { t.Run("Extended basic VC model, credentialSubject is defined as object - undefined fields present", func(t *testing.T) { // Use a different VC to verify the case when credentialSubject is an array. - vcJSONTemplate := ` -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "%s" - ], - "id": "http://example.com/credentials/4643", - "type": [ - "VerifiableCredential", - "CustomExt12" - ], - "issuer": "https://example.com/issuers/14", - "issuanceDate": "2018-02-24T05:28:04Z", - "referenceNumber": 83294847, - "credentialSubject": [ - { - "id": "did:example:abcdef1234567", - "name": "Jane Doe", - "favoriteFood": "Papaya" - } - ] -} -` + vcJSONTemplate := extendedModel vcJSON := fmt.Sprintf(vcJSONTemplate, contextURL) @@ -221,29 +202,7 @@ func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { t.Run("Extended basic VC model, credentialSubject is defined as object - undefined fields present and details", func(t *testing.T) { // Use a different VC to verify the case when credentialSubject is an array. - vcJSONTemplate := ` -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "%s" - ], - "id": "http://example.com/credentials/4643", - "type": [ - "VerifiableCredential", - "CustomExt12" - ], - "issuer": "https://example.com/issuers/14", - "issuanceDate": "2018-02-24T05:28:04Z", - "referenceNumber": 83294847, - "credentialSubject": [ - { - "id": "did:example:abcdef1234567", - "name": "Jane Doe", - "favoriteFood": "Papaya" - } - ] -} -` + vcJSONTemplate := extendedModel vcJSON := fmt.Sprintf(vcJSONTemplate, contextURL) @@ -254,29 +213,7 @@ func Test_ValidateJSONLDWithExtraUndefinedSubjectFields(t *testing.T) { t.Run("Extended basic VC model, credentialSubject is defined as array - undefined fields present", func(t *testing.T) { // Use a different VC to verify the case when credentialSubject is an array. - vcJSONTemplate := ` -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "%s" - ], - "id": "http://example.com/credentials/4643", - "type": [ - "VerifiableCredential", - "CustomExt12" - ], - "issuer": "https://example.com/issuers/14", - "issuanceDate": "2018-02-24T05:28:04Z", - "referenceNumber": 83294847, - "credentialSubject": [ - { - "id": "did:example:abcdef1234567", - "name": "Jane Doe", - "favoriteFood": "Papaya" - } - ] -} -` + vcJSONTemplate := extendedModel vcJSON := fmt.Sprintf(vcJSONTemplate, contextURL) From 26cf1dbce6688c1524794404d8b0b5a404006eac Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 6 Aug 2024 15:54:00 +0200 Subject: [PATCH 6/8] feat: ensure map not nil --- doc/ld/validator/validate.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/ld/validator/validate.go b/doc/ld/validator/validate.go index 27e4ef7..dc1d921 100644 --- a/doc/ld/validator/validate.go +++ b/doc/ld/validator/validate.go @@ -207,6 +207,10 @@ func mapsHaveSameStructure( diffs[diffKey] = append(diffs[diffKey], &Diff{OriginalValue: v1, CompactedValue: v2}) } + if v2Map == nil { + v2Map = make(map[string]interface{}) + } + mp := mapsHaveSameStructure(v1Map, v2Map, diffKey) for m1, m2 := range mp { diffs[m1] = append(diffs[m1], m2...) From 0d3b4e666ca1e367d863f3b0e66ceafbde959c10 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 6 Aug 2024 15:57:38 +0200 Subject: [PATCH 7/8] fix: lint --- doc/ld/validator/validate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ld/validator/validate.go b/doc/ld/validator/validate.go index dc1d921..f2a4029 100644 --- a/doc/ld/validator/validate.go +++ b/doc/ld/validator/validate.go @@ -154,7 +154,7 @@ func validateContextURIPosition(contextURIPositions []string, docMap map[string] return nil } -// nolint: gocyclo +// nolint:gocyclo,funlen func mapsHaveSameStructure( originalMap, compactedMap map[string]interface{}, From 296eef43066c41338ee919e327a33860db5eb4be Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Mon, 12 Aug 2024 14:04:08 +0200 Subject: [PATCH 8/8] fix: find diff --- doc/ld/validator/validate.go | 3 +-- doc/ld/validator/validate_test.go | 37 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/doc/ld/validator/validate.go b/doc/ld/validator/validate.go index f2a4029..a1b2fe8 100644 --- a/doc/ld/validator/validate.go +++ b/doc/ld/validator/validate.go @@ -198,8 +198,7 @@ func mapsHaveSameStructure( v2, present := compacted[k] if !present { // special case - the name of the map was mapped, cannot guess what's a new name - diffs[diffKey] = append(diffs[diffKey], &Diff{OriginalValue: v1, CompactedValue: "!missing!"}) - continue + continue // should not be counted as diff } v2Map, isMap := v2.(map[string]interface{}) diff --git a/doc/ld/validator/validate_test.go b/doc/ld/validator/validate_test.go index 1c905aa..825b176 100644 --- a/doc/ld/validator/validate_test.go +++ b/doc/ld/validator/validate_test.go @@ -562,6 +562,43 @@ func Benchmark_ValidateJSONLD(b *testing.B) { }) } +func TestDiffOnEduCred(t *testing.T) { + diff := findMapDiff(map[string]any{ + "degree": map[string]any{ + "type": "BachelorDegree", + "name": "Bachelor of Science and Arts", + }, + "alumniOf": map[string]any{ + "id": "some-id", + "name": []any{ + map[string]any{ + "value": "University", + "lang": "en", + }, + }, + }, + "type": []interface{}{ + "VerifiableCredential", + "UniversityDegreeCredential", + }, + }, map[string]any{ + "degree": map[string]any{ + "type": "BachelorDegree", + "name": "Bachelor of Science and Arts", + }, + "schema:alumniOf": map[string]any{ + "id": "some-id", + "schema:name": []any{}, + }, + "type": []interface{}{ + "VerifiableCredential", + "UniversityDegreeCredential", + }, + }) + + require.Len(t, diff, 0) +} + func createTestDocumentLoader(t *testing.T, extraContexts ...ldcontext.Document) *ldloader.DocumentLoader { t.Helper()