1b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lanepackage android.core;
2b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
3b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport android.test.AndroidTestCase;
4b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
5b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport android.os.Bundle;
6b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport android.os.Parcel;
7b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport android.os.StrictMode;
8b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport android.net.nsd.NsdServiceInfo;
9b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport android.util.Log;
10b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
11b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.util.Arrays;
12b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.util.HashMap;
13b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.util.Map;
14b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.net.InetAddress;
15b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.net.UnknownHostException;
16b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
17b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
18b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lanepublic class NsdServiceInfoTest extends AndroidTestCase {
19b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
20b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    public final static InetAddress LOCALHOST;
21b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    static {
22b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Because test.
23b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
24b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        StrictMode.setThreadPolicy(policy);
25b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
26b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        InetAddress _host = null;
27b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        try {
28b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            _host = InetAddress.getLocalHost();
29b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        } catch (UnknownHostException e) { }
30b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        LOCALHOST = _host;
31b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    }
32b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
33b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    public void testLimits() throws Exception {
34b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        NsdServiceInfo info = new NsdServiceInfo();
35b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
36b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Non-ASCII keys.
37b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        boolean exceptionThrown = false;
38b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        try {
39b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            info.setAttribute("猫", "meow");
40b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        } catch (IllegalArgumentException e) {
41b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            exceptionThrown = true;
42b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        }
43b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(exceptionThrown);
44b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertEmptyServiceInfo(info);
45b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
46b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // ASCII keys with '=' character.
47b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        exceptionThrown = false;
48b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        try {
49b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            info.setAttribute("kitten=", "meow");
50b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        } catch (IllegalArgumentException e) {
51b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            exceptionThrown = true;
52b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        }
53b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(exceptionThrown);
54b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertEmptyServiceInfo(info);
55b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
56b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Single key + value length too long.
57b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        exceptionThrown = false;
58b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        try {
59b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            String longValue = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
60b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane                    "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
61b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane                    "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
62b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane                    "ooooooooooooooooooooooooooooong";  // 248 characters.
63b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            info.setAttribute("longcat", longValue);  // Key + value == 255 characters.
64b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        } catch (IllegalArgumentException e) {
65b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            exceptionThrown = true;
66b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        }
67b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(exceptionThrown);
68b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertEmptyServiceInfo(info);
69b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
70b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Total TXT record length too long.
71b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        exceptionThrown = false;
72b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        int recordsAdded = 0;
73b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        try {
74b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            for (int i = 100; i < 300; ++i) {
75b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane                // 6 char key + 5 char value + 2 bytes overhead = 13 byte record length.
76b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane                String key = String.format("key%d", i);
77b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane                info.setAttribute(key, "12345");
78b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane                recordsAdded++;
79b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            }
80b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        } catch (IllegalArgumentException e) {
81b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            exceptionThrown = true;
82b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        }
83b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(exceptionThrown);
84b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(100 == recordsAdded);
85b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(info.getTxtRecord().length == 1300);
86b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    }
87b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
88b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    public void testParcel() throws Exception {
89b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        NsdServiceInfo emptyInfo = new NsdServiceInfo();
90b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        checkParcelable(emptyInfo);
91b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
92b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        NsdServiceInfo fullInfo = new NsdServiceInfo();
93b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        fullInfo.setServiceName("kitten");
94b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        fullInfo.setServiceType("_kitten._tcp");
95b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        fullInfo.setPort(4242);
96b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        fullInfo.setHost(LOCALHOST);
97b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        checkParcelable(fullInfo);
98b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
99b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        NsdServiceInfo noHostInfo = new NsdServiceInfo();
100b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        noHostInfo.setServiceName("kitten");
101b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        noHostInfo.setServiceType("_kitten._tcp");
102b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        noHostInfo.setPort(4242);
103b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        checkParcelable(noHostInfo);
104b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
105b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        NsdServiceInfo attributedInfo = new NsdServiceInfo();
106b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setServiceName("kitten");
107b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setServiceType("_kitten._tcp");
108b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setPort(4242);
109b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setHost(LOCALHOST);
110b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setAttribute("color", "pink");
111b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setAttribute("sound", (new String("にゃあ")).getBytes("UTF-8"));
112b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setAttribute("adorable", (String) null);
113b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setAttribute("sticky", "yes");
114b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setAttribute("siblings", new byte[] {});
115b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.setAttribute("edge cases", new byte[] {0, -1, 127, -128});
116b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        attributedInfo.removeAttribute("sticky");
117b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        checkParcelable(attributedInfo);
118b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
119b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Sanity check that we actually wrote attributes to attributedInfo.
120b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(attributedInfo.getAttributes().keySet().contains("adorable"));
121b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        String sound = new String(attributedInfo.getAttributes().get("sound"), "UTF-8");
122b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(sound.equals("にゃあ"));
123b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        byte[] edgeCases = attributedInfo.getAttributes().get("edge cases");
124b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(Arrays.equals(edgeCases, new byte[] {0, -1, 127, -128}));
125b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertFalse(attributedInfo.getAttributes().keySet().contains("sticky"));
126b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    }
127b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
128b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    public void checkParcelable(NsdServiceInfo original) {
129b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Write to parcel.
130b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        Parcel p = Parcel.obtain();
131b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        Bundle writer = new Bundle();
132b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        writer.putParcelable("test_info", original);
133b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        writer.writeToParcel(p, 0);
134b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
135b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Extract from parcel.
136b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        p.setDataPosition(0);
137b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        Bundle reader = p.readBundle();
138b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        reader.setClassLoader(NsdServiceInfo.class.getClassLoader());
139b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        NsdServiceInfo result = reader.getParcelable("test_info");
140b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
141b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Assert equality of base fields.
142b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertEquality(original.getServiceName(), result.getServiceName());
143b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertEquality(original.getServiceType(), result.getServiceType());
144b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertEquality(original.getHost(), result.getHost());
145b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(original.getPort() == result.getPort());
146b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
147b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        // Assert equality of attribute map.
148b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        Map<String, byte[]> originalMap = original.getAttributes();
149b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        Map<String, byte[]> resultMap = result.getAttributes();
150b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertEquality(originalMap.keySet(), resultMap.keySet());
151b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        for (String key : originalMap.keySet()) {
152b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane            assertTrue(Arrays.equals(originalMap.get(key), resultMap.get(key)));
153b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        }
154b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    }
155b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
156b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    public void assertEquality(Object expected, Object result) {
157b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(expected == result || expected.equals(result));
158b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    }
159b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane
160b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    public void assertEmptyServiceInfo(NsdServiceInfo shouldBeEmpty) {
161b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane        assertTrue(null == shouldBeEmpty.getTxtRecord());
162b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane    }
163b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane}
164