xref: /aosp_15_r20/external/avb/tools/transparency/verify/internal/checkpoint/checkpoint_test.go (revision d289c2ba6de359471b23d594623b906876bc48a0)
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