<?php
/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
class CallTest extends PHPUnit_Framework_TestCase
{
    public static $server;
    public static $port;

    public static function setUpBeforeClass()
    {
        self::$server = new Grpc\Server([]);
        self::$port = self::$server->addHttp2Port('0.0.0.0:0');
    }

    public function setUp()
    {
        $this->channel = new Grpc\Channel('localhost:'.self::$port, []);
        $this->call = new Grpc\Call($this->channel,
                                    '/foo',
                                    Grpc\Timeval::infFuture());
    }

    public function tearDown()
    {
        unset($this->call);
        unset($this->channel);
    }

    public function testConstructor()
    {
        $this->assertSame('Grpc\Call', get_class($this->call));
        $this->assertObjectHasAttribute('channel', $this->call);
    }

    public function testAddEmptyMetadata()
    {
        $batch = [
            Grpc\OP_SEND_INITIAL_METADATA => [],
        ];
        $result = $this->call->startBatch($batch);
        $this->assertTrue($result->send_metadata);
    }

    public function testAddSingleMetadata()
    {
        $batch = [
            Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value']],
        ];
        $result = $this->call->startBatch($batch);
        $this->assertTrue($result->send_metadata);
    }

    public function testAddMultiValueMetadata()
    {
        $batch = [
            Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value1', 'value2']],
        ];
        $result = $this->call->startBatch($batch);
        $this->assertTrue($result->send_metadata);
    }

    public function testAddSingleAndMultiValueMetadata()
    {
        $batch = [
            Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'],
                                              'key2' => ['value2',
                                                         'value3'], ],
        ];
        $result = $this->call->startBatch($batch);
        $this->assertTrue($result->send_metadata);
    }

    public function testGetPeer()
    {
        $this->assertTrue(is_string($this->call->getPeer()));
    }

    public function testCancel()
    {
        $this->assertNull($this->call->cancel());
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidStartBatchKey()
    {
        $batch = [
            'invalid' => ['key1' => 'value1'],
        ];
        $result = $this->call->startBatch($batch);
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidMetadataStrKey()
    {
        $batch = [
            Grpc\OP_SEND_INITIAL_METADATA => ['Key' => ['value1', 'value2']],
        ];
        $result = $this->call->startBatch($batch);
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidMetadataIntKey()
    {
        $batch = [
            Grpc\OP_SEND_INITIAL_METADATA => [1 => ['value1', 'value2']],
        ];
        $result = $this->call->startBatch($batch);
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidMetadataInnerValue()
    {
        $batch = [
            Grpc\OP_SEND_INITIAL_METADATA => ['key1' => 'value1'],
        ];
        $result = $this->call->startBatch($batch);
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidConstuctor()
    {
        $this->call = new Grpc\Call();
        $this->assertNull($this->call);
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidConstuctor2()
    {
        $this->call = new Grpc\Call('hi', 'hi', 'hi');
        $this->assertNull($this->call);
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidSetCredentials()
    {
        $this->call->setCredentials('hi');
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testInvalidSetCredentials2()
    {
        $this->call->setCredentials([]);
    }
}
