/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
 */

#include "unit_test.h"
#include "test_tools.h"
#include "BrokerFixture.h"
#include "qpid/client/SubscriptionManager.h"
#include "qpid/client/MessageListener.h"
#include "qpid/sys/Runnable.h"
#include "qpid/sys/Thread.h"
#include "qpid/framing/reply_exceptions.h"

namespace qpid {
namespace tests {

QPID_AUTO_TEST_SUITE(exception_test)

// FIXME aconway 2008-06-12: need to update our exception handling to
// 0-10 handling and extend this test to provoke all the exceptional
// conditions we know of and verify the correct exception is thrown.

using namespace std;
using namespace qpid;
using namespace sys;
using namespace client;
using namespace framing;

using qpid::broker::Broker;
using boost::bind;
using boost::function;

template <class Ex>
struct Catcher : public Runnable {
    function<void ()> f;
    bool caught;
    Thread thread;

    Catcher(function<void ()> f_) : f(f_), caught(false), thread(this) {}
    ~Catcher() { join(); }

    void run() {
        try {
            ScopedSuppressLogging sl; // Suppress messages for expected errors.
            f();
        }
        catch(const Ex& e) {
            caught=true;
            BOOST_TEST_MESSAGE(string("Caught expected exception: ")+e.what()+"["+typeid(e).name()+"]");
        }
        catch(const std::exception& e) {
            BOOST_ERROR(string("Bad exception: ")+e.what()+"["+typeid(e).name()+"] expected: "+typeid(Ex).name());
        }
        catch(...) {
            BOOST_ERROR(string("Bad exception: unknown"));
        }
    }

    bool join() {
        if (thread) {
            thread.join();
            thread=Thread();
        }
        return caught;
    }
};

QPID_AUTO_TEST_CASE(TestSessionBusy) {
    SessionFixture f;
    try {
        ScopedSuppressLogging sl; // Suppress messages for expected errors.
        f.connection.newSession(f.session.getId().getName());
        BOOST_FAIL("Expected SessionBusyException for " << f.session.getId().getName());
    } catch (const SessionBusyException&) {} // FIXME aconway 2008-09-22: client is not throwing correct exception.
}

QPID_AUTO_TEST_CASE(DisconnectedPop) {
    SessionFixture fix;
    fix.session.queueDeclare(arg::queue="q");
    fix.subs.subscribe(fix.lq, "q");
    Catcher<TransportFailure> pop(bind(&LocalQueue::pop, &fix.lq, sys::TIME_SEC));
    fix.shutdownBroker();
    BOOST_CHECK(pop.join());
}

QPID_AUTO_TEST_CASE(DisconnectedListen) {
    SessionFixture fix;
    struct NullListener : public MessageListener {
        void received(Message&) { BOOST_FAIL("Unexpected message"); }
    } l;
    fix.session.queueDeclare(arg::queue="q");
    fix.subs.subscribe(l, "q");

    Catcher<TransportFailure> runner(bind(&SubscriptionManager::run, boost::ref(fix.subs)));
    fix.shutdownBroker();
    runner.join();
    BOOST_CHECK_THROW(fix.session.queueDeclare(arg::queue="x"), TransportFailure);
}

QPID_AUTO_TEST_CASE(NoSuchQueueTest) {
    SessionFixture fix;
    ScopedSuppressLogging sl; // Suppress messages for expected errors.
    BOOST_CHECK_THROW(fix.subs.subscribe(fix.lq, "no such queue"), NotFoundException);
}

QPID_AUTO_TEST_SUITE_END()

}} // namespace qpid::tests
