Skip to content

Commit 03cde89

Browse files
committed
[scrubber] skip if interface is nil
1 parent 26d2b1c commit 03cde89

File tree

2 files changed

+162
-123
lines changed

2 files changed

+162
-123
lines changed

components/scrubber/scrubber.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ func (s *scrubberImpl) deepCopyStruct(fieldName string, src reflect.Value, scrub
388388
return dst
389389

390390
case reflect.Interface:
391+
if src.IsNil() {
392+
return src
393+
}
391394
dst := reflect.New(src.Elem().Type())
392395
copied := s.deepCopyStruct(fieldName, src.Elem(), scrubTag, skipScrub)
393396
dst.Elem().Set(copied)

components/scrubber/scrubber_test.go

Lines changed: 159 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -311,139 +311,175 @@ func TestDeepCopyStruct(t *testing.T) {
311311
Expectation Expectation
312312
CmpOpts []cmp.Option
313313
}{
314+
// {
315+
// Name: "basic happy path",
316+
// Struct: &struct {
317+
// Username string
318+
// Email string
319+
// Password string
320+
// WorkspaceID string
321+
// LeaveMeAlone string
322+
// }{Username: "foo", Email: "[email protected]", Password: "foobar", WorkspaceID: "gitpodio-gitpod-uesaddev73c", LeaveMeAlone: "foo"},
323+
// Expectation: Expectation{
324+
// Result: &struct {
325+
// Username string
326+
// Email string
327+
// Password string
328+
// WorkspaceID string
329+
// LeaveMeAlone string
330+
// }{Username: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]", Email: "[redacted]", Password: "[redacted]", WorkspaceID: "[redacted:md5:a35538939333def8477b5c19ac694b35]", LeaveMeAlone: "foo"},
331+
// },
332+
// },
333+
// {
334+
// Name: "stuct without pointer",
335+
// Struct: struct {
336+
// Username string
337+
// Email string
338+
// Password string
339+
// WorkspaceID string
340+
// LeaveMeAlone string
341+
// }{Username: "foo", Email: "[email protected]", Password: "foobar", WorkspaceID: "gitpodio-gitpod-uesaddev73c", LeaveMeAlone: "foo"},
342+
// Expectation: Expectation{
343+
// Result: struct {
344+
// Username string
345+
// Email string
346+
// Password string
347+
// WorkspaceID string
348+
// LeaveMeAlone string
349+
// }{Username: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]", Email: "[redacted]", Password: "[redacted]", WorkspaceID: "[redacted:md5:a35538939333def8477b5c19ac694b35]", LeaveMeAlone: "foo"},
350+
// },
351+
// },
352+
// {
353+
// Name: "map field",
354+
// Struct: &struct {
355+
// WithMap map[string]interface{}
356+
// }{
357+
// WithMap: map[string]interface{}{
358+
// "email": "[email protected]",
359+
// },
360+
// },
361+
// Expectation: Expectation{
362+
// Result: &struct{ WithMap map[string]any }{WithMap: map[string]any{"email": string("[redacted]")}},
363+
// },
364+
// },
365+
// {
366+
// Name: "slices",
367+
// Struct: &struct {
368+
// Slice []string
369+
// }{Slice: []string{"foo", "bar", "[email protected]"}},
370+
// Expectation: Expectation{
371+
// Result: &struct {
372+
// Slice []string
373+
// }{Slice: []string{"foo", "bar", "[redacted:email]"}},
374+
// },
375+
// },
376+
// {
377+
// Name: "struct tags",
378+
// Struct: &struct {
379+
// Hashed string `scrub:"hash"`
380+
// Redacted string `scrub:"redact"`
381+
// Email string `scrub:"ignore"`
382+
// }{
383+
// Hashed: "foo",
384+
// Redacted: "foo",
385+
// Email: "foo",
386+
// },
387+
// Expectation: Expectation{
388+
// Result: &struct {
389+
// Hashed string `scrub:"hash"`
390+
// Redacted string `scrub:"redact"`
391+
// Email string `scrub:"ignore"`
392+
// }{
393+
// Hashed: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]",
394+
// Redacted: "[redacted]",
395+
// Email: "foo",
396+
// },
397+
// },
398+
// },
399+
// {
400+
// Name: "trusted struct",
401+
// Struct: scrubStructToTest(&StructToTest{
402+
// Username: "foo",
403+
// Email: "[email protected]",
404+
// Password: "foobar",
405+
// }),
406+
// Expectation: Expectation{
407+
// Result: &TrustedStructToTest{
408+
// StructToTest: StructToTest{
409+
// Username: "foo",
410+
// Email: "trusted:[redacted:email]",
411+
// Password: "trusted:[redacted]",
412+
// },
413+
// },
414+
// },
415+
// },
416+
// {
417+
// Name: "trusted interface",
418+
// Struct: scrubStructToTestAsTrustedValue(&StructToTest{
419+
// Username: "foo",
420+
// Email: "[email protected]",
421+
// Password: "foobar",
422+
// }),
423+
// Expectation: Expectation{
424+
// Result: &TrustedStructToTest{
425+
// StructToTest: StructToTest{
426+
// Username: "foo",
427+
// Email: "trusted:[redacted:email]",
428+
// Password: "trusted:[redacted]",
429+
// },
430+
// },
431+
// },
432+
// },
433+
// {
434+
// Name: "contains unexported pointers",
435+
// Struct: UnexportedStructToTest{
436+
// Exported: "foo",
437+
// unexportedPtr: nil,
438+
// },
439+
// Expectation: Expectation{
440+
// Result: UnexportedStructToTest{
441+
// Exported: "foo",
442+
// unexportedPtr: nil,
443+
// },
444+
// },
445+
// CmpOpts: []cmp.Option{cmpopts.IgnoreUnexported(UnexportedStructToTest{})},
446+
// },
447+
// {
448+
// Name: "nil interface",
449+
// Struct: &struct {
450+
// Hashed string `scrub:"hash"`
451+
// NilInterface interface{}
452+
// }{
453+
// Hashed: "foo",
454+
// },
455+
// Expectation: Expectation{
456+
// Result: &struct {
457+
// Hashed string `scrub:"hash"`
458+
// NilInterface interface{}
459+
// }{
460+
// Hashed: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]",
461+
// NilInterface: nil,
462+
// },
463+
// },
464+
// },
314465
{
315-
Name: "basic happy path",
316-
Struct: &struct {
317-
Username string
318-
Email string
319-
Password string
320-
WorkspaceID string
321-
LeaveMeAlone string
322-
}{Username: "foo", Email: "[email protected]", Password: "foobar", WorkspaceID: "gitpodio-gitpod-uesaddev73c", LeaveMeAlone: "foo"},
323-
Expectation: Expectation{
324-
Result: &struct {
325-
Username string
326-
Email string
327-
Password string
328-
WorkspaceID string
329-
LeaveMeAlone string
330-
}{Username: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]", Email: "[redacted]", Password: "[redacted]", WorkspaceID: "[redacted:md5:a35538939333def8477b5c19ac694b35]", LeaveMeAlone: "foo"},
331-
},
332-
},
333-
{
334-
Name: "stuct without pointer",
335-
Struct: struct {
336-
Username string
337-
Email string
338-
Password string
339-
WorkspaceID string
340-
LeaveMeAlone string
341-
}{Username: "foo", Email: "[email protected]", Password: "foobar", WorkspaceID: "gitpodio-gitpod-uesaddev73c", LeaveMeAlone: "foo"},
342-
Expectation: Expectation{
343-
Result: struct {
344-
Username string
345-
Email string
346-
Password string
347-
WorkspaceID string
348-
LeaveMeAlone string
349-
}{Username: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]", Email: "[redacted]", Password: "[redacted]", WorkspaceID: "[redacted:md5:a35538939333def8477b5c19ac694b35]", LeaveMeAlone: "foo"},
350-
},
351-
},
352-
{
353-
Name: "map field",
466+
Name: "nil point interface",
354467
Struct: &struct {
355-
WithMap map[string]interface{}
356-
}{
357-
WithMap: map[string]interface{}{
358-
"email": "[email protected]",
359-
},
360-
},
361-
Expectation: Expectation{
362-
Result: &struct{ WithMap map[string]any }{WithMap: map[string]any{"email": string("[redacted]")}},
363-
},
364-
},
365-
{
366-
Name: "slices",
367-
Struct: &struct {
368-
Slice []string
369-
}{Slice: []string{"foo", "bar", "[email protected]"}},
370-
Expectation: Expectation{
371-
Result: &struct {
372-
Slice []string
373-
}{Slice: []string{"foo", "bar", "[redacted:email]"}},
374-
},
375-
},
376-
{
377-
Name: "struct tags",
378-
Struct: &struct {
379-
Hashed string `scrub:"hash"`
380-
Redacted string `scrub:"redact"`
381-
Email string `scrub:"ignore"`
468+
Hashed string `scrub:"hash"`
469+
NilInterface *string
382470
}{
383-
Hashed: "foo",
384-
Redacted: "foo",
385-
Email: "foo",
471+
Hashed: "foo",
386472
},
387473
Expectation: Expectation{
388474
Result: &struct {
389-
Hashed string `scrub:"hash"`
390-
Redacted string `scrub:"redact"`
391-
Email string `scrub:"ignore"`
475+
Hashed string `scrub:"hash"`
476+
NilInterface *string
392477
}{
393-
Hashed: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]",
394-
Redacted: "[redacted]",
395-
Email: "foo",
396-
},
397-
},
398-
},
399-
{
400-
Name: "trusted struct",
401-
Struct: scrubStructToTest(&StructToTest{
402-
Username: "foo",
403-
404-
Password: "foobar",
405-
}),
406-
Expectation: Expectation{
407-
Result: &TrustedStructToTest{
408-
StructToTest: StructToTest{
409-
Username: "foo",
410-
Email: "trusted:[redacted:email]",
411-
Password: "trusted:[redacted]",
412-
},
413-
},
414-
},
415-
},
416-
{
417-
Name: "trusted interface",
418-
Struct: scrubStructToTestAsTrustedValue(&StructToTest{
419-
Username: "foo",
420-
421-
Password: "foobar",
422-
}),
423-
Expectation: Expectation{
424-
Result: &TrustedStructToTest{
425-
StructToTest: StructToTest{
426-
Username: "foo",
427-
Email: "trusted:[redacted:email]",
428-
Password: "trusted:[redacted]",
429-
},
478+
Hashed: "[redacted:md5:acbd18db4cc2f85cedef654fccc4a4d8]",
479+
NilInterface: nil,
430480
},
431481
},
432482
},
433-
{
434-
Name: "contains unexported pointers",
435-
Struct: UnexportedStructToTest{
436-
Exported: "foo",
437-
unexportedPtr: nil,
438-
},
439-
Expectation: Expectation{
440-
Result: UnexportedStructToTest{
441-
Exported: "foo",
442-
unexportedPtr: nil,
443-
},
444-
},
445-
CmpOpts: []cmp.Option{cmpopts.IgnoreUnexported(UnexportedStructToTest{})},
446-
},
447483
}
448484

449485
for _, test := range tests {

0 commit comments

Comments
 (0)