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