1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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)
}
}
}
|