diff options
| author | tsne <tsne.dev@outlook.com> | 2026-07-06 16:52:20 +0200 |
|---|---|---|
| committer | tsne <tsne.dev@outlook.com> | 2026-07-06 21:37:42 +0200 |
| commit | 84da43998f7cc42cc72652333ac6e3d293abb23e (patch) | |
| tree | 6610f82df854ae86f7f34152bb05fc712ef6f314 /internal/source/source_test.go | |
| download | hopper-main.tar.gz | |
Diffstat (limited to 'internal/source/source_test.go')
| -rw-r--r-- | internal/source/source_test.go | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/internal/source/source_test.go b/internal/source/source_test.go new file mode 100644 index 0000000..933c67a --- /dev/null +++ b/internal/source/source_test.go @@ -0,0 +1,95 @@ +package source + +import ( + "bytes" + "io" + "testing" + + "tsne.dev/hopper/internal/log" +) + +func TestCleanArchivePath(t *testing.T) { + tests := []struct { + raw string + want string + wantErr bool + warn bool + }{ + {"a/b.js", "a/b.js", false, false}, + {"./a//b.js", "a/b.js", false, false}, + {"/abs/x", "", true, false}, + {"../escape", "", true, false}, + {"a/../../escape", "", true, false}, + {"a/../b.js", "b.js", false, true}, // contained .. but stays in root + } + for _, tt := range tests { + var warn bytes.Buffer + log.Init(io.Discard, &warn) + got, err := cleanArchivePath(tt.raw) + if tt.wantErr { + if err == nil { + t.Errorf("%q: expected error", tt.raw) + } + continue + } + if err != nil { + t.Errorf("%q: unexpected error %v", tt.raw, err) + continue + } + if got != tt.want { + t.Errorf("%q: got %q want %q", tt.raw, got, tt.want) + } + if tt.warn && warn.Len() == 0 { + t.Errorf("%q: expected warning", tt.raw) + } + if !tt.warn && warn.Len() != 0 { + t.Errorf("%q: unexpected warning %q", tt.raw, warn.String()) + } + } +} + +func TestSelectPath(t *testing.T) { + tests := []struct { + cleaned string + root string + want string + wantOK bool + }{ + {"assets/x.js", "", "assets/x.js", true}, + {"README.md", "", "README.md", true}, + {"app/assets/x.js", "app", "assets/x.js", true}, + {"README.md", "app", "", false}, + {"app", "app", "", false}, + {"appendix/x", "app", "", false}, + {"dist/public/index.html", "dist/public", "index.html", true}, + {"dist/private/x", "dist/public", "", false}, + } + for _, tt := range tests { + s := &TarGzSource{root: tt.root} + got, ok := s.selectPath(tt.cleaned) + if ok != tt.wantOK { + t.Errorf("selectPath(%q, %q): ok = %v, want %v", tt.cleaned, tt.root, ok, tt.wantOK) + continue + } + if ok && got != tt.want { + t.Errorf("selectPath(%q, %q) = %q, want %q", tt.cleaned, tt.root, got, tt.want) + } + } +} + +func TestContainsDotDot(t *testing.T) { + cases := map[string]bool{ + "a/b/c": false, + "..": true, + "../x": true, + "a/../b": true, + "a/..b/c": false, + "": false, + "a/b/..": true, + } + for in, want := range cases { + if got := containsDotDot(in); got != want { + t.Errorf("containsDotDot(%q) = %v, want %v", in, got, want) + } + } +} |