<?php
// IPAddressTest.php
// Created: 2021-04-26
// Updated: 2022-02-03

declare(strict_types=1);

use PHPUnit\Framework\TestCase;
use Index\Net\IPAddress;

/**
 * @covers IPAddress
 */
final class IPAddressTest extends TestCase {
    public function testParsing(): void {
        $v4 = IPAddress::parse('127.0.0.1');
        $this->assertEquals('127.0.0.1', $v4->getAddress());
        $v6 = IPAddress::parse('::1');
        $this->assertEquals('[::1]', $v6->getAddress());

        $this->expectException(InvalidArgumentException::class);
        $v0 = IPAddress::parse('12.4:424');
    }

    public function testVersion(): void {
        $v4 = IPAddress::parse('123.53.65.34');
        $this->assertEquals(4, $v4->getVersion());
        $this->assertEquals(4, $v4->getWidth());
        $this->assertTrue($v4->isV4());
        $this->assertFalse($v4->isV6());

        $v6 = IPAddress::parse('23cd::43c4:2342:acde');
        $this->assertEquals(6, $v6->getVersion());
        $this->assertEquals(16, $v6->getWidth());
        $this->assertTrue($v6->isV6());
        $this->assertFalse($v6->isV4());
    }

    public function testToString(): void {
        $v4 = IPAddress::parse('53.64.123.86');
        $this->assertEquals('53.64.123.86', (string)$v4);

        $v6 = IPAddress::parse('abcd:1234::43:211a');
        $this->assertEquals('abcd:1234::43:211a', (string)$v6);
    }

    public function testEquals(): void {
        $v41 = IPAddress::parse('53.64.123.86');
        $v42 = IPAddress::parse('123.53.65.34');
        $v61 = IPAddress::parse('abcd:1234::43:211a');
        $v62 = IPAddress::parse('23cd::43c4:2342:acde');

        $this->assertTrue($v41->equals($v41));
        $this->assertFalse($v42->equals($v41));
        $this->assertFalse($v61->equals($v42));
        $this->assertTrue($v62->equals($v62));
    }

    public function testJsonSerialize(): void {
        $addrs = [
            '53.64.123.86',
            '123.53.65.34',
            'abcd:1234::43:211a',
            '23cd::43c4:2342:acde',
        ];

        foreach($addrs as $addr)
            $this->assertEquals(json_encode($addr), json_encode(IPAddress::parse($addr)));
    }

    public function testSerializable(): void {
        $addrs = [
            '53.64.123.86',
            '123.53.65.34',
            'abcd:1234::43:211a',
            '23cd::43c4:2342:acde',
        ];

        foreach($addrs as $addr) {
            $obj = IPAddress::parse($addr);
            $ser = serialize($obj);
            $unser = unserialize($ser);
            $this->assertTrue($obj->equals($unser));
        }
    }
}