View Javadoc
1   /*
2    * Copyright 2016-2024 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.util;
6   
7   import static org.hamcrest.MatcherAssert.assertThat;
8   import static org.hamcrest.Matchers.aMapWithSize;
9   import static org.hamcrest.Matchers.anEmptyMap;
10  import static org.hamcrest.Matchers.empty;
11  import static org.hamcrest.Matchers.emptyString;
12  import static org.hamcrest.Matchers.hasEntry;
13  import static org.hamcrest.Matchers.is;
14  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
15  import static org.junit.jupiter.api.Assertions.assertFalse;
16  import static org.junit.jupiter.api.Assertions.fail;
17  
18  import java.io.IOException;
19  import java.nio.ByteBuffer;
20  import java.nio.ByteOrder;
21  import java.nio.charset.StandardCharsets;
22  import java.nio.file.Files;
23  import java.nio.file.Path;
24  import java.nio.file.StandardOpenOption;
25  import java.util.Arrays;
26  import java.util.LinkedHashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Map.Entry;
30  import java.util.Properties;
31  import java.util.stream.Collectors;
32  
33  import org.junit.jupiter.api.Test;
34  
35  import com.sun.jna.Native;
36  
37  /**
38   * Tests FileUtil
39   */
40  class FileUtilTest {
41  
42      /**
43       * Test read file.
44       */
45      @Test
46      void testReadFile() {
47          // Write to a temp file
48          Path multilineFile = null;
49          try {
50              multilineFile = Files.createTempFile("oshitest.multiline", null);
51              String s = "Line 1\nLine 2\nThe third line\nLine 4\nLine 5\n";
52              Files.write(multilineFile, s.getBytes(StandardCharsets.UTF_8));
53          } catch (IOException e) {
54              fail("IO Exception creating or writing to temporary multiline file.");
55          }
56  
57          // Try the new temp file
58          List<String> tempFileStrings = FileUtil.readFile(multilineFile.toString());
59          assertThat("Temp file line one mismatch", tempFileStrings.get(0), is("Line 1"));
60          List<String> matchingLines = tempFileStrings.stream().filter(s -> s.startsWith("Line "))
61                  .collect(Collectors.toList());
62          assertThat("Matching lines mismatch", matchingLines.size(), is(4));
63  
64          // Delete the temp file
65          try {
66              Files.deleteIfExists(multilineFile);
67          } catch (IOException e) {
68              fail("IO Exception deleting temporary multiline file.");
69          }
70  
71          // Try file not found on deleted file
72          assertThat("Deleted file should return empty", FileUtil.readFile(multilineFile.toString()), is(empty()));
73      }
74  
75      /**
76       * Test get*FromFile
77       */
78      @Test
79      void testGetFromFile() {
80          // Write to temp file
81          Path integerFile = null;
82          try {
83              integerFile = Files.createTempFile("oshitest.int", null);
84              Files.write(integerFile, "123\n".getBytes(StandardCharsets.UTF_8));
85          } catch (IOException e) {
86              fail("IO Exception creating or writing to temporary integer file.");
87          }
88          assertThat("unsigned long from int", FileUtil.getUnsignedLongFromFile(integerFile.toString()), is(123L));
89          assertThat("long from int", FileUtil.getLongFromFile(integerFile.toString()), is(123L));
90          assertThat("int from int", FileUtil.getIntFromFile(integerFile.toString()), is(123));
91          assertThat("string from int", FileUtil.getStringFromFile(integerFile.toString()), is("123"));
92  
93          // Delete the temp file
94          try {
95              Files.deleteIfExists(integerFile);
96          } catch (IOException e) {
97              fail("IO Exception deleting temporary integer file.");
98          }
99  
100         // Write to temp file
101         Path stringFile = null;
102         try {
103             stringFile = Files.createTempFile("oshitest.str", null);
104             Files.write(stringFile, "foo bar\n".getBytes(StandardCharsets.UTF_8));
105         } catch (IOException e) {
106             fail("IO Exception creating or writing to temporary string file.");
107         }
108 
109         assertThat("unsigned long from string", FileUtil.getUnsignedLongFromFile(stringFile.toString()), is(0L));
110         assertThat("long from string", FileUtil.getLongFromFile(stringFile.toString()), is(0L));
111         assertThat("int from string", FileUtil.getIntFromFile(stringFile.toString()), is(0));
112         assertThat("string from string", FileUtil.getStringFromFile(stringFile.toString()), is("foo bar"));
113         // Delete the temp file
114         try {
115             Files.deleteIfExists(stringFile);
116         } catch (IOException e) {
117             fail("IO Exception deleting temporary string file.");
118         }
119 
120         // Try file not found on deleted file
121         assertThat("unsigned long from invalid", FileUtil.getUnsignedLongFromFile(stringFile.toString()), is(0L));
122         assertThat("long from invalid", FileUtil.getLongFromFile(stringFile.toString()), is(0L));
123         assertThat("int from invalid", FileUtil.getIntFromFile(stringFile.toString()), is(0));
124         assertThat("string from invalid ", FileUtil.getStringFromFile(stringFile.toString()), is(emptyString()));
125     }
126 
127     @Test
128     void testReadProcIo() {
129         Map<String, String> expected = new LinkedHashMap<>();
130         expected.put("rchar", "124788352");
131         expected.put("wchar", "124802481");
132         expected.put("syscr", "135");
133         expected.put("syscw", "1547");
134         expected.put("read_bytes", "40304640");
135         expected.put("write_bytes", "124780544");
136         expected.put("cancelled_write_bytes", "42");
137         // Write this to a temp file
138         Path procIoFile = null;
139         try {
140             procIoFile = Files.createTempFile("oshitest.procio", null);
141             for (Entry<String, String> e : expected.entrySet()) {
142                 String s = e.getKey() + ": " + e.getValue() + "\n";
143                 Files.write(procIoFile, s.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
144             }
145         } catch (IOException e) {
146             fail("IO Exception creating or writing to temporary procIo file.");
147         }
148         // Read into map
149         Map<String, String> actual = FileUtil.getKeyValueMapFromFile(procIoFile.toString(), ":");
150         assertThat("procio size", actual, is(aMapWithSize(expected.size())));
151         for (Entry<String, String> entry : expected.entrySet()) {
152             assertThat("procio entry", actual, hasEntry(entry.getKey(), entry.getValue()));
153         }
154 
155         // Cleanup
156         try {
157             Files.deleteIfExists(procIoFile);
158         } catch (IOException e) {
159             fail("IO Exception deleting temporary procIo file.");
160         }
161 
162         // Test deleted file
163         actual = FileUtil.getKeyValueMapFromFile(procIoFile.toString(), ":");
164         assertThat("procio size", actual, anEmptyMap());
165     }
166 
167     @Test
168     void testReadProperties() {
169         Properties props = FileUtil.readPropertiesFromFilename("simplelogger.properties");
170         assertThat("simplelogger properties", props.getProperty("org.slf4j.simpleLogger.defaultLogLevel"), is("INFO"));
171         props = FileUtil.readPropertiesFromFilename("this.file.does.not.exist");
172         assertThat("invalid file", props.stringPropertyNames(), is(empty()));
173     }
174 
175     @Test
176     void testReadBytesFromURL() throws IOException {
177         // Create temporary files
178         Path file1 = Files.createTempFile("oshitest.file1", null);
179         Path file2 = Files.createTempFile("oshitest.file2", null);
180         Path file3 = Files.createTempFile("oshitest.file3", null);
181 
182         Files.write(file1, "Same".getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE);
183         Files.write(file2, "Same".getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE);
184         Files.write(file3, "Different".getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE);
185 
186         byte[] bytes1 = FileUtil.readFileAsBytes(file1.toUri().toURL());
187         byte[] bytes2 = FileUtil.readFileAsBytes(file2.toUri().toURL());
188         byte[] bytes3 = FileUtil.readFileAsBytes(file3.toUri().toURL());
189 
190         assertArrayEquals(bytes1, bytes2, "Byte arrays should match");
191         assertFalse(Arrays.equals(bytes1, bytes3), "Byte arrays should not match");
192     }
193 
194     @Test
195     void testReadBinaryFile() {
196         ByteBuffer buff = ByteBuffer.allocate(18 + Native.LONG_SIZE + Native.SIZE_T_SIZE);
197         buff.order(ByteOrder.nativeOrder());
198         buff.putLong(123L);
199         buff.putInt(45);
200         buff.putShort((short) 67);
201         buff.put((byte) 89);
202         if (Native.LONG_SIZE > 4) {
203             buff.putLong(10L);
204         } else {
205             buff.putInt(10);
206         }
207         if (Native.SIZE_T_SIZE > 4) {
208             buff.putLong(11L);
209         } else {
210             buff.putInt(11);
211         }
212         byte[] arr = new byte[] { 1, 2, 3 };
213         buff.put(arr);
214 
215         // Write to temp file
216         Path binaryFile = null;
217         try {
218             binaryFile = Files.createTempFile("oshitest.binary", null);
219             Files.write(binaryFile, buff.array());
220         } catch (IOException e) {
221             fail("IO Exception creating or writing to temporary binary file.");
222         }
223 
224         // Read from file
225         buff = FileUtil.readAllBytesAsBuffer(binaryFile.toString());
226         assertThat("Buffer size should match bytes written", buff.limit(),
227                 is(18 + Native.LONG_SIZE + Native.SIZE_T_SIZE));
228         assertThat("Long from buffer should match", FileUtil.readLongFromBuffer(buff), is(123L));
229         assertThat("Int from buffer should match", FileUtil.readIntFromBuffer(buff), is(45));
230         assertThat("Short from buffer should match", FileUtil.readShortFromBuffer(buff), is((short) 67));
231         assertThat("Byte from buffer should match", FileUtil.readByteFromBuffer(buff), is((byte) 89));
232         assertThat("NativeLong from buffer should match", FileUtil.readNativeLongFromBuffer(buff).longValue(), is(10L));
233         assertThat("SizeT from buffer should match", FileUtil.readSizeTFromBuffer(buff).longValue(), is(11L));
234         byte[] array = new byte[3];
235         FileUtil.readByteArrayFromBuffer(buff, array);
236         assertArrayEquals(arr, array, "Byte array from buffer should match");
237         // Test reads past end of file
238         assertThat("Long from buffer at limit should be 0", FileUtil.readLongFromBuffer(buff), is(0L));
239         assertThat("Int from buffer at limit should be 0", FileUtil.readIntFromBuffer(buff), is(0));
240         assertThat("Short from buffer at limit should be 0", FileUtil.readShortFromBuffer(buff), is((short) 0));
241         assertThat("Byte from buffer at limit should be 0", FileUtil.readByteFromBuffer(buff), is((byte) 0));
242         assertThat("NativeLong from buffer at limit should be 0", FileUtil.readNativeLongFromBuffer(buff).longValue(),
243                 is(0L));
244         assertThat("SizeT from buffer at limit should be 0", FileUtil.readSizeTFromBuffer(buff).longValue(), is(0L));
245         byte[] arr0 = new byte[] { 0, 0, 0 };
246         array = new byte[3];
247         FileUtil.readByteArrayFromBuffer(buff, array);
248         assertArrayEquals(arr0, array, "Byte array from buffer at limit should be all 0s");
249 
250         // Cleanup
251         try {
252             Files.deleteIfExists(binaryFile);
253         } catch (IOException e) {
254             fail("IO Exception deleting temporary procIo file.");
255         }
256     }
257 }