@@ -12,6 +12,7 @@ import (
1212 "testing"
1313
1414 "github.com/mazrean/formstream"
15+ "github.com/mazrean/formstream/internal/myio"
1516)
1617
1718func ExampleNewParser () {
@@ -69,44 +70,69 @@ large file contents
6970
7071const boundary = "boundary"
7172
72- func sampleForm (fileSize formstream.DataSize , boundary string , reverse bool ) (io.Reader , error ) {
73- b := bytes .NewBuffer (nil )
73+ func sampleForm (fileSize formstream.DataSize , boundary string , reverse bool ) (io.ReadSeekCloser , error ) {
74+ if fileSize > 1 * formstream .GB {
75+ f , err := os .CreateTemp ("" , "formstream-test-form-" )
76+ if err != nil {
77+ return nil , fmt .Errorf ("failed to create temp file: %w" , err )
78+ }
79+
80+ err = createSampleForm (f , fileSize , boundary , reverse )
81+ if err != nil {
82+ return nil , fmt .Errorf ("failed to create sample form: %w" , err )
83+ }
84+
85+ return f , nil
86+ }
87+
88+ buf := bytes .NewBuffer (nil )
89+
90+ err := createSampleForm (buf , fileSize , boundary , reverse )
91+ if err != nil {
92+ return nil , fmt .Errorf ("failed to create sample form: %w" , err )
93+ }
7494
75- mw := multipart .NewWriter (b )
95+ return myio .NopSeekCloser (bytes .NewReader (buf .Bytes ())), nil
96+ }
97+
98+ func createSampleForm (w io.Writer , fileSize formstream.DataSize , boundary string , reverse bool ) error {
99+ mw := multipart .NewWriter (w )
76100 defer mw .Close ()
77101
78102 err := mw .SetBoundary (boundary )
79103 if err != nil {
80- return nil , fmt .Errorf ("failed to set boundary: %w" , err )
104+ return fmt .Errorf ("failed to set boundary: %w" , err )
81105 }
82106
83107 if ! reverse {
84108 err := mw .WriteField ("field" , "value" )
85109 if err != nil {
86- return nil , fmt .Errorf ("failed to write field: %w" , err )
110+ return fmt .Errorf ("failed to write field: %w" , err )
87111 }
88112 }
89113
90114 mh := make (textproto.MIMEHeader )
91115 mh .Set ("Content-Disposition" , `form-data; name="stream"; filename="file.txt"` )
92116 mh .Set ("Content-Type" , "text/plain" )
93- w , err := mw .CreatePart (mh )
117+ pw , err := mw .CreatePart (mh )
94118 if err != nil {
95- return nil , fmt .Errorf ("failed to create part: %w" , err )
119+ return fmt .Errorf ("failed to create part: %w" , err )
96120 }
97- _ , err = io .CopyN (w , strings .NewReader (strings .Repeat ("a" , int (fileSize ))), int64 (fileSize ))
98- if err != nil {
99- return nil , fmt .Errorf ("failed to copy: %w" , err )
121+ for i := 0 ; i < int (fileSize / formstream .MB ); i ++ {
122+ _ , err := pw .Write ([]byte (strings .Repeat ("a" , int (formstream .MB ))))
123+ if err != nil {
124+ return fmt .Errorf ("failed to write: %w" , err )
125+ }
100126 }
101127
102128 if reverse {
103129 err := mw .WriteField ("field" , "value" )
104130 if err != nil {
105- return nil , fmt .Errorf ("failed to write field: %w" , err )
131+ return fmt .Errorf ("failed to write field: %w" , err )
106132 }
107133 }
108134
109- return b , nil
135+ return nil
110136}
111137
112138func BenchmarkFormStreamFastPath (b * testing.B ) {
@@ -122,6 +148,18 @@ func BenchmarkFormStreamFastPath(b *testing.B) {
122148 b .Run ("1GB" , func (b * testing.B ) {
123149 benchmarkFormStream (b , 1 * formstream .GB , false )
124150 })
151+ b .Run ("5GB" , func (b * testing.B ) {
152+ if testing .Short () {
153+ b .Skip ("skipping test in short mode." )
154+ }
155+ benchmarkFormStream (b , 5 * formstream .GB , false )
156+ })
157+ b .Run ("10GB" , func (b * testing.B ) {
158+ if testing .Short () {
159+ b .Skip ("skipping test in short mode." )
160+ }
161+ benchmarkFormStream (b , 10 * formstream .GB , false )
162+ })
125163}
126164
127165func BenchmarkFormStreamSlowPath (b * testing.B ) {
@@ -137,12 +175,31 @@ func BenchmarkFormStreamSlowPath(b *testing.B) {
137175 b .Run ("1GB" , func (b * testing.B ) {
138176 benchmarkFormStream (b , 1 * formstream .GB , true )
139177 })
178+ b .Run ("5GB" , func (b * testing.B ) {
179+ if testing .Short () {
180+ b .Skip ("skipping test in short mode." )
181+ }
182+ benchmarkFormStream (b , 5 * formstream .GB , true )
183+ })
184+ b .Run ("10GB" , func (b * testing.B ) {
185+ if testing .Short () {
186+ b .Skip ("skipping test in short mode." )
187+ }
188+ benchmarkFormStream (b , 10 * formstream .GB , true )
189+ })
140190}
141191
142192func benchmarkFormStream (b * testing.B , fileSize formstream.DataSize , reverse bool ) {
193+ r , err := sampleForm (fileSize , boundary , reverse )
194+ if err != nil {
195+ b .Fatal (err )
196+ }
197+ defer r .Close ()
198+
199+ b .ResetTimer ()
143200 for i := 0 ; i < b .N ; i ++ {
144201 b .StopTimer ()
145- r , err := sampleForm ( fileSize , boundary , reverse )
202+ _ , err := r . Seek ( 0 , io . SeekStart )
146203 if err != nil {
147204 b .Fatal (err )
148205 }
@@ -169,32 +226,50 @@ func benchmarkFormStream(b *testing.B, fileSize formstream.DataSize, reverse boo
169226 if err != nil {
170227 b .Fatal (err )
171228 }
172-
173229 }
174230}
175231
176- func BenchmarkStdMultipart_ReadForm (b * testing.B ) {
177- // default value in http package
178- const maxMemory = 32 * formstream .MB
179-
232+ func BenchmarkStdMultipartReadForm (b * testing.B ) {
180233 b .Run ("1MB" , func (b * testing.B ) {
181- benchmarkStdMultipart_ReadForm (b , 1 * formstream .MB , maxMemory )
234+ benchmarkStdMultipartReadForm (b , 1 * formstream .MB )
182235 })
183236 b .Run ("10MB" , func (b * testing.B ) {
184- benchmarkStdMultipart_ReadForm (b , 10 * formstream .MB , maxMemory )
237+ benchmarkStdMultipartReadForm (b , 10 * formstream .MB )
185238 })
186239 b .Run ("100MB" , func (b * testing.B ) {
187- benchmarkStdMultipart_ReadForm (b , 100 * formstream .MB , maxMemory )
240+ benchmarkStdMultipartReadForm (b , 100 * formstream .MB )
188241 })
189242 b .Run ("1GB" , func (b * testing.B ) {
190- benchmarkStdMultipart_ReadForm (b , 1 * formstream .GB , maxMemory )
243+ benchmarkStdMultipartReadForm (b , 1 * formstream .GB )
244+ })
245+ b .Run ("5GB" , func (b * testing.B ) {
246+ if testing .Short () {
247+ b .Skip ("skipping test in short mode." )
248+ }
249+ benchmarkStdMultipartReadForm (b , 5 * formstream .GB )
250+ })
251+ b .Run ("10GB" , func (b * testing.B ) {
252+ if testing .Short () {
253+ b .Skip ("skipping test in short mode." )
254+ }
255+ benchmarkStdMultipartReadForm (b , 10 * formstream .GB )
191256 })
192257}
193258
194- func benchmarkStdMultipart_ReadForm (b * testing.B , fileSize formstream.DataSize , maxMemory formstream.DataSize ) {
259+ func benchmarkStdMultipartReadForm (b * testing.B , fileSize formstream.DataSize ) {
260+ // default value in http package
261+ const maxMemory = 32 * formstream .MB
262+
263+ r , err := sampleForm (fileSize , boundary , false )
264+ if err != nil {
265+ b .Fatal (err )
266+ }
267+ defer r .Close ()
268+
269+ b .ResetTimer ()
195270 for i := 0 ; i < b .N ; i ++ {
196271 b .StopTimer ()
197- r , err := sampleForm ( fileSize , boundary , false )
272+ _ , err := r . Seek ( 0 , io . SeekStart )
198273 if err != nil {
199274 b .Fatal (err )
200275 }
0 commit comments