package application import ( "errors" "image" "strings" "testing" ) func TestIconEventRoundTrip(t *testing.T) { reference := "sha256:" + strings.Repeat("A1", 32) identity, err := NewIconEventIdentity("request-1", "app-one", reference, 144) if err != nil { t.Fatalf("NewIconEventIdentity() error = %v", err) } if identity.Reference != strings.ToLower(reference) { t.Fatalf("canonical reference = %q", identity.Reference) } icon := image.NewNRGBA(image.Rect(0, 0, 24, 24)) ready, err := NewIconReadyEvent(identity, icon) if err != nil { t.Fatalf("NewIconReadyEvent() error = %v", err) } parsed, handled, err := ParseIconEvent(ready) if err != nil || !handled { t.Fatalf("ParseIconEvent(ready) = (%+v, %t, %v)", parsed, handled, err) } if parsed.Type != EventIconReady || parsed.Identity != identity || parsed.Image != icon { t.Fatalf("parsed ready event = %+v", parsed) } failed, err := NewIconFailedEvent(identity, IconFailureUnsafe) if err != nil { t.Fatalf("NewIconFailedEvent() error = %v", err) } parsed, handled, err = ParseIconEvent(failed) if err != nil || !handled { t.Fatalf("ParseIconEvent(failed) = (%+v, %t, %v)", parsed, handled, err) } if parsed.Type != EventIconFailed || parsed.Identity != identity || parsed.ErrorCode != IconFailureUnsafe { t.Fatalf("parsed failed event = %+v", parsed) } parsed, handled, err = ParseIconEvent(Event{Type: EventCatalogRefreshed}) if err != nil || handled { t.Fatalf("ParseIconEvent(non-icon) = (%+v, %t, %v)", parsed, handled, err) } } func TestIconEventRejectsInvalidIdentityAndPayload(t *testing.T) { validReference := "sha256:" + strings.Repeat("0a", 32) tests := []struct { name string requestID string appID string reference string dpi int }{ {name: "empty request", appID: "app", reference: validReference, dpi: 96}, {name: "empty app", requestID: "request", reference: validReference, dpi: 96}, {name: "bad reference", requestID: "request", appID: "app", reference: "md5:00", dpi: 96}, {name: "low DPI", requestID: "request", appID: "app", reference: validReference, dpi: 47}, {name: "high DPI", requestID: "request", appID: "app", reference: validReference, dpi: 769}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { _, err := NewIconEventIdentity( test.requestID, test.appID, test.reference, test.dpi, ) if !errors.Is(err, ErrInvalidIconEvent) { t.Fatalf("NewIconEventIdentity() error = %v", err) } }) } identity, err := NewIconEventIdentity("request", "app", validReference, 96) if err != nil { t.Fatal(err) } if _, err := NewIconReadyEvent(identity, nil); !errors.Is(err, ErrInvalidIconEvent) { t.Fatalf("NewIconReadyEvent(nil) error = %v", err) } var typedNil *image.NRGBA if _, err := NewIconReadyEvent(identity, typedNil); !errors.Is(err, ErrInvalidIconEvent) { t.Fatalf("NewIconReadyEvent(typed nil) error = %v", err) } if _, err := NewIconFailedEvent(identity, IconFailureCode("raw-http-error")); !errors.Is(err, ErrInvalidIconEvent) { t.Fatalf("NewIconFailedEvent(invalid code) error = %v", err) } invalidPayloads := []Event{ {Type: EventIconReady, RequestID: "request", AppID: "app", Payload: "wrong"}, {Type: EventIconFailed, RequestID: "request", AppID: "app", Payload: "wrong"}, { Type: EventIconReady, RequestID: "request", AppID: "app", Payload: IconReadyPayload{ Reference: validReference, DPI: 96, }, }, { Type: EventIconFailed, RequestID: "request", AppID: "app", Payload: IconFailedPayload{ Reference: validReference, DPI: 96, ErrorCode: IconFailureCode("raw"), }, }, } for _, event := range invalidPayloads { _, handled, err := ParseIconEvent(event) if !handled || !errors.Is(err, ErrInvalidIconEvent) { t.Fatalf("ParseIconEvent(%+v) handled=%t error=%v", event, handled, err) } } }