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 The Apache MINA Project (dev@mina.apache.org)
44   * @version $Rev$, $Date$
45   */
46  public abstract class AbstractFileRegionTest extends TestCase {
47  
48      private static final int FILE_SIZE = 1 * 1024 * 1024; // 1MB file
49      
50      protected abstract IoAcceptor createAcceptor();
51      protected abstract IoConnector createConnector();
52  
53      public void testSendLargeFile() throws Throwable {
54          File file = createLargeFile();
55          assertEquals("Test file not as big as specified", FILE_SIZE, file.length());
56          
57          final CountDownLatch latch = new CountDownLatch(1);
58          final boolean[] success = {false};
59          final Throwable[] exception = {null};
60          
61          int port = AvailablePortFinder.getNextAvailable(1025);
62          IoAcceptor acceptor = createAcceptor();
63          acceptor.setHandler(new IoHandlerAdapter() {
64              private int index = 0;
65              @Override
66              public void exceptionCaught(IoSession session, Throwable cause)
67                      throws Exception {
68                  exception[0] = cause;
69                  session.close(true);
70              }
71              @Override
72              public void messageReceived(IoSession session, Object message) throws Exception {
73                  IoBuffer buffer = (IoBuffer) message;
74                  while (buffer.hasRemaining()) {
75                      int x = buffer.getInt();
76                      if (x != index) {
77                          throw new Exception(String.format("Integer at %d was %d but should have been %d", index, x, index));
78                      }
79                      index++;
80                  }
81                  if (index > FILE_SIZE / 4) {
82                      throw new Exception("Read too much data");
83                  }
84                  if (index == FILE_SIZE / 4) {
85                      success[0] = true;
86                      session.close(true);
87                  }
88              }
89          });
90          acceptor.bind(new InetSocketAddress(port));
91          
92          IoConnector connector = createConnector();
93          connector.setHandler(new IoHandlerAdapter() {
94              @Override
95              public void exceptionCaught(IoSession session, Throwable cause)
96                      throws Exception {
97                  exception[0] = cause;
98                  session.close(true);
99              }
100             @Override
101             public void sessionClosed(IoSession session) throws Exception {
102                 latch.countDown();
103             }
104         });
105         ConnectFuture future = connector.connect(new InetSocketAddress("localhost", port));
106         future.awaitUninterruptibly();
107         
108         IoSession session = future.getSession();
109         session.write(file);
110         
111         latch.await();
112         
113         if (exception[0] != null) {
114             throw exception[0];
115         }
116         assertTrue("Did not complete file transfer successfully", success[0]);
117         
118         assertEquals("Written messages should be 1 (we wrote one file)", 1, session.getWrittenMessages());
119         assertEquals("Written bytes should match file size", FILE_SIZE, session.getWrittenBytes());
120         
121         connector.dispose();
122         acceptor.dispose();
123     }
124     
125     private File createLargeFile() throws IOException {
126         File largeFile = File.createTempFile("mina-test", "largefile");
127         largeFile.deleteOnExit();
128         FileChannel channel = new FileOutputStream(largeFile).getChannel();
129         ByteBuffer buffer = createBuffer();
130         channel.write(buffer);
131         channel.close();
132         return largeFile;
133     }
134     private ByteBuffer createBuffer() {
135         ByteBuffer buffer = ByteBuffer.allocate(FILE_SIZE);
136         for (int i = 0; i < FILE_SIZE / 4; i++) {
137             buffer.putInt(i);
138         }
139         buffer.flip();
140         return buffer;
141     }
142     
143 }