23 |
23 |
24 import javax.naming.Context; |
24 import javax.naming.Context; |
25 import javax.naming.NamingException; |
25 import javax.naming.NamingException; |
26 import javax.naming.directory.Attributes; |
26 import javax.naming.directory.Attributes; |
27 import java.io.PrintStream; |
27 import java.io.PrintStream; |
28 import java.net.DatagramSocket; |
|
29 import java.nio.file.Files; |
28 import java.nio.file.Files; |
30 import java.nio.file.Path; |
29 import java.nio.file.Path; |
31 import java.nio.file.Paths; |
30 import java.nio.file.Paths; |
32 import java.util.Hashtable; |
31 import java.util.Hashtable; |
33 |
32 |
|
33 /** |
|
34 * This is utility class for DNS test, it contains many helper methods to |
|
35 * support test construction. |
|
36 * |
|
37 * For basic test sequence see TestBase and DNSTestBase. |
|
38 */ |
34 public class DNSTestUtils { |
39 public class DNSTestUtils { |
35 public static final String TEST_DNS_SERVER_THREAD = "test.dns.server.thread"; |
40 public static final String TEST_DNS_SERVER_THREAD = "test.dns.server.thread"; |
36 public static final String TEST_DNS_ROOT_URL = "test.dns.root.url"; |
41 public static final String TEST_DNS_ROOT_URL = "test.dns.root.url"; |
37 public static final int HOSTS_LOOKUP_MAX_DEPTH = 3; |
42 public static final int HOSTS_LOOKUP_MAX_DEPTH = 3; |
38 |
43 |
39 protected static boolean debug = true; |
44 protected static boolean debug = true; |
40 |
45 |
41 /* |
46 /** |
42 * Check that attrs contains the mandatory attributes and the right |
47 * Check that attributes contains the mandatory attributes and the right |
43 * objectclass attribute |
48 * objectclass attribute. |
|
49 * |
|
50 * @param attrs given attributes to verify |
|
51 * @param mandatory given mandatory for verification |
|
52 * @param optional given optional for verification |
|
53 * @return <tt>true</tt> if check ok |
44 */ |
54 */ |
45 public static boolean checkSchema(Attributes attrs, String[] mandatory, |
55 public static boolean checkSchema(Attributes attrs, String[] mandatory, |
46 String[] optional) { |
56 String[] optional) { |
47 // Check mandatory attributes |
57 // Check mandatory attributes |
48 for (String mandatoryAttr : mandatory) { |
58 for (String mandatoryAttr : mandatory) { |
68 } |
78 } |
69 |
79 |
70 return true; |
80 return true; |
71 } |
81 } |
72 |
82 |
73 /* |
83 /** |
74 * Process command line arguments and init env |
84 * Process command line arguments and init env. |
75 */ |
85 * This method will prepare default environments which to be used to initial |
76 public static Hashtable<Object, Object> initEnv(DatagramSocket socket, |
86 * DirContext. |
|
87 * |
|
88 * @param localServer <tt>true</tt> if this test will run against with local |
|
89 * server against dump message playback |
|
90 * @param testname test case name to identify playback file |
|
91 * @param args additional arguments for env preparation |
|
92 * @return prepared env which will be used later to initial DirContext |
|
93 */ |
|
94 public static Hashtable<Object, Object> initEnv(boolean localServer, |
77 String testname, String[] args) { |
95 String testname, String[] args) { |
78 |
96 |
79 Hashtable<Object, Object> env = new Hashtable<>(); |
97 Hashtable<Object, Object> env = new Hashtable<>(); |
80 |
98 |
81 // set some default parameters if no additional specified |
99 // set some default parameters if no additional specified |
87 env.put(Context.INITIAL_CONTEXT_FACTORY, |
105 env.put(Context.INITIAL_CONTEXT_FACTORY, |
88 "com.sun.jndi.dns.DnsContextFactory"); |
106 "com.sun.jndi.dns.DnsContextFactory"); |
89 |
107 |
90 boolean traceEnable = false; |
108 boolean traceEnable = false; |
91 boolean loopPlayback = false; |
109 boolean loopPlayback = false; |
92 for (int i = 0; i < args.length; i++) { |
110 for (String arg : args) { |
93 if ((args[i].equals("-D")) && (args.length > i + 1)) { |
111 if (arg.startsWith("-D")) { |
94 extractProperty(args[++i], env); |
112 extractProperty(arg.substring(2), env); |
95 } else if (args[i].startsWith("-D")) { |
113 } else if (arg.equalsIgnoreCase("-trace")) { |
96 extractProperty(args[i].substring(2), env); |
|
97 } else if (args[i].equalsIgnoreCase("-trace")) { |
|
98 traceEnable = true; |
114 traceEnable = true; |
99 } else if (args[i].equalsIgnoreCase("-loop")) { |
115 } else if (arg.equalsIgnoreCase("-loop")) { |
100 loopPlayback = true; |
116 loopPlayback = true; |
101 } |
117 } |
102 } |
118 } |
103 |
119 |
104 debug = Boolean.valueOf(System.getProperty("debug", "true")); |
120 debug = Boolean.valueOf(System.getProperty("debug", "true")); |
109 String url = "dns://" + env.get("DNS_SERVER") + portSuffix; |
125 String url = "dns://" + env.get("DNS_SERVER") + portSuffix; |
110 env.put(Context.PROVIDER_URL, url); |
126 env.put(Context.PROVIDER_URL, url); |
111 env.put(Context.PROVIDER_URL, url + "/" + env.get("DNS_DOMAIN")); |
127 env.put(Context.PROVIDER_URL, url + "/" + env.get("DNS_DOMAIN")); |
112 } |
128 } |
113 |
129 |
114 Runnable inst = null; |
130 Thread inst = null; |
115 if (traceEnable) { |
131 if (traceEnable) { |
116 inst = createDNSTracer(socket, testname, env); |
132 // if trace is enabled, create DNSTracer to dump those message |
|
133 inst = createDNSTracer(testname, env); |
117 } else { |
134 } else { |
118 if (socket != null) { |
135 if (localServer) { |
119 inst = createDNSServer(socket, testname, loopPlayback); |
136 // if use local server, create local DNSServer for playback |
|
137 inst = createDNSServer(testname, loopPlayback); |
120 } else { |
138 } else { |
121 // for tests which run against remote server |
139 // for tests which run against remote server |
122 // or no server required |
140 // or no server required |
123 debug("Skip local DNS Server creation " |
141 debug("Skip local DNS Server creation "); |
124 + "since DatagramSocket is null"); |
|
125 } |
142 } |
126 } |
143 } |
127 |
144 |
128 if (inst != null) { |
145 if (inst != null) { |
129 env.put(TEST_DNS_SERVER_THREAD, startServer(inst)); |
146 inst.start(); |
130 String url = "dns://localhost:" + socket.getLocalPort(); |
147 env.put(TEST_DNS_SERVER_THREAD, inst); |
|
148 String url = "dns://localhost:" + ((Server) inst).getPort(); |
131 |
149 |
132 env.put(TEST_DNS_ROOT_URL, url); |
150 env.put(TEST_DNS_ROOT_URL, url); |
133 env.put(Context.PROVIDER_URL, url + "/" + env.get("DNS_DOMAIN")); |
151 env.put(Context.PROVIDER_URL, url + "/" + env.get("DNS_DOMAIN")); |
134 } |
152 } |
135 |
153 |
136 return env; |
154 return env; |
137 } |
155 } |
138 |
156 |
139 /* |
157 /** |
140 * Clean-up the directory context. |
158 * Clean-up the given directory context. |
|
159 * |
|
160 * @param ctx given context object |
141 */ |
161 */ |
142 public static void cleanup(Context ctx) { |
162 public static void cleanup(Context ctx) { |
143 if (ctx != null) { |
163 if (ctx != null) { |
144 try { |
164 try { |
145 ctx.close(); |
165 ctx.close(); |
160 throw new RuntimeException( |
180 throw new RuntimeException( |
161 "Failed to extract test args property from " + propString); |
181 "Failed to extract test args property from " + propString); |
162 } |
182 } |
163 } |
183 } |
164 |
184 |
165 public static DNSTracer createDNSTracer(DatagramSocket socket, |
185 /** |
166 String testname, Hashtable<Object, Object> env) { |
186 * Return new created DNS tracer. |
167 if (socket == null) { |
187 * |
168 throw new RuntimeException("Error: failed to create DNSTracer " |
188 * @param testname test case name to identify playback file |
169 + "since DatagramSocket is null"); |
189 * @param env given env for initialization |
170 } |
190 * @return created DNS tracer |
171 |
191 * @see DNSTracer |
|
192 */ |
|
193 public static DNSTracer createDNSTracer(String testname, |
|
194 Hashtable<Object, Object> env) { |
172 try { |
195 try { |
173 PrintStream outStream = new PrintStream(getCaptureFile(testname)); |
196 PrintStream outStream = new PrintStream(getCaptureFile(testname)); |
174 return new DNSTracer(socket, outStream, |
197 return new DNSTracer(outStream, (String) env.get("DNS_SERVER"), |
175 (String) env.get("DNS_SERVER"), |
|
176 Integer.parseInt((String) env.get("DNS_PORT"))); |
198 Integer.parseInt((String) env.get("DNS_PORT"))); |
177 } catch (Exception e) { |
199 } catch (Exception e) { |
178 throw new RuntimeException( |
200 throw new RuntimeException( |
179 "Error: failed to create DNSTracer : " + e.getMessage(), e); |
201 "Error: failed to create DNSTracer : " + e.getMessage(), e); |
180 } |
202 } |
181 } |
203 } |
182 |
204 |
183 public static DNSServer createDNSServer(DatagramSocket socket, |
205 /** |
184 String testname, boolean loop) { |
206 * Return new created local DNS Server. |
185 if (socket == null) { |
207 * |
186 throw new RuntimeException("Error: failed to create DNSServer " |
208 * @param testname test case name to identify playback file |
187 + "since DatagramSocket is null"); |
209 * @param loop <tt>true</tt> if DNS server required playback message in loop |
188 } |
210 * @return created local DNS Server |
189 |
211 * @see DNSServer |
|
212 */ |
|
213 public static DNSServer createDNSServer(String testname, boolean loop) { |
190 String path = getCaptureFile(testname); |
214 String path = getCaptureFile(testname); |
191 if (Files.exists(Paths.get(path))) { |
215 if (Files.exists(Paths.get(path))) { |
192 return new DNSServer(socket, path, loop); |
216 try { |
|
217 return new DNSServer(path, loop); |
|
218 } catch (Exception e) { |
|
219 throw new RuntimeException( |
|
220 "Error: failed to create DNSServer : " + e.getMessage(), |
|
221 e); |
|
222 } |
193 } else { |
223 } else { |
194 throw new RuntimeException( |
224 throw new RuntimeException( |
195 "Error: failed to create DNSServer, not found dns " |
225 "Error: failed to create DNSServer, not found dns " |
196 + "cache file " + path); |
226 + "cache file " + path); |
197 } |
227 } |
198 } |
228 } |
199 |
229 |
200 public static Thread startServer(Runnable runnable) { |
230 /** |
201 Thread thread = new Thread(runnable); |
231 * Return dns message capture file path. |
202 thread.start(); |
232 * |
203 return thread; |
233 * @param testname test case name to identify playback file |
204 } |
234 * @return capture file path |
205 |
235 */ |
206 public static String getCaptureFile(String testname) { |
236 public static String getCaptureFile(String testname) { |
207 return Paths.get(System.getProperty("test.src")) |
237 return Paths.get(System.getProperty("test.src")) |
208 .resolve(testname + ".dns").toString(); |
238 .resolve(testname + ".dns").toString(); |
209 } |
239 } |
210 |
240 |
|
241 /** |
|
242 * Enable hosts file. |
|
243 * |
|
244 * @param hostsFile given hosts file |
|
245 */ |
211 public static void enableHostsFile(String hostsFile) { |
246 public static void enableHostsFile(String hostsFile) { |
212 System.out.println("Enable jdk.net.hosts.file = " + hostsFile); |
247 System.out.println("Enable jdk.net.hosts.file = " + hostsFile); |
213 System.setProperty("jdk.net.hosts.file", hostsFile); |
248 System.setProperty("jdk.net.hosts.file", hostsFile); |
214 } |
249 } |
215 |
250 |
|
251 /** |
|
252 * Enable hosts file by given searching depth. |
|
253 * |
|
254 * @param depth given depth for searching hosts file |
|
255 */ |
216 public static void enableHostsFile(int depth) { |
256 public static void enableHostsFile(int depth) { |
217 Path path = Paths.get(System.getProperty("test.src", ".")) |
257 Path path = Paths.get(System.getProperty("test.src", ".")) |
218 .toAbsolutePath(); |
258 .toAbsolutePath(); |
219 for (int i = depth; i >= 0; i--) { |
259 for (int i = depth; i >= 0; i--) { |
220 Path filePath = path.resolve("hosts"); |
260 Path filePath = path.resolve("hosts"); |
228 break; |
268 break; |
229 } |
269 } |
230 } |
270 } |
231 } |
271 } |
232 |
272 |
|
273 /** |
|
274 * Print given object if debug enabled. |
|
275 * |
|
276 * @param object given object to print |
|
277 */ |
233 public static void debug(Object object) { |
278 public static void debug(Object object) { |
234 if (debug) { |
279 if (debug) { |
235 System.out.println(object); |
280 System.out.println(object); |
236 } |
281 } |
237 } |
282 } |
238 |
283 |
|
284 /** |
|
285 * Verify attributes contains the mandatory attributes and the right |
|
286 * objectclass attribute, will throw RuntimeException if verify failed. |
|
287 * |
|
288 * @param attrs given attributes to verify |
|
289 * @param mandatory given mandatory for verification |
|
290 * @param optional given optional for verification |
|
291 */ |
239 public static void verifySchema(Attributes attrs, String[] mandatory, |
292 public static void verifySchema(Attributes attrs, String[] mandatory, |
240 String[] optional) { |
293 String[] optional) { |
241 debug(attrs); |
294 debug(attrs); |
242 if (!checkSchema(attrs, mandatory, optional)) { |
295 if (!checkSchema(attrs, mandatory, optional)) { |
243 throw new RuntimeException("Check schema failed."); |
296 throw new RuntimeException("Check schema failed."); |
244 } |
297 } |
245 } |
298 } |
|
299 |
|
300 /** |
|
301 * Return dns root url. |
|
302 * |
|
303 * @param env given env |
|
304 * @return dns root url |
|
305 */ |
|
306 public static String getRootUrl(Hashtable<Object, Object> env) { |
|
307 return (String) env.get(TEST_DNS_ROOT_URL); |
|
308 } |
|
309 |
|
310 /** |
|
311 * Assemble a fully-qualified domain name from the base component and the |
|
312 * domain name. |
|
313 * |
|
314 * @param base given base component |
|
315 * @param env given env |
|
316 * @param primary <tt>true</tt> if primary domain |
|
317 * @return assembled fully-qualified domain name |
|
318 */ |
|
319 public static String buildFqdn(String base, Hashtable<Object, Object> env, |
|
320 boolean primary) { |
|
321 String domain = (String) (primary ? |
|
322 env.get("DNS_DOMAIN") : |
|
323 env.get("FOREIGN_DOMAIN")); |
|
324 |
|
325 return base + "." + domain; |
|
326 } |
246 } |
327 } |