BOOST_FIXTURE_TEST_CASE( updates_created_different_versions, context )
{
    const json::array response = json_multiple_post(
           subscribe_to_node1()
        << asio_mocks::json_msg( "{ 'id': '192.168.210.1:9999/0' }" )
        << boost::bind( defered_update_node, boost::ref( data_ ), node1, json::string( "update1"),
            boost::ref( static_cast< boost::asio::io_service& >( *this ) ) )
        << asio_mocks::json_msg( "{ 'id': '192.168.210.1:9999/0' }" )
        << asio_mocks::disconnect_read() );

    const json::value version1 = response.at( 1u )
        .upcast< json::object >()
        .at( json::string( "update" ) )
        .upcast< json::array >()
        .at( 0 )
        .upcast< json::object >()
        .at( json::string( "version") );

    const json::value version2 = response.at( 2u )
        .upcast< json::object >()
        .at( json::string( "update" ) )
        .upcast< json::array >()
        .at( 0 )
        .upcast< json::object >()
        .at( json::string( "version") );

    BOOST_CHECK_NE( version1, version2 );
}
/**
 * @test the current behaviour is, that a first update to a subscription is delivered with the a second
 *       http request. Delivering the initial version of the data with the first http request would be
 *       fine too.
 */
BOOST_FIXTURE_TEST_CASE( response_to_subscription, context )
{
    answer_validation_request( node1, true );
    answer_authorization_request( node1, true );
    answer_initialization_request( node1, json::number( 42 ) );

    tools::run( *this );
    const json::array response = json_multiple_post(
           asio_mocks::read_plan()
        << asio_mocks::json_msg( "{ 'cmd': [ { 'subscribe': { 'a':'1' ,'b':'1' } } ] }" )
        << asio_mocks::json_msg( "{ 'id': '192.168.210.1:9999/0' }" )
        << asio_mocks::disconnect_read() );

    BOOST_REQUIRE_EQUAL( response.length(), 2u );
    json::array updates = response.at( 1 ).upcast< json::object >().at( json::string( "update" ) ).upcast< json::array >();

    BOOST_REQUIRE_EQUAL( updates.length(), 1u );
    json::object update = updates.at( 0 ).upcast< json::object >();

    BOOST_CHECK_EQUAL(
        update.at( json::string( "key" ) ),
        json::parse_single_quoted( "{ 'a':'1' ,'b':'1' }" ));

    BOOST_CHECK_EQUAL( update.at( json::string( "data" ) ), json::number( 42 ) );
}
BOOST_FIXTURE_TEST_CASE( defered_response_to_subscription_if_validation_was_asynchronous, context )
{
    const json::array responses = json_multiple_post(
           asio_mocks::read_plan()
        << asio_mocks::json_msg( "{ 'cmd': [ { 'subscribe': { 'a':'1' ,'b':'1' } } ] }" )
        << boost::bind( update_node1_to_42, boost::ref( static_cast< pubsub::test::adapter&>( *this ) ), node1 )
        << asio_mocks::json_msg( "{ 'id': '192.168.210.1:9999/0' }" )
        << asio_mocks::disconnect_read() );

    BOOST_REQUIRE_EQUAL( responses.length(), 2u );
    BOOST_CHECK( find_update( responses.at( 1u ).upcast< json::object >(), "{ 'a':'1' ,'b':'1' }", "42" ) );
}
BOOST_FIXTURE_TEST_CASE( defered_error_message_if_not_authorized, context )
{
    const json::array response = json_multiple_post(
           asio_mocks::read_plan()
        << asio_mocks::json_msg( "{ 'cmd': [ { 'subscribe': { 'a':'1' ,'b':'1' } } ] }" )
        << asio_mocks::json_msg( "{ 'id': '192.168.210.1:9999/0' }" )
        << boost::bind( unauthorized_node_subject, boost::ref( static_cast< pubsub::test::adapter&>( *this ) ), node1 )
        << asio_mocks::disconnect_read() );

    BOOST_REQUIRE_EQUAL( response.length(), 2u );
    json::array resp = response.at( 1 ).upcast< json::object >().at( json::string( "resp" ) ).upcast< json::array >();

    BOOST_REQUIRE_EQUAL( resp.length(), 1u );

    BOOST_CHECK_EQUAL(
        resp.at( 0 ),
        json::parse_single_quoted( "{"
            "'error': 'not allowed'"
            "'subscribe' :{ 'a':'1' ,'b':'1' } }" ) );
}
BOOST_FIXTURE_TEST_CASE( error_message_if_subscription_subject_is_invalid, context )
{
    answer_validation_request( node1, false );

    const json::array response = json_multiple_post(
           asio_mocks::read_plan()
        << asio_mocks::json_msg( "{ 'cmd': [ { 'subscribe': { 'a':'1' ,'b':'1' } } ] }" )
        << asio_mocks::json_msg( "{ 'id': '192.168.210.1:9999/0' }" )
        << asio_mocks::disconnect_read() );

    BOOST_REQUIRE_EQUAL( response.length(), 2u );
    json::array resp = response.at( 1 ).upcast< json::object >().at( json::string( "resp" ) ).upcast< json::array >();

    BOOST_REQUIRE_EQUAL( resp.length(), 1u );

    BOOST_CHECK_EQUAL(
        resp.at( 0 ),
        json::parse_single_quoted( "{"
            "'error': 'invalid node'"
            "'subscribe' :{ 'a':'1' ,'b':'1' } }" ) );
}
BOOST_FIXTURE_TEST_CASE( failed_initialization, context )
{
    answer_validation_request( node1, true );
    answer_authorization_request( node1, true );
    skip_initialization_request( node1 );

    const json::array response = json_multiple_post(
           asio_mocks::read_plan()
        << asio_mocks::json_msg( "{ 'cmd': [ { 'subscribe': { 'a':'1' ,'b':'1' } } ] }" )
        << asio_mocks::json_msg( "{ 'id': '192.168.210.1:9999/0' }" )
        << asio_mocks::disconnect_read() );

    BOOST_REQUIRE_EQUAL( response.length(), 2u );
    json::array resp = response.at( 1 ).upcast< json::object >().at( json::string( "resp" ) ).upcast< json::array >();

    BOOST_REQUIRE_EQUAL( resp.length(), 1u );

    BOOST_CHECK_EQUAL(
        resp.at( 0 ),
        json::parse_single_quoted( "{"
            "'error': 'node initialization failed'"
            "'subscribe' :{ 'a':'1' ,'b':'1' } }" ) );
}
BOOST_FIXTURE_TEST_CASE( unsubscribe_from_not_subscribed_node_http, context )
{
    const json::array response = json_multiple_post(
           subscribe_to_node1()
        << asio_mocks::json_msg( "{"
            "   'id': '192.168.210.1:9999/0',  "
            "   'cmd': [ "
            "       { 'unsubscribe': { 'a': '1', 'b': '2' } } "
            "   ]"
            "}" )
        << asio_mocks::disconnect_read() );

    BOOST_REQUIRE_EQUAL( response.length(), 2u );
    BOOST_CHECK_EQUAL(
        response.at( 1u ),
        json::parse_single_quoted(""
            "{"
            "   'id': '192.168.210.1:9999/0',"
            "   'resp': [{"
            "       'unsubscribe': { 'a': '1', 'b': '2' },"
            "       'error': 'not subscribed'"
            "   }]"
            "}" ) );
}