11/*
2- * Copyright (c)2013 Sonatype, Inc . All rights reserved.
2+ * Copyright (c)2016 AsyncHttpClient Project . All rights reserved.
33 *
44 * This program is licensed to you under the Apache License Version 2.0,
55 * and you may not use this file except in compliance with the Apache License Version 2.0.
6- * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6+ * You may obtain a copy of the Apache License Version 2.0 at
7+ * http://www.apache.org/licenses/LICENSE-2.0.
78 *
89 * Unless required by applicable law or agreed to in writing,
910 * software distributed under the Apache License Version 2.0 is distributed on an
1213 */
1314package com .ning .http .client .multipart ;
1415
15- import static java .nio .charset .StandardCharsets .* ;
16+ import static java .nio .charset .StandardCharsets .UTF_8 ;
1617
1718import org .testng .Assert ;
1819import org .testng .annotations .Test ;
1920
20- import com .ning .http .client .Body ;
2121import com .ning .http .client .FluentCaseInsensitiveStringsMap ;
22- import com .ning .http .client .multipart .ByteArrayPart ;
23- import com .ning .http .client .multipart .FilePart ;
24- import com .ning .http .client .multipart .Part ;
25- import com .ning .http .client .multipart .StringPart ;
2622
2723import java .io .File ;
2824import java .io .IOException ;
2925import java .net .URISyntaxException ;
3026import java .net .URL ;
3127import java .nio .ByteBuffer ;
28+ import java .nio .channels .WritableByteChannel ;
3229import java .util .ArrayList ;
3330import java .util .List ;
31+ import java .util .concurrent .atomic .AtomicLong ;
3432
3533public class MultipartBodyTest {
3634
37- @ Test (groups ="fast" )
38- public void testBasics () {
39- final List <Part >parts =new ArrayList <>();
35+ @ Test
36+ public void transferWithCopy ()throws IOException {
37+ try (MultipartBody multipartBody =buildMultipart ()) {
38+ long tranferred =transferWithCopy (multipartBody );
39+ Assert .assertEquals (tranferred ,multipartBody .getContentLength ());
40+ }
41+ }
4042
41- // add a file
42- final File testFile =getTestfile ();
43- parts .add (new FilePart ("filePart" ,testFile ));
43+ @ Test
44+ public void transferZeroCopy ()throws IOException {
45+ try (MultipartBody multipartBody =buildMultipart ()) {
46+ long tranferred =transferZeroCopy (multipartBody );
47+ Assert .assertEquals (tranferred ,multipartBody .getContentLength ());
48+ }
49+ }
4450
45- // add a byte array
51+ private static MultipartBody buildMultipart () {
52+ List <Part >parts =new ArrayList <>();
53+ parts .add (new FilePart ("filePart" ,getTestfile ()));
4654parts .add (new ByteArrayPart ("baPart" ,"testMultiPart" .getBytes (UTF_8 ),"application/test" ,UTF_8 ,"fileName" ));
47-
48- // add a string
4955parts .add (new StringPart ("stringPart" ,"testString" ));
50-
51- compareContentLength (parts );
56+ return MultipartUtils .newMultipartBody (parts ,new FluentCaseInsensitiveStringsMap ());
5257 }
5358
5459private static File getTestfile () {
@@ -64,35 +69,49 @@ private static File getTestfile() {
6469return file ;
6570 }
6671
67- private static void compareContentLength (final List <Part >parts ) {
68- Assert .assertNotNull (parts );
69- // get expected values
70- final Body multipartBody =MultipartUtils .newMultipartBody (parts ,new FluentCaseInsensitiveStringsMap ());
71- final long expectedContentLength =multipartBody .getContentLength ();
72- try {
73- final ByteBuffer buffer =ByteBuffer .allocate (8192 );
74- boolean last =false ;
75- long totalBytes =0 ;
76- while (!last ) {
77- long readBytes =0 ;
78- try {
79- readBytes =multipartBody .read (buffer );
80- }catch (IOException ie ) {
81- Assert .fail ("read failure" );
82- }
83- if (readBytes >=0 ) {
84- totalBytes +=readBytes ;
85- }else {
86- last =true ;
87- }
88- buffer .clear ();
72+ private static long transferWithCopy (MultipartBody multipartBody )throws IOException {
73+
74+ final ByteBuffer buffer =ByteBuffer .allocate (8192 );
75+ long totalBytes =0 ;
76+ while (true ) {
77+ long readBytes =multipartBody .read (buffer );
78+ if (readBytes <0 ) {
79+ break ;
80+ }
81+ buffer .clear ();
82+ totalBytes +=readBytes ;
83+ }
84+ return totalBytes ;
85+ }
86+
87+ private static long transferZeroCopy (MultipartBody multipartBody )throws IOException {
88+
89+ final ByteBuffer buffer =ByteBuffer .allocate (8192 );
90+ final AtomicLong transferred =new AtomicLong ();
91+
92+ WritableByteChannel mockChannel =new WritableByteChannel () {
93+ @ Override
94+ public boolean isOpen () {
95+ return true ;
8996 }
90- Assert .assertEquals (totalBytes ,expectedContentLength );
91- }finally {
92- try {
93- multipartBody .close ();
94- }catch (IOException ignore ) {
97+
98+ @ Override
99+ public void close ()throws IOException {
100+ }
101+
102+ @ Override
103+ public int write (ByteBuffer src )throws IOException {
104+ int written =src .remaining ();
105+ transferred .set (transferred .get () +written );
106+ src .position (src .limit ());
107+ return written ;
95108 }
109+ };
110+
111+ while (transferred .get () <multipartBody .getContentLength ()) {
112+ multipartBody .transferTo (0 ,mockChannel );
113+ buffer .clear ();
96114 }
115+ return transferred .get ();
97116 }
98117}