Package com.flaptor.hounder.indexer

Source Code of com.flaptor.hounder.indexer.TrafficLimitingSearcherTest$AlwaysFailSearcher

/*
Copyright 2008 Flaptor (flaptor.com)

Licensed 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 com.flaptor.hounder.indexer;

import java.util.Random;

import com.flaptor.hounder.searcher.GroupedSearchResults;
import com.flaptor.hounder.searcher.ISearcher;
import com.flaptor.hounder.searcher.SearcherException;
import com.flaptor.hounder.searcher.TrafficLimitingSearcher;
import com.flaptor.hounder.searcher.filter.AFilter;
import com.flaptor.hounder.searcher.group.AGroup;
import com.flaptor.hounder.searcher.query.AQuery;
import com.flaptor.hounder.searcher.sort.ASort;
import com.flaptor.util.TestCase;
import com.flaptor.util.TestInfo;
import com.flaptor.util.ThreadUtil;

/**
* @author Flaptor Development Team
*/
public class TrafficLimitingSearcherTest extends TestCase {

    private static class WaitingSearcher implements ISearcher {
        public boolean random;
        private int waitingTime;
        public int queriesInProgress = 0;
        private volatile boolean isRunning = true;

        public WaitingSearcher() {
            this(1000, false);
        }

        public WaitingSearcher(int waitingTime,boolean random){
            this.waitingTime=  waitingTime;
            this.random= random;
        }

        @Override
        public void requestStop() {
            isRunning = false;
        }

        @Override
        public boolean isStopped() {
            return !isRunning;
        }

        public GroupedSearchResults search(AQuery query, int firstResult, int count, AGroup group, int groupSize, AFilter filter, ASort sort) {
            synchronized(this) {queriesInProgress++;}
            ThreadUtil.sleep(random ? new Random().nextInt(waitingTime) : waitingTime);
            synchronized(this) {queriesInProgress--;return new GroupedSearchResults();}
        }
    }

    private static class AlwaysFailSearcher implements ISearcher {
        private volatile boolean isRunning = true;
        public AlwaysFailSearcher(){
        };


        @Override
        public void requestStop() {
            isRunning = false;
        }

        @Override
        public boolean isStopped() {
            return !isRunning;
        }

        public GroupedSearchResults search(AQuery query, int firstResult, int count, AGroup group, int groupSize, AFilter filter, ASort sort) throws SearcherException {
            throw new SearcherException("I always fail");
        }
    }

    private int queriesDone = 0;

    @TestInfo(testType = TestInfo.TestType.UNIT)
    public void testMultithreadedFixed() throws InterruptedException {
        multithreaded(false);
    }

    @TestInfo(testType = TestInfo.TestType.UNIT)
    public void testMultithreadedRandom() throws InterruptedException {
        multithreaded(true);
    }

    static int lateDropQueries=0;
    @TestInfo(testType = TestInfo.TestType.UNIT)
    public void testLateDrop() throws InterruptedException {
        WaitingSearcher baseSearcher = new WaitingSearcher(300, false);
        final TrafficLimitingSearcher searcher = new TrafficLimitingSearcher(baseSearcher, 1, 100);
        final int NUM_THREADS=5;
        lateDropQueries=0;
        for (int i =0; i < NUM_THREADS; ++i) {
            try {Thread.sleep(10);} catch (InterruptedException e) {}
            new Thread() {
                public void run() {
//                  long t0 = System.currentTimeMillis();
                    try {
                        searcher.search(null, 0, 1, null, 1, null, null);
                    } catch (Throwable t) {
                        t.printStackTrace();
                        assertTrue(t.getMessage().contains("lateDrop"));
                        lateDropQueries++;
                    } finally {
                        queriesDone++;
                    }
                }
            }.start();
        }
        while (queriesDone < NUM_THREADS) {
            assertTrue(baseSearcher.queriesInProgress <= searcher.getMaxSimultaneousQueries());
            if (baseSearcher.queriesInProgress > searcher.getMaxSimultaneousQueries()){
                fail(baseSearcher.queriesInProgress + " queries, should be <=" + searcher.getMaxSimultaneousQueries());
            }
            Thread.sleep(50);
        }
        assertEquals(NUM_THREADS -1 , lateDropQueries);
    }


    private void multithreaded(boolean random) throws InterruptedException {
        int NUM_THREADS = 1000;
        WaitingSearcher baseSearcher = new WaitingSearcher();
        final TrafficLimitingSearcher searcher = new TrafficLimitingSearcher(baseSearcher, 10, 1000);
        baseSearcher.random = random;
        for (int i =0; i < NUM_THREADS; ++i) {
            try {Thread.sleep(10);} catch (InterruptedException e) {}
            new Thread() {
                public void run() {
//                  long t0 = System.currentTimeMillis();
                    try {
                        searcher.search(null, 0, 1, null, 1, null, null);
                    } catch (Throwable t) {
                        assertTrue(t.getMessage().contains("TrafficLimitingSearcher"));
                    } finally {
                        queriesDone++;
                    }
//                  long tf = System.currentTimeMillis();
//                  System.out.println(tf - t0);
                }
            }.start();
        }

        while (queriesDone < NUM_THREADS) {
            assertTrue(baseSearcher.queriesInProgress <= searcher.getMaxSimultaneousQueries());
            if (baseSearcher.queriesInProgress > searcher.getMaxSimultaneousQueries()){
                fail(baseSearcher.queriesInProgress + " queries, should be <=" + searcher.getMaxSimultaneousQueries());
            }
            Thread.sleep(50);
        }
    }





    boolean semaphorePassed = false;
    /**
     * Tests that queries that throw an Exception on baseSearcher release their semaphore.
     */
    @TestInfo(testType = TestInfo.TestType.UNIT)
    public void testReleaseSemaphoreOnBaseException() {
        // how many simultaneous queries to support
        int slots = 5;
        AlwaysFailSearcher baseSearcher = new AlwaysFailSearcher();
        final TrafficLimitingSearcher searcher = new TrafficLimitingSearcher(baseSearcher,slots,1/*no timeout*/);
        for (int i = 0; i < slots +1 ; i++){
            try {
                searcher.search(null, 0, 1, null, 1, null, null);
                fail(); // should not happen, as AlwaysFailSearcher will throw a SearcherException
            catch (SearcherException se){
                // do nothing ..
            }
        }

        // now, try with another query. If the slots were not released, it should fail with TrafficLimitingSearcher Exception.
        // if it failed with "I always fail", it is ok.
        Thread searchThread  = new Thread() {
            public void run() {
                try {
                    searcher.search(null, 0, 1, null, 1, null, null);
                } catch (Throwable t) {
                    assertFalse(t.getMessage().contains("TrafficLimitingSearcher"));
                    assertTrue(t.getMessage().contains("I always fail"));
                    semaphorePassed = true;
                }
            }
        };
        searchThread.setDaemon(true);
        searchThread.start();

        com.flaptor.util.Execute.sleep(5000);
        if (!semaphorePassed) {
            fail("query got stuck waiting for semaphore");
        }
    }


}
TOP

Related Classes of com.flaptor.hounder.indexer.TrafficLimitingSearcherTest$AlwaysFailSearcher

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.