Skip to content
This repository was archived by the owner on Mar 29, 2023. It is now read-only.

Commit 118a00e

Browse files
authored
Merge pull request #6 from ipfs/fix/5
create implicit directories from multipart requests
2 parents 267cdfe + 57067a8 commit 118a00e

File tree

4 files changed

+316
-274
lines changed

4 files changed

+316
-274
lines changed

file_test.go

+80-116
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,24 @@ func TestSliceFiles(t *testing.T) {
1313
"2": NewBytesFile([]byte("beep")),
1414
"3": NewBytesFile([]byte("boop")),
1515
})
16-
buf := make([]byte, 20)
1716

18-
it := sf.Entries()
19-
20-
if !it.Next() {
21-
t.Fatal("Expected a file")
22-
}
23-
rf := ToFile(it.Node())
24-
if rf == nil {
25-
t.Fatal("Expected a regular file")
26-
}
27-
read, err := rf.Read(buf)
28-
if read != 11 || err != nil {
29-
t.Fatal("NextFile got a file in the wrong order")
30-
}
31-
32-
if !it.Next() {
33-
t.Fatal("Expected a file")
34-
}
35-
if !it.Next() {
36-
t.Fatal("Expected a file")
37-
}
38-
if it.Next() {
39-
t.Fatal("Wild file appeared!")
40-
}
41-
42-
if err := sf.Close(); err != nil {
43-
t.Fatal("Should be able to call `Close` on a SliceFile")
44-
}
17+
CheckDir(t, sf, []Event{
18+
{
19+
kind: TFile,
20+
name: "1",
21+
value: "Some text!\n",
22+
},
23+
{
24+
kind: TFile,
25+
name: "2",
26+
value: "beep",
27+
},
28+
{
29+
kind: TFile,
30+
name: "3",
31+
value: "boop",
32+
},
33+
})
4534
}
4635

4736
func TestReaderFiles(t *testing.T) {
@@ -59,7 +48,6 @@ func TestReaderFiles(t *testing.T) {
5948
t.Fatal("Expected EOF when reading after close")
6049
}
6150
}
62-
6351
func TestMultipartFiles(t *testing.T) {
6452
data := `
6553
--Boundary!
@@ -82,97 +70,73 @@ Content-Type: application/symlink
8270
Content-Disposition: file; filename="dir/simlynk"
8371
8472
anotherfile
73+
--Boundary!
74+
Content-Type: text/plain
75+
Content-Disposition: file; filename="implicit1/implicit2/deep_implicit"
76+
77+
implicit file1
78+
--Boundary!
79+
Content-Type: text/plain
80+
Content-Disposition: file; filename="implicit1/shallow_implicit"
81+
82+
implicit file2
8583
--Boundary!--
8684
8785
`
8886

8987
reader := strings.NewReader(data)
9088
mpReader := multipart.NewReader(reader, "Boundary!")
91-
buf := make([]byte, 20)
92-
93-
// test properties of a file created from the first part
94-
part, err := mpReader.NextPart()
95-
if part == nil || err != nil {
96-
t.Fatal("Expected non-nil part, nil error")
97-
}
98-
mpname, mpf, err := newFileFromPart("", part, &peekReader{r: mpReader})
99-
if mpf == nil || err != nil {
100-
t.Fatal("Expected non-nil multipartFile, nil error")
101-
}
102-
mf, ok := mpf.(File)
103-
if !ok {
104-
t.Fatal("Expected file to not be a directory")
105-
}
106-
if mpname != "name" {
107-
t.Fatal("Expected filename to be \"name\"")
108-
}
109-
if n, err := mf.Read(buf); n != 4 || !(err == io.EOF || err == nil) {
110-
t.Fatal("Expected to be able to read 4 bytes", n, err)
111-
}
112-
if err := mf.Close(); err != nil {
113-
t.Fatal("Expected to be able to close file")
114-
}
115-
116-
// test properties of file created from second part (directory)
117-
part, err = mpReader.NextPart()
118-
if part == nil || err != nil {
119-
t.Fatal("Expected non-nil part, nil error")
120-
}
121-
mpname, mpf, err = newFileFromPart("", part, &peekReader{r: mpReader})
122-
if mpf == nil || err != nil {
123-
t.Fatal("Expected non-nil multipartFile, nil error")
124-
}
125-
md, ok := mpf.(Directory)
126-
if !ok {
127-
t.Fatal("Expected file to be a directory")
128-
}
129-
if mpname != "dir" {
130-
t.Fatal("Expected filename to be \"dir\"")
131-
}
132-
if err := md.Close(); err != nil {
133-
t.Fatal("Should be able to call `Close` on a directory")
134-
}
135-
136-
// test properties of file created from third part (nested file)
137-
part, err = mpReader.NextPart()
138-
if part == nil || err != nil {
139-
t.Fatal("Expected non-nil part, nil error")
140-
}
141-
mpname, mpf, err = newFileFromPart("dir/", part, &peekReader{r: mpReader})
142-
if mpf == nil || err != nil {
143-
t.Fatal("Expected non-nil multipartFile, nil error")
144-
}
145-
mf, ok = mpf.(File)
146-
if !ok {
147-
t.Fatal("Expected file to not be a directory")
148-
}
149-
if mpname != "nested" {
150-
t.Fatalf("Expected filename to be \"nested\", got %s", mpname)
151-
}
152-
if n, err := mf.Read(buf); n != 12 || !(err == nil || err == io.EOF) {
153-
t.Fatalf("expected to be able to read 12 bytes from file: %s (got %d)", err, n)
154-
}
155-
if err := mpf.Close(); err != nil {
156-
t.Fatalf("should be able to close file: %s", err)
157-
}
158-
159-
// test properties of symlink created from fourth part (symlink)
160-
part, err = mpReader.NextPart()
161-
if part == nil || err != nil {
162-
t.Fatal("Expected non-nil part, nil error")
163-
}
164-
mpname, mpf, err = newFileFromPart("dir/", part, &peekReader{r: mpReader})
165-
if mpf == nil || err != nil {
166-
t.Fatal("Expected non-nil multipartFile, nil error")
167-
}
168-
ms, ok := mpf.(*Symlink)
169-
if !ok {
170-
t.Fatal("Expected file to not be a directory")
171-
}
172-
if mpname != "simlynk" {
173-
t.Fatal("Expected filename to be \"dir/simlynk\"")
174-
}
175-
if ms.Target != "anotherfile" {
176-
t.Fatal("expected link to point to anotherfile")
177-
}
89+
dir, err := NewFileFromPartReader(mpReader, multipartFormdataType)
90+
if err != nil {
91+
t.Fatal(err)
92+
}
93+
94+
CheckDir(t, dir, []Event{
95+
{
96+
kind: TFile,
97+
name: "name",
98+
value: "beep",
99+
},
100+
{
101+
kind: TDirStart,
102+
name: "dir",
103+
},
104+
{
105+
kind: TFile,
106+
name: "nested",
107+
value: "some content",
108+
},
109+
{
110+
kind: TSymlink,
111+
name: "simlynk",
112+
value: "anotherfile",
113+
},
114+
{
115+
kind: TDirEnd,
116+
},
117+
{
118+
kind: TDirStart,
119+
name: "implicit1",
120+
},
121+
{
122+
kind: TDirStart,
123+
name: "implicit2",
124+
},
125+
{
126+
kind: TFile,
127+
name: "deep_implicit",
128+
value: "implicit file1",
129+
},
130+
{
131+
kind: TDirEnd,
132+
},
133+
{
134+
kind: TFile,
135+
name: "shallow_implicit",
136+
value: "implicit file2",
137+
},
138+
{
139+
kind: TDirEnd,
140+
},
141+
})
178142
}

helpers_test.go

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package files
2+
3+
import (
4+
"io/ioutil"
5+
"testing"
6+
)
7+
8+
type Kind int
9+
10+
const (
11+
TFile Kind = iota
12+
TSymlink
13+
TDirStart
14+
TDirEnd
15+
)
16+
17+
type Event struct {
18+
kind Kind
19+
name string
20+
value string
21+
}
22+
23+
func CheckDir(t *testing.T, dir Directory, expected []Event) {
24+
expectedIndex := 0
25+
expect := func() (Event, int) {
26+
t.Helper()
27+
28+
if expectedIndex > len(expected) {
29+
t.Fatal("no more expected entries")
30+
}
31+
i := expectedIndex
32+
expectedIndex++
33+
34+
// Add an implicit "end" event at the end. It makes this
35+
// function a bit easier to write.
36+
next := Event{kind: TDirEnd}
37+
if i < len(expected) {
38+
next = expected[i]
39+
}
40+
return next, i
41+
}
42+
var check func(d Directory)
43+
check = func(d Directory) {
44+
it := d.Entries()
45+
46+
for it.Next() {
47+
next, i := expect()
48+
49+
if it.Name() != next.name {
50+
t.Fatalf("[%d] expected filename to be %q", i, next.name)
51+
}
52+
53+
switch next.kind {
54+
case TFile:
55+
mf, ok := it.Node().(File)
56+
if !ok {
57+
t.Fatalf("[%d] expected file to be a normal file: %T", i, it.Node())
58+
}
59+
out, err := ioutil.ReadAll(mf)
60+
if err != nil {
61+
t.Errorf("[%d] failed to read file", i)
62+
continue
63+
}
64+
if string(out) != next.value {
65+
t.Errorf(
66+
"[%d] while reading %q, expected %q, got %q",
67+
i,
68+
it.Name(),
69+
next.value,
70+
string(out),
71+
)
72+
continue
73+
}
74+
case TSymlink:
75+
mf, ok := it.Node().(*Symlink)
76+
if !ok {
77+
t.Errorf("[%d] expected file to be a symlink: %T", i, it.Node())
78+
continue
79+
}
80+
if mf.Target != next.value {
81+
t.Errorf(
82+
"[%d] target of symlink %q should have been %q but was %q",
83+
i,
84+
it.Name(),
85+
next.value,
86+
mf.Target,
87+
)
88+
continue
89+
}
90+
case TDirStart:
91+
mf, ok := it.Node().(Directory)
92+
if !ok {
93+
t.Fatalf(
94+
"[%d] expected file to be a directory: %T",
95+
i,
96+
it.Node(),
97+
)
98+
}
99+
check(mf)
100+
case TDirEnd:
101+
t.Errorf(
102+
"[%d] expected end of directory, found %#v at %q",
103+
i,
104+
it.Node(),
105+
it.Name(),
106+
)
107+
return
108+
default:
109+
t.Fatal("unhandled type", next.kind)
110+
}
111+
if err := it.Node().Close(); err != nil {
112+
t.Fatalf("[%d] expected to be able to close node", i)
113+
}
114+
}
115+
next, i := expect()
116+
117+
if it.Err() != nil {
118+
t.Fatalf("[%d] got error: %s", i, it.Err())
119+
}
120+
121+
if next.kind != TDirEnd {
122+
t.Fatalf("[%d] found end of directory, expected %#v", i, next)
123+
}
124+
}
125+
check(dir)
126+
}

0 commit comments

Comments
 (0)