1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24import java.io.ByteArrayInputStream;
25import java.io.ByteArrayOutputStream;
26import java.io.DataOutputStream;
27import java.io.IOException;
28import java.io.InputStream;
29import java.nio.ByteOrder;
30import java.nio.file.Path;
31import java.util.ArrayList;
32import java.util.Collections;
33import java.util.HashSet;
34import java.util.List;
35import java.util.Set;
36import java.util.stream.Stream;
37import jdk.tools.jlink.internal.Archive;
38import jdk.tools.jlink.internal.ImageFileCreator;
39import jdk.tools.jlink.internal.ImagePluginStack;
40import jdk.tools.jlink.internal.ExecutableImage;
41import jdk.tools.jlink.builder.ImageBuilder;
42import jdk.tools.jlink.plugin.ResourcePool;
43
44
45/*
46 * @test
47 * @summary ImageFileCreator class test
48 * @author Jean-Francois Denise
49 * @modules jdk.jlink/jdk.tools.jlink.internal
50 *          jdk.jlink/jdk.tools.jlink.builder
51 *          jdk.jlink/jdk.tools.jlink.plugin
52 *          java.base/jdk.internal.jimage
53 * @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest
54 */
55public class ImageFileCreatorTest {
56
57    private static class TestArchive implements Archive {
58
59        private final String name;
60        private final List<Entry> entries = new ArrayList<>();
61
62        private TestArchive(String name, List<String> entries) {
63            this.name = name;
64            for (String p : entries) {
65                this.entries.add(new TestEntry(p, p));
66            }
67        }
68
69        @Override
70        public String moduleName() {
71            return name;
72        }
73
74        @Override
75        public Stream<Entry> entries() {
76            return entries.stream();
77        }
78
79        @Override
80        public Path getPath() {
81            return null;
82        }
83
84        @Override
85        public void open() throws IOException {
86        }
87
88        @Override
89        public void close() throws IOException {
90        }
91
92        private class TestEntry extends Entry {
93
94            TestEntry(String path, String name) {
95                super(TestArchive.this, path, name, Entry.EntryType.CLASS_OR_RESOURCE);
96            }
97
98            @Override
99            public long size() {
100                return 0;
101            }
102
103            @Override
104            public InputStream stream() throws IOException {
105                return new ByteArrayInputStream(new byte[0]);
106            }
107        }
108    }
109
110    public static void main(String[] args) throws Exception {
111
112        {
113            List<String> entries = new ArrayList<>();
114            entries.add("classes/class");
115            test(entries);
116        }
117
118        {
119            // Add an entry that is a directory, that is wrong
120            List<String> entries = new ArrayList<>();
121            entries.add("classes");
122            entries.add("classes/class");
123            test(entries);
124        }
125
126        {
127            // Add an entry that is wrongly prefixed by /
128            // /bad//classes/class is the resource added
129            // /bad/classes/class is the metadata node built.
130            List<String> entries = new ArrayList<>();
131            entries.add("/classes/class");
132            test(entries);
133        }
134
135        {
136            // Trailing '/' is wrong
137            List<String> entries = new ArrayList<>();
138            entries.add("classes/class/");
139            test(entries);
140        }
141
142        {
143            // Too much '/' characters
144            List<String> entries = new ArrayList<>();
145            entries.add("classes//class/");
146            test(entries);
147        }
148
149        {
150            // Too much '/' characters
151            List<String> entries = new ArrayList<>();
152            entries.add("classes/////class/");
153            test(entries);
154        }
155
156        {
157            // Single '/' character
158            List<String> entries = new ArrayList<>();
159            entries.add("/");
160            test(entries);
161        }
162
163        {
164            // 2 '/' characters
165            List<String> entries = new ArrayList<>();
166            entries.add("//");
167            test(entries);
168        }
169
170        {
171            // 3 '/' characters
172            List<String> entries = new ArrayList<>();
173            entries.add("///");
174            test(entries);
175        }
176
177        {
178            // no character
179            List<String> entries = new ArrayList<>();
180            entries.add("");
181            test(entries);
182        }
183
184        {
185            // all together
186            List<String> entries = new ArrayList<>();
187            entries.add("");
188            entries.add("///");
189            entries.add("//");
190            entries.add("/");
191            entries.add("classes/////class/");
192            entries.add("classes//class/");
193            entries.add("classes/class/");
194            entries.add("/classes/class");
195            entries.add("classes");
196            entries.add("classes/class");
197            test(entries);
198        }
199
200    }
201
202    private static void test(List<String> entries) throws Exception {
203        TestArchive arch = new TestArchive("bad", entries);
204        Set<Archive> archives = new HashSet<>();
205        archives.add(arch);
206        ImageBuilder noopBuilder = new ImageBuilder() {
207
208            @Override
209            public DataOutputStream getJImageOutputStream() {
210                return new DataOutputStream(new ByteArrayOutputStream());
211            }
212
213            @Override
214            public ExecutableImage getExecutableImage() {
215                return null;
216            }
217
218            @Override
219            public void storeFiles(ResourcePool content) {
220            }
221        };
222
223        ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(),
224                null, false);
225
226        ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack);
227    }
228}
229