1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package libcore.java.nio.file;
18
19import org.junit.rules.TestRule;
20import org.junit.runner.Description;
21import org.junit.runners.model.Statement;
22
23import java.io.BufferedWriter;
24import java.io.File;
25import java.io.FileWriter;
26import java.io.IOException;
27import java.io.InputStream;
28import java.io.OutputStream;
29import java.nio.file.CopyOption;
30import java.nio.file.DirectoryStream;
31import java.nio.file.Files;
32import java.nio.file.LinkOption;
33import java.nio.file.OpenOption;
34import java.nio.file.Path;
35import java.nio.file.Paths;
36import java.nio.file.attribute.BasicFileAttributes;
37
38class FilesSetup implements TestRule {
39
40    final static String DATA_FILE = "dataFile";
41
42    final static String NON_EXISTENT_FILE = "nonExistentFile";
43
44    final static String TEST_FILE_DATA = "hello";
45
46    final static String TEST_FILE_DATA_2 = "test";
47
48    /**
49     *  Data that includes characters code above the US-ASCII range and will be more obviously
50     *  corrupted if encoded / decoded incorrectly than
51     *  {@link #TEST_FILE_DATA} / {@link #TEST_FILE_DATA_2}.
52     */
53    final static String UTF_16_DATA = "परीक्षण";
54
55    private String testDir;
56
57    private Path dataFilePath;
58
59    private Path testPath;
60
61    private Path testDirPath;
62
63    private boolean filesInitialized = false;
64
65    void setUp() throws Exception {
66        initializeFiles();
67    }
68
69    void tearDown() throws Exception {
70        filesInitialized = false;
71        clearAll();
72    }
73
74    private void initializeFiles() throws IOException {
75        testDirPath = Files.createTempDirectory("testDir");
76        testDir = testDirPath.toString();
77        dataFilePath = Paths.get(testDir, DATA_FILE);
78        testPath = Paths.get(testDir, NON_EXISTENT_FILE);
79        File testInputFile = new File(testDir, DATA_FILE);
80        if (!testInputFile.exists()) {
81            testInputFile.createNewFile();
82        }
83        FileWriter fw = new FileWriter(testInputFile.getAbsoluteFile());
84        BufferedWriter bw = new BufferedWriter(fw);
85        bw.write(TEST_FILE_DATA);
86        bw.close();
87        filesInitialized = true;
88    }
89
90    Path getTestPath() {
91        checkState();
92        return testPath;
93    }
94
95    Path getDataFilePath() {
96        checkState();
97        return dataFilePath;
98    }
99
100    Path getTestDirPath() {
101        checkState();
102        return testDirPath;
103    }
104
105    String getTestDir() {
106        checkState();
107        return testDir;
108    }
109
110    private void checkState() {
111        if (!filesInitialized) {
112            throw new IllegalStateException("Files are not setup.");
113        }
114    }
115
116    void clearAll() throws IOException {
117        Path root = Paths.get(testDir);
118        delete(root);
119    }
120
121    void reset() throws IOException {
122        clearAll();
123        initializeFiles();
124    }
125
126    private static void delete(Path path) throws IOException {
127        if (Files.isDirectory(path)) {
128            DirectoryStream<Path> dirStream = Files.newDirectoryStream(path);
129            dirStream.forEach(
130                    p -> {
131                        try {
132                            delete(p);
133                        } catch (IOException e) {
134                            throw new RuntimeException(e);
135                        }
136                    }
137            );
138            dirStream.close();
139        }
140        try {
141            Files.deleteIfExists(path);
142        } catch (Exception e) {
143            // Do nothing
144        }
145    }
146
147    static void writeToFile(Path file, String data, OpenOption... option) throws IOException {
148        OutputStream os = Files.newOutputStream(file, option);
149        os.write(data.getBytes());
150        os.close();
151    }
152
153    static String readFromFile(Path file) throws IOException {
154        InputStream is = Files.newInputStream(file);
155        return readFromInputStream(is);
156    }
157
158    static String readFromInputStream(InputStream is) throws IOException {
159        byte[] input = new byte[10000];
160        is.read(input);
161        return new String(input, "UTF-8").trim();
162    }
163
164    static Process execCmdAndWaitForTermination(String... cmdList)
165            throws InterruptedException, IOException {
166        Process process = Runtime.getRuntime().exec(cmdList);
167        // Wait for the process to terminate.
168        process.waitFor();
169        return process;
170    }
171
172    @Override
173    public Statement apply(Statement statement, Description description) {
174        return new Statement() {
175            @Override
176            public void evaluate() throws Throwable {
177                try {
178                    setUp();
179                    statement.evaluate();
180                } finally {
181                    tearDown();
182                }
183            }
184        };
185    }
186
187    Path getPathInTestDir(String path) {
188        return Paths.get(getTestDir(), path);
189    }
190
191    /**
192     * Non Standard CopyOptions.
193     */
194    enum NonStandardOption implements CopyOption, OpenOption {
195        OPTION1,
196    }
197
198}
199