View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.net.tftp;
18  
19  import java.io.BufferedInputStream;
20  import java.io.BufferedOutputStream;
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.OutputStream;
27  
28  import org.apache.commons.net.tftp.TFTPServer.ServerMode;
29  
30  import junit.framework.TestCase;
31  
32  /**
33   * Test the TFTP Server and TFTP Client by creating some files in the system temp folder and then
34   * uploading and downloading them.
35   */
36  public class TFTPTest extends TestCase
37  {
38      private static final int SERVER_PORT = 6902;
39      private static TFTPServer tftpS;
40      private static final File serverDirectory = new File(System.getProperty("java.io.tmpdir"));
41      private static final String filePrefix = "tftp-";
42      private static final File[] files = new File[8];
43  
44      static int testsLeftToRun = 6;
45  
46      // only want to do this once...
47      static
48      {
49          try
50          {
51              files[0] = createFile(new File(serverDirectory, filePrefix + "empty.txt"), 0);
52              files[1] = createFile(new File(serverDirectory, filePrefix + "small.txt"), 1);
53              files[2] = createFile(new File(serverDirectory, filePrefix + "511.txt"), 511);
54              files[3] = createFile(new File(serverDirectory, filePrefix + "512.txt"), 512);
55              files[4] = createFile(new File(serverDirectory, filePrefix + "513.txt"), 513);
56              files[5] = createFile(new File(serverDirectory, filePrefix + "med.txt"), 1000 * 1024);
57              files[6] = createFile(new File(serverDirectory, filePrefix + "big.txt"), 5000 * 1024);
58              files[7] = createFile(new File(serverDirectory, filePrefix + "huge.txt"), 37000 * 1024);
59  
60              // Start the server
61              tftpS = new TFTPServer(serverDirectory, serverDirectory, SERVER_PORT, ServerMode.GET_AND_PUT,
62                      null, null);
63              tftpS.setSocketTimeout(2000);
64          }
65          catch (IOException e)
66          {
67              e.printStackTrace();
68          }
69  
70      }
71  
72      @Override
73      protected void tearDown() throws Exception
74      {
75          testsLeftToRun--;
76          if (testsLeftToRun <= 0)
77          {
78              if (tftpS != null)
79              {
80                  tftpS.shutdown();
81              }
82              for (File file : files)
83              {
84                  file.delete();
85              }
86          }
87          super.tearDown();
88      }
89  
90      /*
91       * Create a file, size specified in bytes
92       */
93      private static File createFile(File file, int size) throws IOException
94      {
95          OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
96          byte[] temp = "0".getBytes();
97          for (int i = 0; i < size; i++)
98          {
99              os.write(temp);
100         }
101         os.close();
102         return file;
103     }
104 
105     public void testTFTPBinaryDownloads() throws Exception
106     {
107         // test with the smaller files
108         for (int i = 0; i < 6; i++)
109         {
110             testDownload(TFTP.BINARY_MODE, files[i]);
111         }
112     }
113 
114     public void testASCIIDownloads() throws Exception
115     {
116         // test with the smaller files
117         for (int i = 0; i < 6; i++)
118         {
119             try {
120                 testDownload(TFTP.ASCII_MODE, files[i]);
121             } catch (IOException e) {
122                 fail("Entry "+i+" Error "+e.toString());
123             }
124 
125         }
126     }
127 
128     public void testTFTPBinaryUploads() throws Exception
129     {
130         // test with the smaller files
131         for (int i = 0; i < 6; i++)
132         {
133             testUpload(TFTP.BINARY_MODE, files[i]);
134         }
135     }
136 
137     public void testASCIIUploads() throws Exception
138     {
139         // test with the smaller files
140         for (int i = 0; i < 6; i++)
141         {
142             testUpload(TFTP.ASCII_MODE, files[i]);
143         }
144     }
145 
146     public void testHugeUploads() throws Exception
147     {
148         for (int i = 5; i < files.length; i++)
149         {
150             testUpload(TFTP.BINARY_MODE, files[i]);
151         }
152     }
153 
154     public void testHugeDownloads() throws Exception
155     {
156         // test with the smaller files
157         for (int i = 5; i < files.length; i++)
158         {
159             testDownload(TFTP.BINARY_MODE, files[i]);
160         }
161     }
162 
163     private void testDownload(int mode, File file) throws IOException
164     {
165         // Create our TFTP instance to handle the file transfer.
166         TFTPClient tftp = new TFTPClient();
167         tftp.open();
168         tftp.setSoTimeout(2000);
169 
170         File out = new File(serverDirectory, filePrefix + "download");
171 
172         // cleanup old failed runs
173         out.delete();
174         assertTrue("Couldn't clear output location", !out.exists());
175 
176         FileOutputStream output = new FileOutputStream(out);
177 
178         tftp.receiveFile(file.getName(), mode, output, "localhost", SERVER_PORT);
179         output.close();
180 
181         assertTrue("file not created", out.exists());
182         assertTrue("files not identical on file " + file, filesIdentical(out, file));
183 
184         // delete the downloaded file
185         out.delete();
186     }
187 
188     private void testUpload(int mode, File file) throws Exception
189     {
190         // Create our TFTP instance to handle the file transfer.
191         TFTPClient tftp = new TFTPClient();
192         tftp.open();
193         tftp.setSoTimeout(2000);
194 
195         File in = new File(serverDirectory, filePrefix + "upload");
196         // cleanup old failed runs
197         in.delete();
198         assertTrue("Couldn't clear output location", !in.exists());
199 
200         FileInputStream fis = new FileInputStream(file);
201         tftp.sendFile(in.getName(), mode, fis, "localhost", SERVER_PORT);
202         fis.close();
203 
204         // need to give the server a bit of time to receive our last packet, and
205         // close out its file buffers, etc.
206         Thread.sleep(100);
207         assertTrue("file not created", in.exists());
208         assertTrue("files not identical on file " + file, filesIdentical(file, in));
209 
210         in.delete();
211     }
212 
213     private boolean filesIdentical(File a, File b) throws IOException
214     {
215         if (!a.exists() || !b.exists())
216         {
217             return false;
218         }
219 
220         if (a.length() != b.length())
221         {
222             return false;
223         }
224 
225         InputStream fisA = new BufferedInputStream(new FileInputStream(a));
226         InputStream fisB = new BufferedInputStream(new FileInputStream(b));
227 
228         int aBit = fisA.read();
229         int bBit = fisB.read();
230 
231         while (aBit != -1)
232         {
233             if (aBit != bBit)
234             {
235                 fisA.close();
236                 fisB.close();
237                 return false;
238             }
239             aBit = fisA.read();
240             bBit = fisB.read();
241         }
242 
243         fisA.close();
244         fisB.close();
245         return true;
246     }
247 }