package tentaclewire import ( "encoding/json" "git.stormux.org/storm/cthulhu/internal/interaction" "strings" "testing" ) func TestInteractionContract(t *testing.T) { form := &interaction.Form{Title: "Wormhole menu", Elements: []interaction.Element{{ID: "choices", Label: "Options", Kind: interaction.List, Items: []interaction.Item{{ID: "send", Label: "Send focused item"}}}}} for _, value := range []Interaction{ {Form: form, Next: "choice"}, {Form: form, Next: "choice", Poll: "status"}, {Source: "focus", Next: "send"}, {Source: "clipboard", Next: "send"}, {Presentation: Presentation{Speech: "Ready"}, Done: true}, {Done: true}, {}, } { data, _ := json.Marshal(value) if _, err := DecodeInteraction(data); err != nil { t.Fatalf("%s: %v", data, err) } } for _, raw := range []string{`null`, ` null `, `{"form":null}`, `{"clipboard":null}`, `{"unknown":true}`, `{"source":"desktop","next":"send"}`, `{"source":"focus"}`, `{"next":"send"}`, `{"poll":"status"}`, `{"speech":"bad\u0000"}`, `{"uninterruptible":true}`} { if _, err := DecodeInteraction([]byte(raw)); err == nil { t.Fatal("accepted", raw) } } for _, value := range []Interaction{{Form: form}, {Form: form, Next: "choice", Done: true}, {Form: form, Next: "choice", Source: "focus"}} { data, _ := json.Marshal(value) if _, err := DecodeInteraction(data); err == nil { t.Fatal("accepted", string(data)) } } copy := strings.Repeat("x", MaxPresentationBytes+1) data, _ := json.Marshal(Interaction{Clipboard: ©}) if _, err := DecodeInteraction(data); err == nil { t.Fatal("accepted oversized clipboard write") } form.Title = "Bad\x1btitle" data, _ = json.Marshal(Interaction{Form: form, Next: "choice"}) if _, err := DecodeInteraction(data); err == nil { t.Fatal("accepted control in title") } } func TestInteractionGrantsRemainExplicit(t *testing.T) { for _, apis := range [][]string{{"commands"}, {"commands", "presentation"}, {"commands", "presentation", "interaction"}} { if !ValidAPIs(apis, apis) { t.Fatal("rejected", apis) } } for _, apis := range [][]string{{"commands", "interaction"}, {"commands", "presentation", "unknown"}, {"commands", "interaction", "presentation"}} { if ValidAPIs(apis, apis) { t.Fatal("accepted", apis) } } if ValidAPIs([]string{"commands", "presentation", "interaction"}, []string{"commands", "presentation"}) { t.Fatal("missing grant accepted") } } func TestSecretInteractionContract(t *testing.T) { base := `{"form":{"title":"Connection","elements":[{"id":"key","label":"Channel key","kind":2,%s}]},"next":"connect"}` for _, flag := range []string{`"secret":true`, `"secret":false`} { value, err := DecodeInteraction([]byte(strings.Replace(base, "%s", flag, 1))) if err != nil || value.Form.Elements[0].Secret != (flag == `"secret":true`) { t.Fatal("valid secret flag rejected or changed") } } for _, flag := range []string{`"secret":null`, `"secret":1`, `"secret":"true"`, `"Secret":true`, `"secret":true,"secret":false`, `"secret":true,"Secret":false`, `"secret":true,"unknown":true`} { if _, err := DecodeInteraction([]byte(strings.Replace(base, "%s", flag, 1))); err == nil { t.Fatal("malformed secret flag accepted", flag) } } page := PreferencePage{ID: "connection", Title: "Connection", Command: "connect", Elements: []interaction.Element{{ID: "key", Label: "Channel key", Kind: interaction.Entry, Secret: true}}, Values: map[string]interaction.Value{"key": {Text: "fixture"}}} if ValidateExtensions(Extensions{Pages: []PreferencePage{page}}) == nil || ValidatePageValues(page, page.Values) == nil { t.Fatal("secret permitted in persistent page values") } }