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 static org.junit.jupiter.api.Assertions.assertThrows;
20  
21  import java.io.BufferedOutputStream;
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.OutputStream;
27  import java.net.InetAddress;
28  
29  import junit.framework.TestCase;
30  
31  import org.apache.commons.io.FileUtils;
32  import org.apache.commons.net.tftp.TFTPServer.ServerMode;
33  
34  /**
35   * Test the TFTP Server and TFTP Client by creating some FILES in the system temp folder and then uploading and downloading them.
36   */
37  public class TFTPTest extends TestCase {
38      private static final int SERVER_PORT = 6902;
39      private static TFTPServer tftpS;
40      private static final File SERVER_DIR = FileUtils.getTempDirectory();
41      private static final String FILE_PREFIX = "tftp-";
42      private static final File[] FILES = new File[8];
43  
44      static int testsLeftToRun = 9; // TODO Nasty hack.
45  
46      // only want to do this once...
47      static {
48          try {
49              FILES[0] = createFile(new File(SERVER_DIR, FILE_PREFIX + "empty.txt"), 0);
50              FILES[1] = createFile(new File(SERVER_DIR, FILE_PREFIX + "small.txt"), 1);
51              FILES[2] = createFile(new File(SERVER_DIR, FILE_PREFIX + "511.txt"), 511);
52              FILES[3] = createFile(new File(SERVER_DIR, FILE_PREFIX + "512.txt"), 512);
53              FILES[4] = createFile(new File(SERVER_DIR, FILE_PREFIX + "513.txt"), 513);
54              FILES[5] = createFile(new File(SERVER_DIR, FILE_PREFIX + "med.txt"), 1000 * 1024);
55              FILES[6] = createFile(new File(SERVER_DIR, FILE_PREFIX + "big.txt"), 5000 * 1024);
56              FILES[7] = createFile(new File(SERVER_DIR, FILE_PREFIX + "huge.txt"), 37000 * 1024);
57  
58              // Start the server
59              tftpS = new TFTPServer(SERVER_DIR, SERVER_DIR, SERVER_PORT, ServerMode.GET_AND_PUT, null, null);
60              tftpS.setSocketTimeout(2000);
61          } catch (final IOException e) {
62              e.printStackTrace();
63          }
64  
65      }
66  
67      /*
68       * Create a file, size specified in bytes
69       */
70      private static File createFile(final File file, final int size) throws IOException {
71          try (final OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) {
72              final byte[] temp = "0".getBytes();
73              for (int i = 0; i < size; i++) {
74                  os.write(temp);
75              }
76          }
77          return file;
78      }
79  
80      private boolean contentEquals(final File a, final File b) throws IOException {
81          return FileUtils.contentEquals(a, b);
82      }
83  
84      @Override
85      protected void tearDown() throws Exception {
86          testsLeftToRun--;
87          if (testsLeftToRun <= 0) {
88              if (tftpS != null) {
89                  tftpS.close();
90              }
91              for (final File file : FILES) {
92                  file.delete();
93              }
94          }
95          super.tearDown();
96      }
97  
98      public void testASCIIDownloads() {
99          // test with the smaller FILES
100         for (int i = 0; i < 6; i++) {
101             try {
102                 testDownload(TFTP.ASCII_MODE, FILES[i]);
103             } catch (final IOException e) {
104                 fail("Entry " + i + " Error " + e.toString());
105             }
106 
107         }
108     }
109 
110     public void testASCIIUploads() throws Exception {
111         // test with the smaller FILES
112         for (int i = 0; i < 6; i++) {
113             testUpload(TFTP.ASCII_MODE, FILES[i]);
114         }
115     }
116 
117     public void testDiscardPackets() throws IOException {
118         try (TFTP tftp = new TFTP()) {
119             assertThrows(NullPointerException.class, tftp::discardPackets);
120             tftp.open();
121             tftp.discardPackets();
122         }
123     }
124 
125     private void testDownload(final int mode, final File file) throws IOException {
126         // Create our TFTP instance to handle the file transfer.
127         try (TFTPClient tftp = new TFTPClient()) {
128             tftp.open();
129             tftp.setSoTimeout(2000);
130 
131             final File out = new File(SERVER_DIR, FILE_PREFIX + "download");
132 
133             // cleanup old failed runs
134             out.delete();
135             assertFalse("Couldn't clear output location", out.exists());
136 
137             try (final FileOutputStream output = new FileOutputStream(out)) {
138                 tftp.receiveFile(file.getName(), mode, output, "localhost", SERVER_PORT);
139             }
140 
141             assertTrue("file not created", out.exists());
142             assertTrue("FILES not identical on file " + file, contentEquals(out, file));
143 
144             // delete the downloaded file
145             out.delete();
146         }
147     }
148 
149     public void testGetModeName() {
150         assertNotNull(TFTP.getModeName(0));
151         assertNotNull(TFTP.getModeName(1));
152     }
153 
154     public void testHugeDownloads() throws Exception {
155         // test with the smaller FILES
156         for (int i = 5; i < FILES.length; i++) {
157             testDownload(TFTP.BINARY_MODE, FILES[i]);
158         }
159     }
160 
161     public void testHugeUploads() throws Exception {
162         for (int i = 5; i < FILES.length; i++) {
163             testUpload(TFTP.BINARY_MODE, FILES[i]);
164         }
165     }
166 
167     public void testSend() throws IOException {
168         try (TFTP tftp = new TFTP()) {
169             tftp.open();
170             tftp.send(new TFTPDataPacket(InetAddress.getLocalHost(), tftp.getLocalPort(), 0, new byte[10]));
171         }
172     }
173 
174     public void testTFTPBinaryDownloads() throws Exception {
175         // test with the smaller FILES
176         for (int i = 0; i < 6; i++) {
177             testDownload(TFTP.BINARY_MODE, FILES[i]);
178         }
179     }
180 
181     public void testTFTPBinaryUploads() throws Exception {
182         // test with the smaller FILES
183         for (int i = 0; i < 6; i++) {
184             testUpload(TFTP.BINARY_MODE, FILES[i]);
185         }
186     }
187 
188     private void testUpload(final int mode, final File file) throws Exception {
189         // Create our TFTP instance to handle the file transfer.
190         try (TFTPClient tftp = new TFTPClient()) {
191             tftp.open();
192             tftp.setSoTimeout(2000);
193 
194             final File in = new File(SERVER_DIR, FILE_PREFIX + "upload");
195             // cleanup old failed runs
196             in.delete();
197             assertFalse("Couldn't clear output location", in.exists());
198 
199             try (final FileInputStream fis = new FileInputStream(file)) {
200                 tftp.sendFile(in.getName(), mode, fis, "localhost", SERVER_PORT);
201             }
202 
203             // need to give the server a bit of time to receive our last packet, and
204             // close out its file buffers, etc.
205             Thread.sleep(100);
206             assertTrue("file not created", in.exists());
207             assertTrue("FILES not identical on file " + file, contentEquals(file, in));
208 
209             in.delete();
210         }
211     }
212 }