A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
1package appview
2
3import (
4 "io/fs"
5 "testing"
6 "testing/fstest"
7)
8
9func TestOverlayFS_Open_UpperWins(t *testing.T) {
10 lower := fstest.MapFS{
11 "file.txt": &fstest.MapFile{Data: []byte("lower")},
12 }
13 upper := fstest.MapFS{
14 "file.txt": &fstest.MapFile{Data: []byte("upper")},
15 }
16
17 ofs := newOverlayFS(upper, lower)
18
19 data, err := fs.ReadFile(ofs, "file.txt")
20 if err != nil {
21 t.Fatal(err)
22 }
23 if string(data) != "upper" {
24 t.Errorf("expected upper content, got %q", data)
25 }
26}
27
28func TestOverlayFS_Open_FallbackToLower(t *testing.T) {
29 lower := fstest.MapFS{
30 "only-lower.txt": &fstest.MapFile{Data: []byte("lower")},
31 }
32 upper := fstest.MapFS{}
33
34 ofs := newOverlayFS(upper, lower)
35
36 data, err := fs.ReadFile(ofs, "only-lower.txt")
37 if err != nil {
38 t.Fatal(err)
39 }
40 if string(data) != "lower" {
41 t.Errorf("expected lower content, got %q", data)
42 }
43}
44
45func TestOverlayFS_Open_UpperOnly(t *testing.T) {
46 lower := fstest.MapFS{}
47 upper := fstest.MapFS{
48 "only-upper.txt": &fstest.MapFile{Data: []byte("upper")},
49 }
50
51 ofs := newOverlayFS(upper, lower)
52
53 data, err := fs.ReadFile(ofs, "only-upper.txt")
54 if err != nil {
55 t.Fatal(err)
56 }
57 if string(data) != "upper" {
58 t.Errorf("expected upper content, got %q", data)
59 }
60}
61
62func TestOverlayFS_Open_NotFound(t *testing.T) {
63 lower := fstest.MapFS{}
64 upper := fstest.MapFS{}
65
66 ofs := newOverlayFS(upper, lower)
67
68 _, err := ofs.Open("missing.txt")
69 if err == nil {
70 t.Fatal("expected error for missing file")
71 }
72}
73
74func TestOverlayFS_ReadDir_Merge(t *testing.T) {
75 lower := fstest.MapFS{
76 "dir/a.txt": &fstest.MapFile{Data: []byte("a-lower")},
77 "dir/b.txt": &fstest.MapFile{Data: []byte("b-lower")},
78 }
79 upper := fstest.MapFS{
80 "dir/b.txt": &fstest.MapFile{Data: []byte("b-upper")},
81 "dir/c.txt": &fstest.MapFile{Data: []byte("c-upper")},
82 }
83
84 ofs := newOverlayFS(upper, lower)
85 rdfs, ok := ofs.(fs.ReadDirFS)
86 if !ok {
87 t.Fatal("overlayFS does not implement ReadDirFS")
88 }
89
90 entries, err := rdfs.ReadDir("dir")
91 if err != nil {
92 t.Fatal(err)
93 }
94
95 // Should have a.txt (lower), b.txt (upper), c.txt (upper) = 3 entries
96 if len(entries) != 3 {
97 t.Fatalf("expected 3 entries, got %d", len(entries))
98 }
99
100 names := make([]string, len(entries))
101 for i, e := range entries {
102 names[i] = e.Name()
103 }
104
105 expected := []string{"a.txt", "b.txt", "c.txt"}
106 for i, name := range expected {
107 if names[i] != name {
108 t.Errorf("entry %d: expected %q, got %q", i, name, names[i])
109 }
110 }
111
112 // Verify b.txt content comes from upper
113 data, err := fs.ReadFile(ofs, "dir/b.txt")
114 if err != nil {
115 t.Fatal(err)
116 }
117 if string(data) != "b-upper" {
118 t.Errorf("expected b-upper, got %q", data)
119 }
120}
121
122func TestOverlayFS_ReadFile(t *testing.T) {
123 lower := fstest.MapFS{
124 "file.txt": &fstest.MapFile{Data: []byte("lower")},
125 }
126 upper := fstest.MapFS{
127 "file.txt": &fstest.MapFile{Data: []byte("upper")},
128 }
129
130 ofs := newOverlayFS(upper, lower)
131 rffs, ok := ofs.(fs.ReadFileFS)
132 if !ok {
133 t.Fatal("overlayFS does not implement ReadFileFS")
134 }
135
136 data, err := rffs.ReadFile("file.txt")
137 if err != nil {
138 t.Fatal(err)
139 }
140 if string(data) != "upper" {
141 t.Errorf("expected upper, got %q", data)
142 }
143}