Package org.apache.qpid.test.framework.distributedtesting

Source Code of org.apache.qpid.test.framework.distributedtesting.InteropTestDecorator

/*
*
* 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.
*
*/
package org.apache.qpid.test.framework.distributedtesting;

import junit.framework.Test;
import junit.framework.TestResult;

import org.apache.log4j.Logger;

import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.sequencers.CircuitFactory;
import org.apache.qpid.test.framework.sequencers.InteropCircuitFactory;
import org.apache.qpid.test.utils.ConversationFactory;

import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;

import javax.jms.Connection;

import java.util.*;

/**
* DistributedTestDecorator is a test decorator, written to implement the interop test specification. Given a list
* of enlisted test clients, that are available to run interop tests, this decorator invites them to participate
* in each test in the wrapped test suite. Amongst all the clients that respond to the invite, all pairs are formed,
* and each pairing (in both directions, but excluding the reflexive pairings) is split into a sender and receivers
* role and a test case run between them. Any enlisted combinations that do not accept a test invite are automatically
* failed.
*
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Broadcast test invitations and collect enlists. <td> {@link org.apache.qpid.test.utils.ConversationFactory}.
* <tr><td> Output test failures for clients unwilling to run the test case. <td> {@link Coordinator}
* <tr><td> Execute distributed test cases. <td> {@link FrameworkBaseCase}
* <tr><td> Fail non-participating pairings. <td> {@link OptOutTestCase}
* </table>
*/
public class InteropTestDecorator extends DistributedTestDecorator
{
    /** Used for debugging. */
    private static final Logger log = Logger.getLogger(InteropTestDecorator.class);

    /**
     * Creates a wrapped suite test decorator from another one.
     *
     * @param suite               The test suite.
     * @param availableClients    The list of all clients that responded to the compulsory invite.
     * @param controlConversation The conversation helper for the control level, test coordination conversation.
     * @param controlConnection   The connection that the coordination messages are sent over.
     */
    public InteropTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
        ConversationFactory controlConversation, Connection controlConnection)
    {
        super(suite, availableClients, controlConversation, controlConnection);
    }

    /**
     * Broadcasts a test invitation and accetps enlisting from participating clients. The wrapped test case is
     * then repeated for every combination of test clients (provided the wrapped test case extends
     * {@link FrameworkBaseCase}.
     *
     * <p/>Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime exceptions,
     * resulting in the non-completion of the test run.
     *
     * @todo Better error recovery for failure of the invite/enlist conversation could be added.
     *
     * @param testResult The the results object to monitor the test results with.
     */
    public void run(TestResult testResult)
    {
        log.debug("public void run(TestResult testResult): called");

        Collection<Test> tests = testSuite.getAllUnderlyingTests();

        for (Test test : getAllUnderlyingTests())
        {
            FrameworkBaseCase coordTest = (FrameworkBaseCase) test;

            // Broadcast the invitation to find out what clients are available to test.
            Set<TestClientDetails> enlists = signupClients(coordTest);

            // Compare the list of willing clients to the list of all available.
            Set<TestClientDetails> optOuts = new HashSet<TestClientDetails>(allClients);
            optOuts.removeAll(enlists);

            // Output test failures for clients that will not particpate in the test.
            Set<List<TestClientDetails>> failPairs = allPairs(optOuts, allClients);

            for (List<TestClientDetails> failPair : failPairs)
            {
                // Create a distributed test circuit factory for the test.
                CircuitFactory circuitFactory = getTestSequencer();

                // Create an automatic failure test for the opted out test pair.
                FrameworkBaseCase failTest = new OptOutTestCase("testOptOut");
                circuitFactory.setSender(failPair.get(0));
                circuitFactory.setReceiver(failPair.get(1));
                failTest.setCircuitFactory(circuitFactory);

                failTest.run(testResult);
            }

            // Loop over all combinations of clients, willing to run the test.
            Set<List<TestClientDetails>> enlistedPairs = allPairs(enlists, enlists);

            for (List<TestClientDetails> enlistedPair : enlistedPairs)
            {
                // Create a distributed test circuit factory for the test.
                CircuitFactory circuitFactory = getTestSequencer();

                // Set the sending and receiving client details on the test circuitFactory.
                circuitFactory.setSender(enlistedPair.get(0));
                circuitFactory.setReceiver(enlistedPair.get(1));

                // Pass down the connection to hold the coordination conversation over.
                circuitFactory.setConversationFactory(conversationFactory);

                // Execute the test case.
                coordTest.setCircuitFactory(circuitFactory);
                coordTest.run(testResult);
            }
        }
    }

    /**
     * Should provide the distributed test sequencer to pass to {@link org.apache.qpid.test.framework.FrameworkBaseCase}
     * tests.
     *
     * @return A distributed test sequencer.
     */
    public CircuitFactory getTestSequencer()
    {
        return new InteropCircuitFactory();
    }

    /**
     * Produces all pairs of combinations of elements from two sets. The ordering of the elements in the pair is
     * important, that is the pair <l, r> is distinct from <r, l>; both pairs are generated. For any element, i, in
     * both the left and right sets, the reflexive pair <i, i> is not generated.
     *
     * @param left  The left set.
     * @param right The right set.
     * @param <E>   The type of the content of the pairs.
     *
     * @return All pairs formed from the permutations of all elements of the left and right sets.
     */
    private <E> Set<List<E>> allPairs(Set<E> left, Set<E> right)
    {
        log.debug("private <E> Set<List<E>> allPairs(Set<E> left = " + left + ", Set<E> right = " + right + "): called");

        Set<List<E>> results = new HashSet<List<E>>();

        // Form all pairs from left to right.
        // Form all pairs from right to left.
        for (E le : left)
        {
            for (E re : right)
            {
                if (!le.equals(re))
                {
                    results.add(new Pair<E>(le, re));
                    results.add(new Pair<E>(re, le));
                }
            }
        }

        log.debug("results = " + results);

        return results;
    }

    /**
     * A simple implementation of a pair, using a list.
     */
    private class Pair<T> extends ArrayList<T>
    {
        /**
         * Creates a new pair of elements.
         *
         * @param first  The first element.
         * @param second The second element.
         */
        public Pair(T first, T second)
        {
            super();
            super.add(first);
            super.add(second);
        }
    }
}
TOP

Related Classes of org.apache.qpid.test.framework.distributedtesting.InteropTestDecorator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.