1 package org.jivesoftware.openfire.net;
2 
3 import org.jivesoftware.openfire.net.DNSUtil;
4 import org.junit.Assert;
5 import org.junit.Test;
6 
7 import java.util.List;
8 
9 /**
10  * Unit tests for {@link org.jivesoftware.openfire.net.DNSUtil}.
11  *
12  * @author Guus der Kinderen, guus.der.kinderen@gmail.com
13  */
14 public class DNSUtilTest {
15 
16     //@Test
testJabberDotOrg()17     public void testJabberDotOrg() throws Exception {
18         for (int i=0; i<=10; i++) {
19         final List<DNSUtil.HostAddress> list = DNSUtil.resolveXMPPDomain("jabber.org", 5222);
20         for(DNSUtil.HostAddress address : list) {
21             System.out.println("Address: " + address.toString());
22         }
23             System.out.println("");
24         }
25     }
26 
27     /**
28      * Runs {@link DNSUtil#prioritize(org.jivesoftware.openfire.net.DNSUtil.WeightedHostAddress[])} on a copy of the
29      * DNS SRV xmpp-server records for jabber.org (as they were last 2012).
30      */
31     @Test
testJabberDotOrgMock()32     public void testJabberDotOrgMock() throws Exception {
33         // setup
34         final DNSUtil.WeightedHostAddress fallback = new DNSUtil.WeightedHostAddress("fallback.jabber.org", 5269, false, 31, 31);
35         final DNSUtil.WeightedHostAddress hermes6  = new DNSUtil.WeightedHostAddress("hermes6.jabber.org",  5269, false, 30, 30);
36         final DNSUtil.WeightedHostAddress hermes   = new DNSUtil.WeightedHostAddress("hermes.jabber.org",   5269, false, 30, 30);
37 
38         // do magic
39         final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(new DNSUtil.WeightedHostAddress[]{fallback, hermes6, hermes});
40 
41         // verify
42         Assert.assertEquals("There were three records in the input, the output should have contained the same amount.", 3, result.size());
43         Assert.assertTrue("The 'hermes' host should have been included somewhere in the output."   , result.contains(hermes));
44         Assert.assertTrue("The 'hermes6' host should have been included somewhere in the output."  , result.contains(hermes6));
45         Assert.assertTrue("The 'fallback' host should bhave been included somewhere in the output.", result.contains(fallback));
46         Assert.assertEquals("The 'fallback' host should have been the last record in the result."  , fallback, result.get(2));
47     }
48 
49     /**
50      * A basic check that verifies that when one hosts exists, it gets returned in the output.
51      */
52     @Test
testOneHost()53     public void testOneHost() throws Exception {
54         // setup
55         final DNSUtil.WeightedHostAddress host = new DNSUtil.WeightedHostAddress("host", 5222, false, 1, 1);
56 
57         // do magic
58         final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(new DNSUtil.WeightedHostAddress[]{host});
59 
60         // verify
61         Assert.assertEquals( 1, result.size() );
62         Assert.assertEquals(host, result.get(0));
63     }
64 
65     /**
66      * A check equal to {@link #testOneHost()}, but using (the edge-case) priority value of zero.
67      */
68     @Test
testOneHostZeroPiority()69     public void testOneHostZeroPiority() throws Exception {
70         // setup
71         final DNSUtil.WeightedHostAddress host = new DNSUtil.WeightedHostAddress("host", 5222, false, 0, 1);
72 
73         // do magic
74         final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(new DNSUtil.WeightedHostAddress[]{host});
75 
76         // verify
77         Assert.assertEquals(1, result.size());
78         Assert.assertEquals(host, result.get(0));
79     }
80 
81     /**
82      * A check equal to {@link #testOneHost()}, but using (the edge-case) weight value of zero.
83      */
84     @Test
testOneHostZeroWeight()85     public void testOneHostZeroWeight() throws Exception {
86         // setup
87         final DNSUtil.WeightedHostAddress host = new DNSUtil.WeightedHostAddress("host", 5222, false, 1, 0);
88 
89         // do magic
90         final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(new DNSUtil.WeightedHostAddress[]{host});
91 
92         // verify
93         Assert.assertEquals(1, result.size());
94         Assert.assertEquals(host, result.get(0));
95     }
96 
97     /**
98      * Verifies that when a couple of records exist that all have a particular priority, those records are all included
99      * in the result, ordered (ascending) by their priority.
100      * @throws Exception
101      */
102     @Test
testDifferentPriorities()103     public void testDifferentPriorities() throws Exception {
104         // setup
105         final DNSUtil.WeightedHostAddress hostA = new DNSUtil.WeightedHostAddress("hostA", 5222, false, 1, 1);
106         final DNSUtil.WeightedHostAddress hostB = new DNSUtil.WeightedHostAddress("hostB", 5222, false, 3, 1);
107         final DNSUtil.WeightedHostAddress hostC = new DNSUtil.WeightedHostAddress("hostC", 5222, false, 2, 1);
108 
109         // do magic
110         final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(new DNSUtil.WeightedHostAddress[]{hostA, hostB, hostC});
111 
112         // verify
113         Assert.assertEquals(3, result.size());
114         Assert.assertEquals(hostA, result.get(0));
115         Assert.assertEquals(hostC, result.get( 1 ));
116         Assert.assertEquals(hostB, result.get(2));
117     }
118 
119     /**
120      * A test equal to {@link #testDifferentPriorities()}, but with one of the priorities set to zero.
121      */
122     @Test
testZeroPriority()123     public void testZeroPriority() throws Exception {
124         // setup
125         final DNSUtil.WeightedHostAddress hostA = new DNSUtil.WeightedHostAddress("hostA", 5222, false, 0, 1);
126         final DNSUtil.WeightedHostAddress hostB = new DNSUtil.WeightedHostAddress("hostB", 5222, false, 2, 1);
127         final DNSUtil.WeightedHostAddress hostC = new DNSUtil.WeightedHostAddress("hostC", 5222, false, 1, 1);
128 
129         // do magic
130         final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(new DNSUtil.WeightedHostAddress[]{hostA, hostB, hostC});
131 
132         // verify
133         Assert.assertEquals(3, result.size());
134         Assert.assertEquals(hostA, result.get(0));
135         Assert.assertEquals(hostC, result.get(1));
136         Assert.assertEquals(hostB, result.get(2));
137     }
138 
139     /**
140      * A test that verifies that hosts with equal weight are alternately first in the resulting list.
141      *
142      * The test that is done here re-executes until each of the input records was included in the output as the first
143      * record. This indicates that the returning list is at the very least not always ordered in the exact same way.
144      */
145     @Test
testSameWeights()146     public void testSameWeights() throws Exception {
147         // setup
148         final DNSUtil.WeightedHostAddress hostA = new DNSUtil.WeightedHostAddress("hostA", 5222, false, 1, 10);
149         final DNSUtil.WeightedHostAddress hostB = new DNSUtil.WeightedHostAddress("hostB", 5222, false, 1, 10);
150         final DNSUtil.WeightedHostAddress[] hosts = new DNSUtil.WeightedHostAddress[] { hostA, hostB };
151 
152         // do magic
153         boolean hostAWasFirst = false;
154         boolean hostBWasFirst = false;
155         final int maxTries = Integer.MAX_VALUE;
156         for (int i=0; i<maxTries; i++) {
157             final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(hosts);
158             if (hostA.equals(result.get(0))) {
159                 hostAWasFirst = true;
160             }
161 
162             if (hostB.equals(result.get(0))) {
163                 hostBWasFirst = true;
164             }
165 
166             if (hostAWasFirst && hostBWasFirst) {
167                 break;
168             }
169 
170             if (i%1000000==0 && i>0) {
171                 System.err.println("The last " + i + " iterations of this test all had the same result, which is very unlikely to occur (there should be an even distribution between two possible outcomes). We'll iterate up to "+ maxTries +" times, but you might want to abort the unit test at this point...");
172             }
173         }
174 
175         // verify
176         Assert.assertTrue( hostAWasFirst );
177         Assert.assertTrue( hostBWasFirst );
178     }
179 
180     /**
181      * A test equal to {@link #testSameWeights()}, but using records with a weight of zero.
182      */
183     @Test
testZeroWeights()184     public void testZeroWeights() throws Exception {
185         // setup
186         final DNSUtil.WeightedHostAddress hostA = new DNSUtil.WeightedHostAddress("hostA", 5222, false, 1, 0);
187         final DNSUtil.WeightedHostAddress hostB = new DNSUtil.WeightedHostAddress("hostB", 5222, false, 1, 0);
188         final DNSUtil.WeightedHostAddress[] hosts = new DNSUtil.WeightedHostAddress[] { hostA, hostB };
189 
190         // do magic
191         boolean hostAWasFirst = false;
192         boolean hostBWasFirst = false;
193         final int maxTries = Integer.MAX_VALUE;
194         for (int i=0; i<maxTries; i++) {
195             final List<DNSUtil.WeightedHostAddress> result = DNSUtil.prioritize(hosts);
196             if (hostA.equals(result.get(0))) {
197                 hostAWasFirst = true;
198             }
199 
200             if (hostB.equals(result.get(0))) {
201                 hostBWasFirst = true;
202             }
203 
204             if (hostAWasFirst && hostBWasFirst) {
205                 break;
206             }
207 
208             if (i%1000000==0 && i>0) {
209                 System.err.println("The last " + i + " iterations of this test all had the same result, which is very unlikely to occur (there should be an even distribution between two possible outcomes). We'll iterate up to "+ maxTries +" times, but you might want to abort the unit test at this point...");
210             }
211         }
212 
213         // verify
214         Assert.assertTrue(hostAWasFirst);
215         Assert.assertTrue(hostBWasFirst);
216     }
217 
218     /**
219      * A test that verifies that {@link DNSUtil#isNameCoveredByPattern(String, String)} finds a match when both
220      * arguments have the same value.
221      */
222     @Test
testNameCoverageExactMatch()223     public void testNameCoverageExactMatch() throws Exception
224     {
225         // setup
226         final String name = "xmpp.example.org";
227         final String pattern = name;
228 
229         // do magic
230         final boolean result = DNSUtil.isNameCoveredByPattern( name, pattern );
231 
232         // verify
233         Assert.assertTrue( result );
234     }
235 
236     /**
237      * A test that verifies that {@link DNSUtil#isNameCoveredByPattern(String, String)} does not find a match when both
238      * arguments have different values.
239      */
240     @Test
testNameCoverageUnequal()241     public void testNameCoverageUnequal() throws Exception
242     {
243         // setup
244         final String name = "xmpp.example.org";
245         final String pattern = "something.completely.different";
246 
247         // do magic
248         final boolean result = DNSUtil.isNameCoveredByPattern( name, pattern );
249 
250         // verify
251         Assert.assertFalse( result );
252     }
253 
254     /**
255      * A test that verifies that {@link DNSUtil#isNameCoveredByPattern(String, String)} does not find a match when the
256      * needle/name is a subdomain of the DNS pattern, without the DNS pattern including a wildcard.
257      */
258     @Test
testNameCoverageSubdomainNoWildcard()259     public void testNameCoverageSubdomainNoWildcard() throws Exception
260     {
261         // setup
262         final String name = "xmpp.example.org";
263         final String pattern = "example.org";
264 
265         // do magic
266         final boolean result = DNSUtil.isNameCoveredByPattern( name, pattern );
267 
268         // verify
269         Assert.assertFalse( result );
270     }
271 
272     /**
273      * A test that verifies that {@link DNSUtil#isNameCoveredByPattern(String, String)} does not find a match when the
274      * last part of the needle/name equals the pattern.
275      */
276     @Test
testNameCoveragePartialMatchButNoSubdomain()277     public void testNameCoveragePartialMatchButNoSubdomain() throws Exception
278     {
279         // setup
280         final String name = "xmppexample.org";
281         final String pattern = "example.org";
282 
283         // do magic
284         final boolean result = DNSUtil.isNameCoveredByPattern( name, pattern );
285 
286         // verify
287         Assert.assertFalse( result );
288     }
289 
290     /**
291      * A test that verifies that {@link DNSUtil#isNameCoveredByPattern(String, String)} finds a match when the
292      * needle/name is a subdomain of the DNS pattern, while the DNS pattern includes a wildcard.
293      */
294     @Test
testNameCoverageSubdomainWithWildcard()295     public void testNameCoverageSubdomainWithWildcard() throws Exception
296     {
297         // setup
298         final String name = "xmpp.example.org";
299         final String pattern = "*.example.org";
300 
301         // do magic
302         final boolean result = DNSUtil.isNameCoveredByPattern( name, pattern );
303 
304         // verify
305         Assert.assertTrue( result );
306     }
307 
308     /**
309      * A test that verifies that {@link DNSUtil#isNameCoveredByPattern(String, String)} finds a match when the
310      * needle/name is a subdomain of a subdomain of the DNS pattern, while the DNS pattern includes a wildcard.
311      */
312     @Test
testNameCoverageSubSubdomainWithWildcard()313     public void testNameCoverageSubSubdomainWithWildcard() throws Exception
314     {
315         // setup
316         final String name = "deeper.xmpp.example.org";
317         final String pattern = "*.example.org";
318 
319         // do magic
320         final boolean result = DNSUtil.isNameCoveredByPattern( name, pattern );
321 
322         // verify
323         Assert.assertTrue( result );
324     }
325 
326     /**
327      * A test that verifies that {@link DNSUtil#isNameCoveredByPattern(String, String)} finds a match when the
328      * needle/name equals the domain part of the DNS pattern, while the DNS pattern includes a wildcard.
329      *
330      * Although somewhat shady, the certificate management in Openfire depends on this to hold true.
331      */
332     @Test
testNameCoverageSubdomainWithWildcardOfSameDomain()333     public void testNameCoverageSubdomainWithWildcardOfSameDomain() throws Exception
334     {
335         // setup
336         final String name = "xmpp.example.org";
337         final String pattern = "*.xmpp.example.org";
338 
339         // do magic
340         final boolean result = DNSUtil.isNameCoveredByPattern( name, pattern );
341 
342         // verify
343         Assert.assertTrue( result );
344     }
345 
346     /**
347      * Verifies that {@link DNSUtil#constructLookup(String, String, String)} successfully constructs a query part.
348      */
349     @Test
testConstructLookup()350     public void testConstructLookup() throws Exception
351     {
352         // Setup test fixture.
353         final String service = "xmpp-client";
354         final String protocol = "tcp";
355         final String name = "igniterealtime.org";
356 
357         // Execute system under test.
358         final String result = DNSUtil.constructLookup(service, protocol, name);
359 
360         // Verify results.
361         Assert.assertEquals("_xmpp-client._tcp.igniterealtime.org.", result);
362     }
363 }
364