/*
 * Copyright 2011 Google Inc.
 * Copyright 2014 Andreas Schildbach
 *
 * 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 org.bitcoinj.core;

import static org.bitcoinj.core.Utils.HEX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.math.BigInteger;
import java.net.InetAddress;

import org.bitcoinj.params.MainNetParams;
import org.junit.Test;

public class PeerAddressTest {
    private static final NetworkParameters MAINNET = MainNetParams.get();

    @Test
    public void testPeerAddressRoundtrip() throws Exception {
        // copied verbatim from https://en.bitcoin.it/wiki/Protocol_specification#Network_address
        String fromSpec = "010000000000000000000000000000000000ffff0a000001208d";
        PeerAddress pa = new PeerAddress(MAINNET, HEX.decode(fromSpec), 0, 0);
        String reserialized = Utils.HEX.encode(pa.unsafeBitcoinSerialize());
        assertEquals(reserialized, fromSpec);
    }

    @Test
    public void roundtrip_ipv4_currentProtocolVersion() throws Exception {
        long time = Utils.currentTimeSeconds();
        PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("1.2.3.4"), 1234,
                NetworkParameters.ProtocolVersion.CURRENT.getBitcoinProtocolVersion(), BigInteger.ZERO);
        byte[] serialized = pa.bitcoinSerialize();
        PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0,
                NetworkParameters.ProtocolVersion.CURRENT.getBitcoinProtocolVersion());
        assertEquals("1.2.3.4", pa2.getAddr().getHostAddress());
        assertEquals(1234, pa2.getPort());
        assertEquals(BigInteger.ZERO, pa2.getServices());
        assertTrue(pa2.getTime() >= time && pa2.getTime() < time + 5); // potentially racy
    }

    @Test
    public void roundtrip_ipv4_ancientProtocolVersion() throws Exception {
        PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("1.2.3.4"), 1234, 0, BigInteger.ZERO);
        byte[] serialized = pa.bitcoinSerialize();
        PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, 0);
        assertEquals("1.2.3.4", pa2.getAddr().getHostAddress());
        assertEquals(1234, pa2.getPort());
        assertEquals(BigInteger.ZERO, pa2.getServices());
        assertEquals(-1, pa2.getTime());
    }

    @Test
    public void roundtrip_ipv6_currentProtocolVersion() throws Exception {
        long time = Utils.currentTimeSeconds();
        PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7334"), 1234,
                NetworkParameters.ProtocolVersion.CURRENT.getBitcoinProtocolVersion(), BigInteger.ZERO);
        byte[] serialized = pa.bitcoinSerialize();
        PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0,
                NetworkParameters.ProtocolVersion.CURRENT.getBitcoinProtocolVersion());
        assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", pa2.getAddr().getHostAddress());
        assertEquals(1234, pa2.getPort());
        assertEquals(BigInteger.ZERO, pa2.getServices());
        assertTrue(pa2.getTime() >= time && pa2.getTime() < time + 5); // potentially racy
    }

    @Test
    public void roundtrip_ipv6_ancientProtocolVersion() throws Exception {
        PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7334"), 1234, 0,
                BigInteger.ZERO);
        byte[] serialized = pa.bitcoinSerialize();
        PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, 0);
        assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", pa2.getAddr().getHostAddress());
        assertEquals(1234, pa2.getPort());
        assertEquals(BigInteger.ZERO, pa2.getServices());
        assertEquals(-1, pa2.getTime());
    }

    @Test
    public void testBitcoinSerialize() throws Exception {
        PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName(null), 8333, 0, BigInteger.ZERO);
        assertEquals("000000000000000000000000000000000000ffff7f000001208d", Utils.HEX.encode(pa.bitcoinSerialize()));
    }
}

@@ -1015,16 +1015,20 @@
 .get();%0A
+    
 %0A    @Te
@@ -1050,32 +1050,36 @@
 oid 
-testPeerAddressRoundtrip
+parse_ancientProtocolVersion
 () t
@@ -1118,17 +1118,8 @@
 ied 
-verbatim 
 from
@@ -1155,24 +1155,24 @@
 rotocol_
-specific
+document
 ation#Ne
@@ -1200,24 +1200,19 @@
  String 
-fromSpec
+hex
  = %220100
@@ -1323,24 +1323,19 @@
 .decode(
-fromSpec
+hex
 ), 0, 0)
@@ -1348,120 +1348,586 @@
     
-String reserialized = Utils.HEX.encode(pa.unsafeBitcoinSerialize());%0A        assertEquals(reserialized, fromSpec
+assertEquals(26, pa.length);%0A        assertEquals(VersionMessage.NODE_NETWORK, pa.getServices().longValue());%0A        assertEquals(%2210.0.0.1%22, pa.getAddr().getHostAddress());%0A        assertEquals(8333, pa.getPort());%0A    %7D%0A%0A    @Test%0A    public void bitcoinSerialize_ancientProtocolVersion() throws Exception %7B%0A        PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName(null), 8333, 0, BigInteger.ZERO);%0A        assertEquals(26, pa.length);        %0A        assertEquals(%22000000000000000000000000000000000000ffff7f000001208d%22, Utils.HEX.encode(pa.bitcoinSerialize())
 );%0A 
@@ -4702,307 +4702,7 @@
    %7D
-%0A%0A    @Test%0A    public void testBitcoinSerialize() throws Exception %7B%0A        PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName(null), 8333, 0, BigInteger.ZERO);%0A        assertEquals(%22000000000000000000000000000000000000ffff7f000001208d%22, Utils.HEX.encode(pa.bitcoinSerialize()));%0A    %7D
 %0A%7D%0A

Tidy up parse and bitcoinSerialize tests.