| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "encoding/json" |
| 6 | "io" |
| 7 | "net/http" |
| 8 | "net/http/httptest" |
| 9 | "strings" |
| 10 | "testing" |
| 11 | ) |
| 12 | |
| 13 | // instanceCreate carries the config binding when one is asked for, and omits |
| 14 | // the key entirely when it is not — so a create from a caller that never |
| 15 | // heard of the flag is byte-identical to what it always sent. |
| 16 | func TestInstanceCreateSendsEnvironmentOnlyWhenGiven(t *testing.T) { |
| 17 | var gotBody string |
| 18 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 19 | b, _ := io.ReadAll(r.Body) |
| 20 | gotBody = string(b) |
| 21 | w.WriteHeader(http.StatusCreated) |
| 22 | json.NewEncoder(w).Encode(map[string]any{ |
| 23 | "host": "canary.example.com", "channel": "canary/x", "environment": "jam-canary", |
| 24 | }) |
| 25 | })) |
| 26 | defer ts.Close() |
| 27 | s := newTestSession(ts.URL) |
| 28 | |
| 29 | rec, err := s.instanceCreate(context.Background(), apiAcct{Seg: "bah"}, "app", |
| 30 | "canary.example.com", "", "canary/x", "", "jam-canary", nil, nil, nil) |
| 31 | if err != nil { |
| 32 | t.Fatalf("instanceCreate: %v", err) |
| 33 | } |
| 34 | if !strings.Contains(gotBody, `"environment":"jam-canary"`) { |
| 35 | t.Errorf("request body = %s, want it to carry the environment", gotBody) |
| 36 | } |
| 37 | // The decode matters as much as the send: `canary ls` prints this column, |
| 38 | // and the whole point of the column is that a wrong binding is otherwise |
| 39 | // invisible — the host serves GETs perfectly either way. |
| 40 | if rec.Environment != "jam-canary" { |
| 41 | t.Errorf("decoded environment = %q, want jam-canary", rec.Environment) |
| 42 | } |
| 43 | |
| 44 | gotBody = "" |
| 45 | if _, err := s.instanceCreate(context.Background(), apiAcct{Seg: "bah"}, "app", |
| 46 | "plain.example.com", "", "", "", "", nil, nil, nil); err != nil { |
| 47 | t.Fatalf("instanceCreate (no environment): %v", err) |
| 48 | } |
| 49 | if strings.Contains(gotBody, "environment") { |
| 50 | t.Errorf("request body = %s, want no environment key when none was given", gotBody) |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | // instanceSetEnvironment sends the field ALWAYS, empty string included: |
| 55 | // clearing a binding — returning a route to the app's default bundle — is a |
| 56 | // real request, and an omitempty here would silently turn it into a no-op |
| 57 | // PATCH the door then refuses as "nothing to update". |
| 58 | func TestInstanceSetEnvironmentSendsAnEmptyValue(t *testing.T) { |
| 59 | var gotBody, gotMethod string |
| 60 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 61 | gotMethod = r.Method |
| 62 | b, _ := io.ReadAll(r.Body) |
| 63 | gotBody = string(b) |
| 64 | json.NewEncoder(w).Encode(map[string]any{"host": "canary.example.com", "environment": ""}) |
| 65 | })) |
| 66 | defer ts.Close() |
| 67 | s := newTestSession(ts.URL) |
| 68 | |
| 69 | rec, err := s.instanceSetEnvironment(context.Background(), apiAcct{Seg: "bah"}, "app", |
| 70 | "canary.example.com", "") |
| 71 | if err != nil { |
| 72 | t.Fatalf("instanceSetEnvironment: %v", err) |
| 73 | } |
| 74 | if gotMethod != http.MethodPatch { |
| 75 | t.Errorf("method = %s, want PATCH — this rides the same door as set-upstreams", gotMethod) |
| 76 | } |
| 77 | if !strings.Contains(gotBody, `"environment":""`) { |
| 78 | t.Errorf("request body = %s, want an explicit empty environment", gotBody) |
| 79 | } |
| 80 | if rec.Environment != "" { |
| 81 | t.Errorf("decoded environment = %q, want empty", rec.Environment) |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | // environmentSuffix renders nothing for the default bundle. The empty case is |
| 86 | // the common one, and printing "environment default" on every create would |
| 87 | // train people to skim the parenthetical in the case that matters. |
| 88 | func TestEnvironmentSuffix(t *testing.T) { |
| 89 | for _, tc := range []struct{ env, want string }{ |
| 90 | {"", ""}, |
| 91 | {" ", ""}, |
| 92 | {"jam-canary", ", environment jam-canary"}, |
| 93 | } { |
| 94 | if got := environmentSuffix(tc.env); got != tc.want { |
| 95 | t.Errorf("environmentSuffix(%q) = %q, want %q", tc.env, got, tc.want) |
| 96 | } |
| 97 | } |
| 98 | } |
| 99 | |