1c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev/*
2c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * Copyright (C) 2018 The Android Open Source Project
3c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev *
4c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * Licensed under the Apache License, Version 2.0 (the "License");
5c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * you may not use this file except in compliance with the License.
6c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * You may obtain a copy of the License at
7c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev *
8c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev *      http://www.apache.org/licenses/LICENSE-2.0
9c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev *
10c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * Unless required by applicable law or agreed to in writing, software
11c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * distributed under the License is distributed on an "AS IS" BASIS,
12c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * See the License for the specific language governing permissions and
14c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * limitations under the License.
15c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev */
16c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
17c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevpackage com.android.server.net;
18c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
19c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport static org.junit.Assert.assertEquals;
20c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport static org.junit.Assert.assertNotNull;
21c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport static org.junit.Assert.fail;
22c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
23c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.net.IpConfiguration;
24c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.net.IpConfiguration.IpAssignment;
25c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.net.IpConfiguration.ProxySettings;
26c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.net.LinkAddress;
27c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.net.NetworkUtils;
28c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.net.ProxyInfo;
29c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.net.StaticIpConfiguration;
30c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.support.test.runner.AndroidJUnit4;
31c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport android.util.ArrayMap;
32c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
33c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport org.junit.Test;
34c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport org.junit.runner.RunWith;
35c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
36c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport java.io.ByteArrayInputStream;
37c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport java.io.ByteArrayOutputStream;
38c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport java.io.DataOutputStream;
39c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport java.io.IOException;
40c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevimport java.io.InputStream;
41c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
42c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev/**
43c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev * Unit tests for {@link IpConfigStore}
44c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev */
45c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev@RunWith(AndroidJUnit4.class)
46c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsevpublic class IpConfigStoreTest {
47c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
48c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    @Test
49c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    public void backwardCompatibility2to3() throws IOException {
50c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final int KEY_CONFIG = 17;
51c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
52c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        DataOutputStream outputStream = new DataOutputStream(byteStream);
53c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
54c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        IpConfiguration expectedConfig = new IpConfiguration(IpAssignment.DHCP,
55c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                ProxySettings.NONE, null, null);
56c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
57c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        // Emulate writing to old format.
58c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        writeDhcpConfigV2(outputStream, KEY_CONFIG, expectedConfig);
59c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
60c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        InputStream in = new ByteArrayInputStream(byteStream.toByteArray());
61c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        ArrayMap<String, IpConfiguration> configurations = IpConfigStore.readIpConfigurations(in);
62c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
63c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertNotNull(configurations);
64c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertEquals(1, configurations.size());
65c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        IpConfiguration actualConfig = configurations.get(String.valueOf(KEY_CONFIG));
66c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertNotNull(actualConfig);
67c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertEquals(expectedConfig, actualConfig);
68c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    }
69c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
70c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    @Test
71c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    public void staticIpMultiNetworks() throws Exception {
72c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final String IFACE_1 = "eth0";
73c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final String IFACE_2 = "eth1";
74c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final String IP_ADDR_1 = "192.168.1.10/24";
75c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final String IP_ADDR_2 = "192.168.1.20/24";
76c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final String DNS_IP_ADDR_1 = "1.2.3.4";
77c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final String DNS_IP_ADDR_2 = "5.6.7.8";
78c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
79c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
80c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1);
81c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1));
82c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2));
83c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
84c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2");
85c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
86c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        IpConfiguration expectedConfig1 = new IpConfiguration(IpAssignment.STATIC,
87c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                ProxySettings.STATIC, staticIpConfiguration, proxyInfo);
88c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        IpConfiguration expectedConfig2 = new IpConfiguration(expectedConfig1);
89c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        expectedConfig2.getStaticIpConfiguration().ipAddress = new LinkAddress(IP_ADDR_2);
90c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
91c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        ArrayMap<String, IpConfiguration> expectedNetworks = new ArrayMap<>();
92c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        expectedNetworks.put(IFACE_1, expectedConfig1);
93c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        expectedNetworks.put(IFACE_2, expectedConfig2);
94c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
95c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        MockedDelayedDiskWrite writer = new MockedDelayedDiskWrite();
96c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        IpConfigStore store = new IpConfigStore(writer);
97c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        store.writeIpConfigurations("file/path/not/used/", expectedNetworks);
98c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
99c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        InputStream in = new ByteArrayInputStream(writer.byteStream.toByteArray());
100c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        ArrayMap<String, IpConfiguration> actualNetworks = IpConfigStore.readIpConfigurations(in);
101c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertNotNull(actualNetworks);
102c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertEquals(2, actualNetworks.size());
103c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertEquals(expectedNetworks.get(IFACE_1), actualNetworks.get(IFACE_1));
104c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        assertEquals(expectedNetworks.get(IFACE_2), actualNetworks.get(IFACE_2));
105c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    }
106c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
107c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    // This is simplified snapshot of code that was used to store values in V2 format (key as int).
108c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    private static void writeDhcpConfigV2(DataOutputStream out, int configKey,
109c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev            IpConfiguration config) throws IOException {
110c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        out.writeInt(2);  // VERSION 2
111c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        switch (config.ipAssignment) {
112c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev            case DHCP:
113c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                out.writeUTF("ipAssignment");
114c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                out.writeUTF(config.ipAssignment.toString());
115c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                break;
116c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev            default:
117c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                fail("Not supported in test environment");
118c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        }
119c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
120c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        out.writeUTF("id");
121c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        out.writeInt(configKey);
122c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        out.writeUTF("eos");
123c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    }
124c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
125c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    /** Synchronously writes into given byte steam */
126c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    private static class MockedDelayedDiskWrite extends DelayedDiskWrite {
127c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
128c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
129c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        @Override
130c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        public void write(String filePath, Writer w) {
131c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev            DataOutputStream outputStream = new DataOutputStream(byteStream);
132c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev
133c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev            try {
134c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                w.onWriteCalled(outputStream);
135c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev            } catch (IOException e) {
136c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev                fail();
137c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev            }
138c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev        }
139c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev    }
140c07a96d1e4a90c1c42040fd24ad9e4f209becce4Pavel Maltsev}
141