github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/mime/multipart/writer_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package multipart 6 7 import ( 8 "bytes" 9 "io/ioutil" 10 "mime" 11 "net/textproto" 12 "strings" 13 "testing" 14 ) 15 16 func TestWriter(t *testing.T) { 17 fileContents := []byte("my file contents") 18 19 var b bytes.Buffer 20 w := NewWriter(&b) 21 { 22 part, err := w.CreateFormFile("myfile", "my-file.txt") 23 if err != nil { 24 t.Fatalf("CreateFormFile: %v", err) 25 } 26 part.Write(fileContents) 27 err = w.WriteField("key", "val") 28 if err != nil { 29 t.Fatalf("WriteField: %v", err) 30 } 31 part.Write([]byte("val")) 32 err = w.Close() 33 if err != nil { 34 t.Fatalf("Close: %v", err) 35 } 36 s := b.String() 37 if len(s) == 0 { 38 t.Fatal("String: unexpected empty result") 39 } 40 if s[0] == '\r' || s[0] == '\n' { 41 t.Fatal("String: unexpected newline") 42 } 43 } 44 45 r := NewReader(&b, w.Boundary()) 46 47 part, err := r.NextPart() 48 if err != nil { 49 t.Fatalf("part 1: %v", err) 50 } 51 if g, e := part.FormName(), "myfile"; g != e { 52 t.Errorf("part 1: want form name %q, got %q", e, g) 53 } 54 slurp, err := ioutil.ReadAll(part) 55 if err != nil { 56 t.Fatalf("part 1: ReadAll: %v", err) 57 } 58 if e, g := string(fileContents), string(slurp); e != g { 59 t.Errorf("part 1: want contents %q, got %q", e, g) 60 } 61 62 part, err = r.NextPart() 63 if err != nil { 64 t.Fatalf("part 2: %v", err) 65 } 66 if g, e := part.FormName(), "key"; g != e { 67 t.Errorf("part 2: want form name %q, got %q", e, g) 68 } 69 slurp, err = ioutil.ReadAll(part) 70 if err != nil { 71 t.Fatalf("part 2: ReadAll: %v", err) 72 } 73 if e, g := "val", string(slurp); e != g { 74 t.Errorf("part 2: want contents %q, got %q", e, g) 75 } 76 77 part, err = r.NextPart() 78 if part != nil || err == nil { 79 t.Fatalf("expected end of parts; got %v, %v", part, err) 80 } 81 } 82 83 func TestWriterSetBoundary(t *testing.T) { 84 tests := []struct { 85 b string 86 ok bool 87 }{ 88 {"abc", true}, 89 {"", false}, 90 {"ungültig", false}, 91 {"!", false}, 92 {strings.Repeat("x", 70), true}, 93 {strings.Repeat("x", 71), false}, 94 {"bad!ascii!", false}, 95 {"my-separator", true}, 96 {"with space", true}, 97 {"badspace ", false}, 98 {"(boundary)", true}, 99 } 100 for i, tt := range tests { 101 var b bytes.Buffer 102 w := NewWriter(&b) 103 err := w.SetBoundary(tt.b) 104 got := err == nil 105 if got != tt.ok { 106 t.Errorf("%d. boundary %q = %v (%v); want %v", i, tt.b, got, err, tt.ok) 107 } else if tt.ok { 108 got := w.Boundary() 109 if got != tt.b { 110 t.Errorf("boundary = %q; want %q", got, tt.b) 111 } 112 113 ct := w.FormDataContentType() 114 mt, params, err := mime.ParseMediaType(ct) 115 if err != nil { 116 t.Errorf("could not parse Content-Type %q: %v", ct, err) 117 } else if mt != "multipart/form-data" { 118 t.Errorf("unexpected media type %q; want %q", mt, "multipart/form-data") 119 } else if b := params["boundary"]; b != tt.b { 120 t.Errorf("unexpected boundary parameter %q; want %q", b, tt.b) 121 } 122 123 w.Close() 124 wantSub := "\r\n--" + tt.b + "--\r\n" 125 if got := b.String(); !strings.Contains(got, wantSub) { 126 t.Errorf("expected %q in output. got: %q", wantSub, got) 127 } 128 } 129 } 130 } 131 132 func TestWriterBoundaryGoroutines(t *testing.T) { 133 // Verify there's no data race accessing any lazy boundary if it's used by 134 // different goroutines. This was previously broken by 135 // https://codereview.appspot.com/95760043/ and reverted in 136 // https://codereview.appspot.com/117600043/ 137 w := NewWriter(ioutil.Discard) 138 done := make(chan int) 139 go func() { 140 w.CreateFormField("foo") 141 done <- 1 142 }() 143 w.Boundary() 144 <-done 145 } 146 147 func TestSortedHeader(t *testing.T) { 148 var buf bytes.Buffer 149 w := NewWriter(&buf) 150 if err := w.SetBoundary("MIMEBOUNDARY"); err != nil { 151 t.Fatalf("Error setting mime boundary: %v", err) 152 } 153 154 header := textproto.MIMEHeader{ 155 "A": {"2"}, 156 "B": {"5", "7", "6"}, 157 "C": {"4"}, 158 "M": {"3"}, 159 "Z": {"1"}, 160 } 161 162 part, err := w.CreatePart(header) 163 if err != nil { 164 t.Fatalf("Unable to create part: %v", err) 165 } 166 part.Write([]byte("foo")) 167 168 w.Close() 169 170 want := "--MIMEBOUNDARY\r\nA: 2\r\nB: 5\r\nB: 7\r\nB: 6\r\nC: 4\r\nM: 3\r\nZ: 1\r\n\r\nfoo\r\n--MIMEBOUNDARY--\r\n" 171 if want != buf.String() { 172 t.Fatalf("\n got: %q\nwant: %q\n", buf.String(), want) 173 } 174 }