Skip to content

Commit 6a08a3a

Browse files
authored
Merge pull request #92 from go-oidfed/enc/find-entity-metadata
[metadata] Fix FindEntityMetadata; extend testing
2 parents a66be3b + fdac609 commit 6a08a3a

File tree

2 files changed

+112
-15
lines changed

2 files changed

+112
-15
lines changed

metadata.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@ func applyPolicy(metadata any, policy MetadataPolicy, ownTag string) (any, error
316316
// FindEntityMetadata finds metadata for the specified entity type in the
317317
// metadata and decodes it into the provided metadata object.
318318
func (m *Metadata) FindEntityMetadata(entityType string, metadata any) error {
319+
// Validate that metadata is a pointer
320+
metadataValue := reflect.ValueOf(metadata)
321+
if metadataValue.Kind() != reflect.Ptr || metadataValue.IsNil() {
322+
return errors.New("metadata parameter must be a non-nil pointer")
323+
}
324+
319325
// Check if the entity type indicates one of the explicit struct fields.
320326
v := reflect.ValueOf(m)
321327
t := v.Elem().Type()
@@ -329,16 +335,23 @@ func (m *Metadata) FindEntityMetadata(entityType string, metadata any) error {
329335
if j != entityType {
330336
continue
331337
}
332-
if j == entityType {
333-
fmt.Printf("found entity type %s\n", entityType)
334-
}
335338

336339
value := v.Elem().FieldByName(t.Field(i).Name)
337340
if value.IsZero() {
338341
continue
339342
}
340343

341-
metadata = value.Interface()
344+
// Get the field value and set it to the metadata parameter
345+
fieldValue := value.Interface()
346+
sourceValue := reflect.ValueOf(fieldValue).Elem()
347+
348+
// Create a new instance of the same type as the field
349+
targetValue := metadataValue.Elem()
350+
if !sourceValue.Type().AssignableTo(targetValue.Type()) {
351+
return errors.Errorf("cannot assign %v to %v", sourceValue.Type(), targetValue.Type())
352+
}
353+
354+
targetValue.Set(sourceValue)
342355
return nil
343356
}
344357

@@ -353,10 +366,13 @@ func (m *Metadata) FindEntityMetadata(entityType string, metadata any) error {
353366
// struct so we can use RTTI to give the caller a richer representation.
354367
jsonMetadata, err := json.Marshal(metadataMap)
355368
if err != nil {
356-
return errors.Errorf("failed to marshal metadata: %s", err)
369+
return errors.Wrapf(err, "failed to marshal metadata")
357370
}
358-
359-
return json.Unmarshal(jsonMetadata, metadata)
371+
// Unmarshal the JSON data into the new instance
372+
if err = json.Unmarshal(jsonMetadata, metadata); err != nil {
373+
return errors.Wrapf(err, "failed to unmarshal metadata")
374+
}
375+
return nil
360376
}
361377

362378
// OAuthClientMetadata is a type for holding the metadata about an oauth client

metadata_test.go

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package oidfed
33
import (
44
"bytes"
55
"encoding/json"
6+
"fmt"
67
"reflect"
78
"testing"
89

@@ -333,48 +334,128 @@ func TestMetadata_UnmarshalJSON(t *testing.T) {
333334
}
334335

335336
func TestMetadata_FindEntityMetadata(t *testing.T) {
336-
type AnotherEntityMetadata struct{}
337+
type AnotherEntityMetadata struct {
338+
AKey string `json:"a-key"`
339+
}
337340
var metadata Metadata
338341
if err := json.Unmarshal(metadataMarshalData["extra metadata"].Data, &metadata); err != nil {
339342
t.Fatal(err)
340343
}
341344

342345
testCases := map[string]struct {
343346
metadataType string
344-
deserializeInto any
347+
deserializeInto string
345348
shouldSucceed bool
349+
expectedResult any
346350
}{
347351
"Metadata is present and in an explicit struct field": {
348352
metadataType: "federation_entity",
349-
deserializeInto: FederationEntityMetadata{},
353+
deserializeInto: "federation_entity_metadata",
354+
shouldSucceed: true,
355+
expectedResult: FederationEntityMetadata{
356+
FederationFetchEndpoint: "https://federation.endpoint/fetch",
357+
wasSet: map[string]bool{
358+
"FederationFetchEndpoint": true,
359+
},
360+
},
361+
},
362+
"Metadata handle nil pointer parameter": {
363+
metadataType: "federation_entity",
364+
deserializeInto: "",
365+
shouldSucceed: false,
366+
expectedResult: nil,
367+
},
368+
"Metadata present in Extra but incorrectly typed": {
369+
metadataType: "another-entity",
370+
deserializeInto: "struct name",
350371
shouldSucceed: true,
372+
expectedResult: struct{ Name string }{},
373+
},
374+
"Struct field present but empty": {
375+
metadataType: "openid_provider",
376+
deserializeInto: "openid_provider_metadata",
377+
shouldSucceed: false,
378+
expectedResult: OpenIDProviderMetadata{},
379+
},
380+
"Extra metadata with invalid entity type": {
381+
metadataType: "invalid-extra",
382+
deserializeInto: "struct",
383+
shouldSucceed: false,
384+
expectedResult: struct{}{},
351385
},
352386
"Metadata is present and in extra metadata": {
353387
metadataType: "another-entity",
354-
deserializeInto: AnotherEntityMetadata{},
388+
deserializeInto: "another_entity_metadata",
355389
shouldSucceed: true,
390+
expectedResult: AnotherEntityMetadata{
391+
AKey: "a-value",
392+
},
356393
},
357394
"Metadata is absent and would be in an explicit struct field": {
358395
metadataType: "openid_provider",
359-
deserializeInto: OpenIDProviderMetadata{},
396+
deserializeInto: "openid_provider_metadata",
360397
shouldSucceed: false,
398+
expectedResult: OpenIDProviderMetadata{},
361399
},
362400
"Metadata is absent and would be in extra metadata": {
363401
metadataType: "no-such-metadata",
364-
deserializeInto: struct{}{},
402+
deserializeInto: "struct",
365403
shouldSucceed: false,
404+
expectedResult: struct{}{},
366405
},
367406
}
368407

369408
for name, testCase := range testCases {
370409
t.Run(
371410
name, func(t *testing.T) {
372-
err := metadata.FindEntityMetadata(testCase.metadataType, &testCase.deserializeInto)
411+
var err error
412+
var result any
413+
switch testCase.deserializeInto {
414+
case "federation_entity_metadata":
415+
var deserialize FederationEntityMetadata
416+
err = metadata.FindEntityMetadata(testCase.metadataType, &deserialize)
417+
result = deserialize
418+
case "openid_provider_metadata":
419+
var deserialize OpenIDProviderMetadata
420+
err = metadata.FindEntityMetadata(testCase.metadataType, &deserialize)
421+
result = deserialize
422+
case "another_entity_metadata":
423+
var deserialize AnotherEntityMetadata
424+
err = metadata.FindEntityMetadata(testCase.metadataType, &deserialize)
425+
result = deserialize
426+
case "struct":
427+
var deserialize struct{}
428+
err = metadata.FindEntityMetadata(testCase.metadataType, &deserialize)
429+
result = deserialize
430+
case "struct name":
431+
var deserialize struct{ Name string }
432+
err = metadata.FindEntityMetadata(testCase.metadataType, &deserialize)
433+
result = deserialize
434+
default:
435+
err = metadata.FindEntityMetadata(testCase.metadataType, nil)
436+
}
437+
fmt.Printf("Result: %T %+v\n", result, result)
438+
373439
if testCase.shouldSucceed && err != nil {
374440
t.Error(err)
375441
} else if !testCase.shouldSucceed && err == nil {
376442
t.Errorf("finding %s metadata should fail", testCase.metadataType)
377-
t.Logf("%+v", testCase.deserializeInto)
443+
if result != nil {
444+
// t.Logf("%+v", reflect.ValueOf(testValue).Elem().Interface())
445+
t.Logf("%+v", result)
446+
}
447+
}
448+
449+
if testCase.expectedResult != nil && result != nil {
450+
if !reflect.DeepEqual(result, testCase.expectedResult) {
451+
t.Errorf(
452+
"Result not as expected.\nExpected: %T: %+v\n Got: %T: %+v",
453+
testCase.expectedResult,
454+
testCase.expectedResult,
455+
result,
456+
result,
457+
)
458+
}
378459
}
379460
},
380461
)

0 commit comments

Comments
 (0)