1package checkpoint 2 3import ( 4 "net/http" 5 "net/http/httptest" 6 "net/url" 7 "path" 8 "testing" 9 10 "github.com/google/go-cmp/cmp" 11) 12 13func TestInvalidCheckpointFormat(t *testing.T) { 14 tests := []struct { 15 desc string 16 m string 17 wantErr bool 18 }{ 19 { 20 desc: "unknown origin", 21 m: "UNKNOWN\n1\nbananas\n", 22 wantErr: true, 23 }, 24 { 25 desc: "bad size", 26 m: "developers.google.com/android/binary_transparency/0\n-1\nbananas\n", 27 wantErr: true, 28 }, 29 { 30 desc: "not enough newlines", 31 m: "developers.google.com/android/binary_transparency/0\n1\n", 32 wantErr: true, 33 }, 34 { 35 desc: "non-numeric size", 36 m: "developers.google.com/android/binary_transparency/0\nbananas\ndGhlIHZpZXcgZnJvbSB0aGUgdHJlZSB0b3BzIGlzIGdyZWF0IQ==\n", 37 wantErr: true, 38 }, 39 { 40 desc: "too many newlines", 41 m: "developers.google.com/android/binary_transparency/0\n1\n\n\n\n", 42 wantErr: true, 43 }, 44 { 45 desc: "does not end with newline", 46 m: "developers.google.com/android/binary_transparency/0\n1\ngarbage", 47 wantErr: true, 48 }, 49 { 50 desc: "invalid - empty header", 51 m: "\n9944\ndGhlIHZpZXcgZnJvbSB0aGUgdHJlZSB0b3BzIGlzIGdyZWF0IQ==\n", 52 wantErr: true, 53 }, 54 } 55 56 for _, tt := range tests { 57 t.Run(tt.desc, func(t *testing.T) { 58 if _, gotErr := parseCheckpoint(tt.m); gotErr == nil { 59 t.Fatalf("fromText(%v): want error, got nil", tt.m) 60 } 61 }) 62 } 63} 64 65// testServer serves a test envelope `e` at path "test/file" and 404 otherwise. 66// It is used to minimally test FromURL. 67func testServer(t *testing.T, e string) *httptest.Server { 68 t.Helper() 69 return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 70 if r.URL.String() == "/test/file/checkpoint.txt" { 71 w.Write([]byte(e)) 72 } else { 73 w.WriteHeader(http.StatusNotFound) 74 } 75 })) 76} 77 78// TestGetSignedCheckpoint is a minimal test to check URL I/O. 79// Content specific tests are done in the other tests. 80func TestGetSignedCheckpoint(t *testing.T) { 81 serverContent := "testContent" 82 s := testServer(t, serverContent) 83 u, err := url.Parse(s.URL) 84 if err != nil { 85 t.Fatalf("invalid URL for testServer %s: %v", s.URL, err) 86 } 87 defer s.Close() 88 89 for _, tt := range []struct { 90 desc string 91 path string 92 want string 93 wantErr bool 94 }{ 95 { 96 desc: "good_file", 97 path: "test/file", 98 want: serverContent, 99 wantErr: false, 100 }, 101 { 102 desc: "bad_path", 103 path: "bad/path", 104 wantErr: true, 105 }, 106 } { 107 t.Run(tt.desc, func(t *testing.T) { 108 u.Path = path.Join(u.Path, tt.path) 109 b, gotErr := getSignedCheckpoint(u.String()) 110 got := string(b) 111 if diff := cmp.Diff(got, tt.want); diff != "" { 112 t.Errorf("bad response body: got %v, want %v", got, tt.want) 113 } 114 if gotErr != nil && !tt.wantErr { 115 t.Errorf("unexpected error: got %t, want %t", gotErr, tt.wantErr) 116 } 117 }) 118 } 119} 120