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