Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 453a5233 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Gerrit Code Review
Browse files

Merge "Minor changes to LinkAddress."

parents 738fa2f6 e1ad1849
Loading
Loading
Loading
Loading
+29 −24
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import java.net.InterfaceAddress;
import java.net.UnknownHostException;

/**
 * Identifies an address of a network link
 * Identifies an IP address on a network link.
 * @hide
 */
public class LinkAddress implements Parcelable {
@@ -35,7 +35,7 @@ public class LinkAddress implements Parcelable {
    private InetAddress address;

    /**
     * Network prefix length
     * Prefix length.
     */
    private int prefixLength;

@@ -50,10 +50,19 @@ public class LinkAddress implements Parcelable {
        this.prefixLength = prefixLength;
    }

    /**
     * Constructs a new {@code LinkAddress} from an {@code InetAddress} and a prefix length.
     * @param address The IP address.
     * @param prefixLength The prefix length.
     */
    public LinkAddress(InetAddress address, int prefixLength) {
        init(address, prefixLength);
    }

    /**
     * Constructs a new {@code LinkAddress} from an {@code InterfaceAddress}.
     * @param interfaceAddress The interface address.
     */
    public LinkAddress(InterfaceAddress interfaceAddress) {
        init(interfaceAddress.getAddress(),
             interfaceAddress.getNetworkPrefixLength());
@@ -86,13 +95,13 @@ public class LinkAddress implements Parcelable {

    @Override
    public String toString() {
        return (address == null ? "" : (address.getHostAddress() + "/" + prefixLength));
        return address.getHostAddress() + "/" + prefixLength;
    }

    /**
     * Compares this {@code LinkAddress} instance against the specified address
     * in {@code obj}. Two addresses are equal if their InetAddress and prefixLength
     * are equal
     * are equal.
     *
     * @param obj the object to be tested for equality.
     * @return {@code true} if both objects are equal, {@code false} otherwise.
@@ -107,30 +116,30 @@ public class LinkAddress implements Parcelable {
            this.prefixLength == linkAddress.prefixLength;
    }

    @Override
    /*
     * generate hashcode based on significant fields
    /**
     * Returns a hashcode for this address.
     */
    @Override
    public int hashCode() {
        return ((null == address) ? 0 : address.hashCode()) + prefixLength;
        return address.hashCode() + 11 * prefixLength;
    }

    /**
     * Returns the InetAddress for this address.
     * Returns the InetAddress of this address.
     */
    public InetAddress getAddress() {
        return address;
    }

    /**
     * Get network prefix length
     * Returns the prefix length of this address.
     */
    public int getNetworkPrefixLength() {
        return prefixLength;
    }

    /**
     * Implement the Parcelable interface
     * Implement the Parcelable interface.
     * @hide
     */
    public int describeContents() {
@@ -142,13 +151,8 @@ public class LinkAddress implements Parcelable {
     * @hide
     */
    public void writeToParcel(Parcel dest, int flags) {
        if (address != null) {
            dest.writeByte((byte)1);
        dest.writeByteArray(address.getAddress());
        dest.writeInt(prefixLength);
        } else {
            dest.writeByte((byte)0);
        }
    }

    /**
@@ -159,13 +163,14 @@ public class LinkAddress implements Parcelable {
        new Creator<LinkAddress>() {
            public LinkAddress createFromParcel(Parcel in) {
                InetAddress address = null;
                int prefixLength = 0;
                if (in.readByte() == 1) {
                try {
                    address = InetAddress.getByAddress(in.createByteArray());
                        prefixLength = in.readInt();
                    } catch (UnknownHostException e) { }
                } catch (UnknownHostException e) {
                    // Nothing we can do here. When we call the constructor, we'll throw an
                    // IllegalArgumentException, because a LinkAddress can't have a null
                    // InetAddress.
                }
                int prefixLength = in.readInt();
                return new LinkAddress(address, prefixLength);
            }

+213 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.net.LinkAddress;
import android.os.Parcel;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

/**
 * Tests for {@link LinkAddress}.
 */
public class LinkAddressTest extends AndroidTestCase {

    private static final String V4 = "192.0.2.1";
    private static final String V6 = "2001:db8::1";
    private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
    private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);

    public void testConstructors() throws SocketException {
        LinkAddress address;

        // Valid addresses work as expected.
        address = new LinkAddress(V4_ADDRESS, 25);
        assertEquals(V4_ADDRESS, address.getAddress());
        assertEquals(25, address.getNetworkPrefixLength());

        address = new LinkAddress(V6_ADDRESS, 127);
        assertEquals(V6_ADDRESS, address.getAddress());
        assertEquals(127, address.getNetworkPrefixLength());

        address = new LinkAddress(V6 + "/64");
        assertEquals(V6_ADDRESS, address.getAddress());
        assertEquals(64, address.getNetworkPrefixLength());

        address = new LinkAddress(V4 + "/23");
        assertEquals(V4_ADDRESS, address.getAddress());
        assertEquals(23, address.getNetworkPrefixLength());

        // InterfaceAddress doesn't have a constructor. Fetch some from an interface.
        List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses();

        // We expect to find 127.0.0.1/8 and ::1/128, in any order.
        LinkAddress ipv4Loopback, ipv6Loopback;
        assertEquals(2, addrs.size());
        if (addrs.get(0).getAddress() instanceof Inet4Address) {
            ipv4Loopback = new LinkAddress(addrs.get(0));
            ipv6Loopback = new LinkAddress(addrs.get(1));
        } else {
            ipv4Loopback = new LinkAddress(addrs.get(1));
            ipv6Loopback = new LinkAddress(addrs.get(0));
        }

        assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
        assertEquals(8, ipv4Loopback.getNetworkPrefixLength());

        assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
        assertEquals(128, ipv6Loopback.getNetworkPrefixLength());

        // Null addresses are rejected.
        try {
            address = new LinkAddress(null, 24);
            fail("Null InetAddress should cause IllegalArgumentException");
        } catch(IllegalArgumentException expected) {}

        try {
            address = new LinkAddress((String) null);
            fail("Null string should cause IllegalArgumentException");
        } catch(IllegalArgumentException expected) {}

        try {
            address = new LinkAddress((InterfaceAddress) null);
            fail("Null string should cause NullPointerException");
        } catch(NullPointerException expected) {}

        // Invalid prefix lengths are rejected.
        try {
            address = new LinkAddress(V4 + "/-1");
            fail("Negative IPv4 prefix length should cause IllegalArgumentException");
        } catch(IllegalArgumentException expected) {}

        try {
            address = new LinkAddress(V6 + "/-1");
            fail("Negative IPv6 prefix length should cause IllegalArgumentException");
        } catch(IllegalArgumentException expected) {}

        try {
            address = new LinkAddress(V4 + "/33");
            fail("/35 IPv4 prefix length should cause IllegalArgumentException");
        } catch(IllegalArgumentException expected) {}

        try {
            address = new LinkAddress(V6 + "/129");
            fail("/129 IPv6 prefix length should cause IllegalArgumentException");
        } catch(IllegalArgumentException expected) {}
    }

    private void assertLinkAddressesEqual(LinkAddress l1, LinkAddress l2) {
        assertTrue(l1 + " unexpectedly not equal to " + l2, l1.equals(l2));
        assertTrue(l2 + " unexpectedly not equal to " + l1, l2.equals(l1));
        assertEquals(l1.hashCode(), l2.hashCode());
    }

    private void assertLinkAddressesNotEqual(LinkAddress l1, LinkAddress l2) {
        assertFalse(l1 + " unexpectedly equal to " + l2, l1.equals(l2));
        assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1));
    }

    public void testEquals() {
        LinkAddress l1, l2;

        l1 = new LinkAddress("2001:db8::1/64");
        l2 = new LinkAddress("2001:db8::1/64");
        assertLinkAddressesEqual(l1, l2);

        l2 = new LinkAddress("2001:db8::1/65");
        assertLinkAddressesNotEqual(l1, l2);
        l2 = new LinkAddress("2001:db8::2/64");
        assertLinkAddressesNotEqual(l1, l2);

        l1 = new LinkAddress("192.0.2.1/24");
        l2 = new LinkAddress("192.0.2.1/24");
        assertLinkAddressesEqual(l1, l2);

        l2 = new LinkAddress("192.0.2.1/23");
        assertLinkAddressesNotEqual(l1, l2);
        l2 = new LinkAddress("192.0.2.2/24");
        assertLinkAddressesNotEqual(l1, l2);

        // Addresses with the same start or end bytes aren't equal between families.
        l1 = new LinkAddress("255.255.255.255/24");
        l2 = new LinkAddress("ffff:ffff::/24");
        assertLinkAddressesNotEqual(l1, l2);
        l2 = new LinkAddress("::ffff:ffff/24");
        assertLinkAddressesNotEqual(l1, l2);

        // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address.
        // TODO: Investigate fixing this.
        String addressString = V4 + "/24";
        l1 = new LinkAddress(addressString);
        l2 = new LinkAddress("::ffff:" + addressString);
        assertLinkAddressesEqual(l1, l2);
    }

    public void testHashCode() {
        LinkAddress l;

        l = new LinkAddress(V4_ADDRESS, 23);
        assertEquals(-982787, l.hashCode());

        l = new LinkAddress(V4_ADDRESS, 27);
        assertEquals(-982743, l.hashCode());

        l = new LinkAddress(V6_ADDRESS, 64);
        assertEquals(1076522926, l.hashCode());

        l = new LinkAddress(V6_ADDRESS, 128);
        assertEquals(1076523630, l.hashCode());
    }

    private LinkAddress passThroughParcel(LinkAddress l) {
        Parcel p = Parcel.obtain();
        LinkAddress l2 = null;
        try {
            l.writeToParcel(p, 0);
            p.setDataPosition(0);
            l2 = LinkAddress.CREATOR.createFromParcel(p);
        } finally {
            p.recycle();
        }
        assertNotNull(l2);
        return l2;
    }

    private void assertParcelingIsLossless(LinkAddress l) {
      LinkAddress l2 = passThroughParcel(l);
      assertEquals(l, l2);
    }

    public void testParceling() {
        LinkAddress l;

        l = new LinkAddress(V6_ADDRESS, 64);
        assertParcelingIsLossless(l);

        l = new LinkAddress(V4 + "/28");
        assertParcelingIsLossless(l);
    }
}