github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/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 "net/textproto" 11 "strings" 12 "testing" 13 ) 14 15 func TestWriter(t *testing.T) { 16 fileContents := []byte("my file contents") 17 18 var b bytes.Buffer 19 w := NewWriter(&b) 20 { 21 part, err := w.CreateFormFile("myfile", "my-file.txt") 22 if err != nil { 23 t.Fatalf("CreateFormFile: %v", err) 24 } 25 part.Write(fileContents) 26 err = w.WriteField("key", "val") 27 if err != nil { 28 t.Fatalf("WriteField: %v", err) 29 } 30 part.Write([]byte("val")) 31 err = w.Close() 32 if err != nil { 33 t.Fatalf("Close: %v", err) 34 } 35 s := b.String() 36 if len(s) == 0 { 37 t.Fatal("String: unexpected empty result") 38 } 39 if s[0] == '\r' || s[0] == '\n' { 40 t.Fatal("String: unexpected newline") 41 } 42 } 43 44 r := NewReader(&b, w.Boundary()) 45 46 part, err := r.NextPart() 47 if err != nil { 48 t.Fatalf("part 1: %v", err) 49 } 50 if g, e := part.FormName(), "myfile"; g != e { 51 t.Errorf("part 1: want form name %q, got %q", e, g) 52 } 53 slurp, err := ioutil.ReadAll(part) 54 if err != nil { 55 t.Fatalf("part 1: ReadAll: %v", err) 56 } 57 if e, g := string(fileContents), string(slurp); e != g { 58 t.Errorf("part 1: want contents %q, got %q", e, g) 59 } 60 61 part, err = r.NextPart() 62 if err != nil { 63 t.Fatalf("part 2: %v", err) 64 } 65 if g, e := part.FormName(), "key"; g != e { 66 t.Errorf("part 2: want form name %q, got %q", e, g) 67 } 68 slurp, err = ioutil.ReadAll(part) 69 if err != nil { 70 t.Fatalf("part 2: ReadAll: %v", err) 71 } 72 if e, g := "val", string(slurp); e != g { 73 t.Errorf("part 2: want contents %q, got %q", e, g) 74 } 75 76 part, err = r.NextPart() 77 if part != nil || err == nil { 78 t.Fatalf("expected end of parts; got %v, %v", part, err) 79 } 80 } 81 82 func TestWriterSetBoundary(t *testing.T) { 83 var b bytes.Buffer 84 w := NewWriter(&b) 85 tests := []struct { 86 b string 87 ok bool 88 }{ 89 {"abc", true}, 90 {"", false}, 91 {"ungültig", false}, 92 {"!", false}, 93 {strings.Repeat("x", 70), true}, 94 {strings.Repeat("x", 71), false}, 95 {"bad!ascii!", false}, 96 {"my-separator", true}, 97 } 98 for i, tt := range tests { 99 err := w.SetBoundary(tt.b) 100 got := err == nil 101 if got != tt.ok { 102 t.Errorf("%d. boundary %q = %v (%v); want %v", i, tt.b, got, err, tt.ok) 103 } else if tt.ok { 104 got := w.Boundary() 105 if got != tt.b { 106 t.Errorf("boundary = %q; want %q", got, tt.b) 107 } 108 } 109 } 110 w.Close() 111 if got := b.String(); !strings.Contains(got, "\r\n--my-separator--\r\n") { 112 t.Errorf("expected my-separator in output. got: %q", got) 113 } 114 } 115 116 func TestWriterBoundaryGoroutines(t *testing.T) { 117 // Verify there's no data race accessing any lazy boundary if it's used by 118 // different goroutines. This was previously broken by 119 // https://codereview.appspot.com/95760043/ and reverted in 120 // https://codereview.appspot.com/117600043/ 121 w := NewWriter(ioutil.Discard) 122 done := make(chan int) 123 go func() { 124 w.CreateFormField("foo") 125 done <- 1 126 }() 127 w.Boundary() 128 <-done 129 } 130 131 func TestSortedHeader(t *testing.T) { 132 var buf bytes.Buffer 133 w := NewWriter(&buf) 134 if err := w.SetBoundary("MIMEBOUNDARY"); err != nil { 135 t.Fatalf("Error setting mime boundary: %v", err) 136 } 137 138 header := textproto.MIMEHeader{ 139 "A": {"2"}, 140 "B": {"5", "7", "6"}, 141 "C": {"4"}, 142 "M": {"3"}, 143 "Z": {"1"}, 144 } 145 146 part, err := w.CreatePart(header) 147 if err != nil { 148 t.Fatalf("Unable to create part: %v", err) 149 } 150 part.Write([]byte("foo")) 151 152 w.Close() 153 154 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" 155 if want != buf.String() { 156 t.Fatalf("\n got: %q\nwant: %q\n", buf.String(), want) 157 } 158 }