| 1 | package hostops |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | // TestClassifyAccountLimitsRecordIsExact: the console's per-account limits |
| 10 | // record (plans-caps-packs spec §7) is a reviewed non-app family. It is only |
| 11 | // ever put; nothing deletes it, and nothing else under accounts/<sqid>/ rides |
| 12 | // on its classification. |
| 13 | func TestClassifyAccountLimitsRecordIsExact(t *testing.T) { |
| 14 | ctx := context.Background() |
| 15 | key := "accounts/bab/limits.json" |
| 16 | for _, c := range []struct { |
| 17 | name string |
| 18 | target MutationTarget |
| 19 | }{ |
| 20 | {"first put", MutationTarget{Surface: "bucket", Method: "Put", Key: key, After: []byte(`{}`)}}, |
| 21 | {"replacing put", MutationTarget{Surface: "bucket", Method: "Put", Key: key, ETag: "x", Before: []byte(`{}`), After: []byte(`{}`)}}, |
| 22 | } { |
| 23 | got, err := ClassifyMutation(ctx, nil, nil, c.target) |
| 24 | if err != nil { |
| 25 | t.Errorf("%s: %v", c.name, err) |
| 26 | continue |
| 27 | } |
| 28 | if got.Family != "account-limits" || got.NonApp == "" || len(got.Scopes) != 0 || got.MailGate { |
| 29 | t.Errorf("%s: classified %+v, want non-app family account-limits with no scopes", c.name, got) |
| 30 | } |
| 31 | } |
| 32 | for _, c := range []struct { |
| 33 | name string |
| 34 | target MutationTarget |
| 35 | }{ |
| 36 | {"a delete", MutationTarget{Surface: "bucket", Method: "Delete", Key: key}}, |
| 37 | {"an invalid account", MutationTarget{Surface: "bucket", Method: "Put", Key: "accounts/BAB!/limits.json", After: []byte(`{}`)}}, |
| 38 | {"a deeper key", MutationTarget{Surface: "bucket", Method: "Put", Key: "accounts/bab/x/limits.json", After: []byte(`{}`)}}, |
| 39 | {"a lookalike name", MutationTarget{Surface: "bucket", Method: "Put", Key: "accounts/bab/limits.json.bak", After: []byte(`{}`)}}, |
| 40 | } { |
| 41 | if got, err := ClassifyMutation(ctx, nil, nil, c.target); !errors.Is(err, ErrUnclassified) { |
| 42 | t.Errorf("%s: classified %+v, err %v; want ErrUnclassified", c.name, got, err) |
| 43 | } |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | // TestClassifyPlansMarkerIsExact: the console's deployment marker (plans 2) |
| 48 | // is a reviewed non-app family, put only. |
| 49 | func TestClassifyPlansMarkerIsExact(t *testing.T) { |
| 50 | ctx := context.Background() |
| 51 | key := "control/plans.json" |
| 52 | got, err := ClassifyMutation(ctx, nil, nil, MutationTarget{Surface: "bucket", Method: "Put", Key: key, After: []byte(`{}`)}) |
| 53 | if err != nil || got.NonApp == "" || len(got.Scopes) != 0 { |
| 54 | t.Fatalf("put: %+v, %v; want a non-app family", got, err) |
| 55 | } |
| 56 | for _, c := range []MutationTarget{ |
| 57 | {Surface: "bucket", Method: "Delete", Key: key}, |
| 58 | {Surface: "bucket", Method: "Put", Key: "control/plans.json.bak", After: []byte(`{}`)}, |
| 59 | {Surface: "bucket", Method: "Put", Key: "control/plans", After: []byte(`{}`)}, |
| 60 | } { |
| 61 | if got, err := ClassifyMutation(ctx, nil, nil, c); !errors.Is(err, ErrUnclassified) { |
| 62 | t.Errorf("%s %s: classified %+v, err %v; want ErrUnclassified", c.Method, c.Key, got, err) |
| 63 | } |
| 64 | } |
| 65 | } |
| 66 | |