| 1 | package hostops |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "testing" |
| 7 | |
| 8 | "github.com/carlosframework/platform/internal/release" |
| 9 | ) |
| 10 | |
| 11 | // TestClassifyPromotionRecordIsExact: a build's signed promotion record, |
| 12 | // releases/<acct>/<app>/promoted/<version> (settings plan 2, spec §4.1), is |
| 13 | // a reviewed family scoped to exactly its app, put and deleted; nothing |
| 14 | // else under releases/<acct>/<app>/ is. |
| 15 | func TestClassifyPromotionRecordIsExact(t *testing.T) { |
| 16 | ctx := context.Background() |
| 17 | key := release.PromotionRecordKey("bab", "km", "v1") |
| 18 | for _, c := range []struct { |
| 19 | name string |
| 20 | target MutationTarget |
| 21 | }{ |
| 22 | {"record put", MutationTarget{Surface: "bucket", Method: "Put", Key: key, After: []byte(`{}`)}}, |
| 23 | {"record put over an existing one", MutationTarget{Surface: "bucket", Method: "Put", Key: key, ETag: "x", Before: []byte(`{}`), After: []byte(`{}`)}}, |
| 24 | {"record delete", MutationTarget{Surface: "bucket", Method: "Delete", Key: key}}, |
| 25 | } { |
| 26 | got, err := ClassifyMutation(ctx, nil, nil, c.target) |
| 27 | if err != nil { |
| 28 | t.Errorf("%s: %v", c.name, err) |
| 29 | continue |
| 30 | } |
| 31 | if got.Family != "promotion-record" || got.NonApp != "" || got.MailGate || |
| 32 | len(got.Scopes) != 1 || got.Scopes[0] != (AppScope{"bab", "km"}) { |
| 33 | t.Errorf("%s: classified %+v, want family promotion-record scoped to exactly {bab km}", c.name, got) |
| 34 | } |
| 35 | } |
| 36 | for _, c := range []struct { |
| 37 | name string |
| 38 | target MutationTarget |
| 39 | }{ |
| 40 | {"an invalid account", MutationTarget{Surface: "bucket", Method: "Put", Key: "releases/BAB!/km/promoted/v1", After: []byte(`{}`)}}, |
| 41 | {"an invalid app", MutationTarget{Surface: "bucket", Method: "Put", Key: "releases/bab/KM!/promoted/v1", After: []byte(`{}`)}}, |
| 42 | {"an empty version", MutationTarget{Surface: "bucket", Method: "Put", Key: "releases/bab/km/promoted/", After: []byte(`{}`)}}, |
| 43 | {"a sixth segment", MutationTarget{Surface: "bucket", Method: "Put", Key: key + "/x", After: []byte(`{}`)}}, |
| 44 | {"no version", MutationTarget{Surface: "bucket", Method: "Put", Key: "releases/bab/km/promoted", After: []byte(`{}`)}}, |
| 45 | {"another name under the app", MutationTarget{Surface: "bucket", Method: "Put", Key: "releases/bab/km/other/v1", After: []byte(`{}`)}}, |
| 46 | {"the dev version", MutationTarget{Surface: "bucket", Method: "Put", Key: "releases/bab/km/promoted/dev", After: []byte(`{}`)}}, |
| 47 | {"a delete-if-match", MutationTarget{Surface: "bucket", Method: "DeleteIfMatch", Key: key, ETag: "x"}}, |
| 48 | } { |
| 49 | got, err := ClassifyMutation(ctx, nil, nil, c.target) |
| 50 | if !errors.Is(err, ErrUnclassified) && !errors.Is(err, ErrIdentity) { |
| 51 | t.Errorf("%s: classified %+v, err %v; want ErrUnclassified or ErrIdentity", c.name, got, err) |
| 52 | } |
| 53 | } |
| 54 | } |
| 55 | |