1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.transport;
21  
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.net.InetSocketAddress;
26  import java.nio.ByteBuffer;
27  import java.nio.channels.FileChannel;
28  import java.util.concurrent.CountDownLatch;
29  
30  import junit.framework.TestCase;
31  
32  import org.apache.mina.core.buffer.IoBuffer;
33  import org.apache.mina.core.future.ConnectFuture;
34  import org.apache.mina.core.service.IoAcceptor;
35  import org.apache.mina.core.service.IoConnector;
36  import org.apache.mina.core.service.IoHandlerAdapter;
37  import org.apache.mina.core.session.IoSession;
38  import org.apache.mina.util.AvailablePortFinder;
39  
40  /**
41   * TODO Add documentation
42   * 
43   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
44   */
45  public abstract class AbstractFileRegionTest extends TestCase {
46  
47      private static final int FILE_SIZE = 1 * 1024 * 1024; // 1MB file
48      
49      protected abstract IoAcceptor createAcceptor();
50      protected abstract IoConnector createConnector();
51  
52      public void testSendLargeFile() throws Throwable {
53          File file = createLargeFile();
54          assertEquals("Test file not as big as specified", FILE_SIZE, file.length());
55          
56          final CountDownLatch latch = new CountDownLatch(1);
57          final boolean[] success = {false};
58          final Throwable[] exception = {null};
59          
60          int port = AvailablePortFinder.getNextAvailable(1025);
61          IoAcceptor acceptor = createAcceptor();
62          acceptor.setHandler(new IoHandlerAdapter() {
63              private int index = 0;
64              @Override
65              public void exceptionCaught(IoSession session, Throwable cause)
66                      throws Exception {
67                  exception[0] = cause;
68                  session.close(true);
69              }
70              @Override
71              public void messageReceived(IoSession session, Object message) throws Exception {
72                  IoBuffer buffer = (IoBuffer) message;
73                  while (buffer.hasRemaining()) {
74                      int x = buffer.getInt();
75                      if (x != index) {
76                          throw new Exception(String.format("Integer at %d was %d but should have been %d", index, x, index));
77                      }
78                      index++;
79                  }
80                  if (index > FILE_SIZE / 4) {
81                      throw new Exception("Read too much data");
82                  }
83                  if (index == FILE_SIZE / 4) {
84                      success[0] = true;
85                      session.close(true);
86                  }
87              }
88          });
89          acceptor.bind(new InetSocketAddress(port));
90          
91          IoConnector connector = createConnector();
92          connector.setHandler(new IoHandlerAdapter() {
93              @Override
94              public void exceptionCaught(IoSession session, Throwable cause)
95                      throws Exception {
96                  exception[0] = cause;
97                  session.close(true);
98              }
99              @Override
100             public void sessionClosed(IoSession session) throws Exception {
101                 latch.countDown();
102             }
103         });
104         ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port));
105         future.awaitUninterruptibly();
106         
107         IoSession session = future.getSession();
108         session.write(file);
109         
110         latch.await();
111         
112         if (exception[0] != null) {
113             throw exception[0];
114         }
115         assertTrue("Did not complete file transfer successfully", success[0]);
116         
117         assertEquals("Written messages should be 1 (we wrote one file)", 1, session.getWrittenMessages());
118         assertEquals("Written bytes should match file size", FILE_SIZE, session.getWrittenBytes());
119         
120         connector.dispose();
121         acceptor.dispose();
122     }
123     
124     private File createLargeFile() throws IOException {
125         File largeFile = File.createTempFile("mina-test", "largefile");
126         largeFile.deleteOnExit();
127         FileChannel channel = new FileOutputStream(largeFile).getChannel();
128         ByteBuffer buffer = createBuffer();
129         channel.write(buffer);
130         channel.close();
131         return largeFile;
132     }
133     private ByteBuffer createBuffer() {
134         ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE);
135         for (int i = 0; i < FILE_SIZE / 4; i++) {
136             buffer.putInt(i);
137         }
138         buffer.flip();
139         return buffer;
140     }
141     
142 }