Package org.jscsi.scsi.tasks.management

Source Code of org.jscsi.scsi.tasks.management.DefaultTaskSetTest

/**
* Copyright (c) 2012, University of Konstanz, Distributed Systems Group
* 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 the University of Konstanz 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 <COPYRIGHT HOLDER> 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.
*/
//Cleversafe open-source code header - Version 1.1 - December 1, 2006
//
//Cleversafe Dispersed Storage(TM) is software for secure, private and
//reliable storage of the world's data using information dispersal.
//
//Copyright (C) 2005-2007 Cleversafe, Inc.
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
//USA.
//
//Contact Information:
// Cleversafe, 10 W. 35th Street, 16th Floor #84,
// Chicago IL 60616
// email: licensing@cleversafe.org
//
//END-OF-HEADER
//-----------------------
//@author: John Quigley <jquigley@cleversafe.com>
//@date: January 1, 2008
//---------------------

package org.jscsi.scsi.tasks.management;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.log4j.Logger;
import org.jscsi.core.scsi.Status;
import org.jscsi.scsi.protocol.sense.KCQ;
import org.jscsi.scsi.protocol.sense.SenseData;
import org.jscsi.scsi.protocol.sense.SenseDataFactory;
import org.jscsi.scsi.tasks.Task;
import org.jscsi.scsi.transport.Nexus;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class DefaultTaskSetTest extends AbstractTaskSetTest
{
   // TODO: Test abort(), clear(), clear(Nexus), and remove(Nexus) methods

   private static Logger _logger = Logger.getLogger(DefaultTaskSetTest.class);

   // 10 threads is an arbitrary value chosen to always allow simultaneous task execution
   // for all the following test cases.
   public static final int MANAGER_THREAD_COUNT = 10;

   // Queue depth set to be great enough for all test cases without queue bottleneck
   public static final int SET_QUEUE_DEPTH = 10;

   // A queue depth set to test queue bottleneck conditions
   public static final int LIMITING_SET_QUEUE_DEPTH = 5;

   @Before
   public void setUp() throws Exception
   {
      //DOMConfigurator.configure(System.getProperty("log4j.configuration"));
   }

   @After
   public void tearDown() throws Exception
   {
   }

   private static void waitForTask(TestTask task, int loginterval) throws InterruptedException
   {
      synchronized (task)
      {
         _logger.debug("Testing framework waiting on task: " + task);
         synchronized (task)
         {
            while (!task.isDone())
            {
               _logger.debug("testing framework waiting... (" + task + ")");
               task.wait(loginterval);
            }
         }
         _logger.debug("Testing framework found task is now complete: " + task);
      }
   }

   private static void executeTaskSet(List<TestTask> taskSet) throws InterruptedException
   {
      TaskSet set = new DefaultTaskSet(SET_QUEUE_DEPTH);
      DefaultTaskManager manager = new DefaultTaskManager(MANAGER_THREAD_COUNT, set);

      for (Task t : taskSet)
      {
         set.offer(t);
      }

      Thread thread = new Thread(manager);
      _logger.debug("Starting task manager: " + manager);
      thread.start();

      for (TestTask task : taskSet)
      {
         waitForTask(task, 100);
      }

      manager.shutdown();
      thread.join();

   }

   private static void checkTaskSet(List<TestTask> taskSet)
   {
      for (int i = 0; i < taskSet.size(); i++)
      {
         TestTask t = taskSet.get(i);

         if (!t.isDone())
         {
            fail("Task " + i + " not executed: " + t.getClass().getName());
         }
         else
         {
            assertTrue("Task " + i + " failed (" + t.isProper() + "): " + t.reason() + ": "
                  + t.getClass().getName(), t.isProper());
         }
      }
   }

   @Test
   public void testStaticInsertion_HSO() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new HeadOfQueueTask(new Nexus(nexus, 0), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 1), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 2), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_HSSO() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new HeadOfQueueTask(new Nexus(nexus, 0), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 1), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 2), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 3), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_HOOS() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new HeadOfQueueTask(new Nexus(nexus, 0), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 1), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 2), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 3), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_HHSS() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new HeadOfQueueTask(new Nexus(nexus, 0), taskSet, 0);
      new HeadOfQueueTask(new Nexus(nexus, 1), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 2), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 3), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_SOSSOHH() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new SimpleTask(new Nexus(nexus, 0), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 1), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 2), taskSet, 100);
      new SimpleTask(new Nexus(nexus, 3), taskSet, 50);
      new OrderedTask(new Nexus(nexus, 4), taskSet, 0);
      new HeadOfQueueTask(new Nexus(nexus, 5), taskSet, 0);
      new HeadOfQueueTask(new Nexus(nexus, 6), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_OSOOHH() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new OrderedTask(new Nexus(nexus, 0), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 1), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 2), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 3), taskSet, 0);
      new HeadOfQueueTask(new Nexus(nexus, 4), taskSet, 0);
      new HeadOfQueueTask(new Nexus(nexus, 5), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_SOSSO() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new SimpleTask(new Nexus(nexus, 0), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 1), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 2), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 3), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 4), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_OSSO() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new OrderedTask(new Nexus(nexus, 0), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 1), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 2), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 3), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testStaticInsertion_SSO() throws InterruptedException
   {
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      new SimpleTask(new Nexus(nexus, 0), taskSet, 0);
      new SimpleTask(new Nexus(nexus, 1), taskSet, 0);
      new OrderedTask(new Nexus(nexus, 2), taskSet, 100);

      executeTaskSet(taskSet);
      checkTaskSet(taskSet);
   }

   @Test
   public void testDynamicInsertion_H1S2H3S4_34() throws InterruptedException
   {
      /*
       * Tests scenario in SAM-2 7.7.2 Figure 34
       *
       * Expected execution order:
       *
       * 0     put(H1), ena(H1)     wait 4000
       *       put(S2)              wait 4000
       *       wait(100)
       *
       * 100   put(H3), ena(H3)     wait 500
       *       put(S4)              wait 100
       *      
       * 600   fin(H3)
       *
       * 4000  fin(H1)
       *       ena(S2)
       *       ena(S4)
       *
       * 4100  fin(S4)
       *
       * 8000 fin(S2)
       *
       *
       */
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      TestTask h1 = new HeadOfQueueTask(new Nexus(nexus, 1), taskSet, 4000);
      TestTask s2 = new SimpleTask(new Nexus(nexus, 2), taskSet, 4000);
      TestTask h3 = new HeadOfQueueTask(new Nexus(nexus, 3), taskSet, 500);
      TestTask s4 = new SimpleTask(new Nexus(nexus, 4), taskSet, 100);

      TaskSet set = new DefaultTaskSet(SET_QUEUE_DEPTH);
      TaskManager manager = new DefaultTaskManager(MANAGER_THREAD_COUNT, set);

      // Start task manager
      Thread thread = new Thread(manager);
      _logger.debug("Starting task manager with empty task set: " + manager);
      thread.start();

      // Waiting for 1 seconds
      Thread.sleep(1000);

      // Time: 0

      set.offer(h1);
      set.offer(s2);

      Thread.sleep(100);

      // Time: 100

      assertTrue("H1 finished too quickly", !h1.isDone());
      assertTrue("S2 finished too quickly", !s2.isDone());

      set.offer(h3);
      set.offer(s4);

      waitForTask(h3, 500);

      // Time: 600

      assertTrue("H1 finished too quickly", !h1.isDone());
      assertTrue("S2 finished too quickly", !s2.isDone());
      assertTrue("H3 finished improperly", h3.isProper());
      assertTrue("S4 finished too quickly", !s4.isDone());

      waitForTask(h1, 500);

      // Time: 4000

      assertTrue("H1 finished improperly", h1.isProper());
      assertTrue("S2 finished too quickly", !s2.isDone());
      assertTrue("S4 finished too quickly", !s4.isDone());

      waitForTask(s4, 500);

      // Time: 4100

      assertTrue("S2 finished too quickly", !s2.isDone());
      assertTrue("S4 finished improperly", s4.isProper());

      waitForTask(s2, 500);

      assertTrue("S2 finished improperly", s2.isProper());

      // Shutting down task manager
      thread.interrupt();
      thread.join();

   }

   @Test
   public void testDynamicInsertion_H1S2H3S4_35() throws InterruptedException
   {
      /*
       * Tests scenario in SAM-2 7.7.2 Figure 35
       *
       * Expected execution order:
       *
       * 0     put(H1), ena(H1)     wait 2000
       *       put(S2)              wait 1000
       *       wait(100)
       *
       * 100   put(H3), ena(H3)     wait 4000
       *       put(S4)              wait 100
       *
       * 2100  fin(H1)
       *       ena(S2)
       *
       * 3100  fin(S2)
       *
       * 4100  fin(H3)
       *       ena(S4)
       *      
       * 4200  fin(S4)
       *
       */
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      TestTask h1 = new HeadOfQueueTask(new Nexus(nexus, 1), taskSet, 2000);
      TestTask s2 = new SimpleTask(new Nexus(nexus, 2), taskSet, 1000);
      TestTask h3 = new HeadOfQueueTask(new Nexus(nexus, 3), taskSet, 4000);
      TestTask s4 = new SimpleTask(new Nexus(nexus, 4), taskSet, 100);

      TaskSet set = new DefaultTaskSet(SET_QUEUE_DEPTH);
      TaskManager manager = new DefaultTaskManager(MANAGER_THREAD_COUNT, set);

      // Start task manager
      Thread thread = new Thread(manager);
      _logger.debug("Starting task manager with empty task set: " + manager);
      thread.start();

      // Waiting for 1 seconds
      Thread.sleep(1000);

      // Time: 0

      set.offer(h1);
      set.offer(s2);

      Thread.sleep(100);

      // Time: 100

      assertTrue("H1 finished too quickly", !h1.isDone());
      assertTrue("S2 finished too quickly", !s2.isDone());

      set.offer(h3);
      set.offer(s4);

      waitForTask(h1, 500);

      // Time: 2100

      assertTrue("H1 finished improperly", h1.isProper());
      assertTrue("S2 finished too quickly", !s2.isDone());
      assertTrue("H3 finished too quickly", !h3.isDone());
      assertTrue("S4 finished too quickly", !s4.isDone());

      waitForTask(s2, 500);

      // Time: 3100

      assertTrue("S2 finished improperly", s2.isProper());
      assertTrue("H3 finished too quickly", !h3.isDone());
      assertTrue("S4 finished too quickly", !s4.isDone());

      waitForTask(h3, 500);

      // Time: 4100

      assertTrue("H3 finished improperly", h3.isProper());
      assertTrue("S4 finished too quickly", !s4.isDone());

      waitForTask(s4, 500);

      assertTrue("S4 finished improperly", s4.isProper());

      // Shutting down task manager
      thread.interrupt();
      thread.join();

   }

   @Test
   public void testDynamicInsertion_S1O2S3S4O5_36() throws InterruptedException
   {
      /*
       * Tests scenario in SAM-2 7.7.3 Figure 36
       *
       * Expected execution order:
       *
       * 0     put(S1)              wait 1000
       *       ena(S1)
       *       put(O2)              wait 1000
       *       wait(100)
       *      
       * 100   put(S3)              wait 1000
       *       put(S4)              wait 500
       *       put(O5)              wait 500
       *      
       * 1000  fin(S1)
       *       ena(O2)
       *      
       * 2000  fin(O2)
       *       ena(S3)
       *       ena(S4)
       *      
       *      
       * 2500  fin(S4)
       *      
       * 3000  fin(S3)
       *       ena(O5)
       *      
       * 3500  fin(O5)
       *
       */
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      TestTask s1 = new SimpleTask(new Nexus(nexus, 1), taskSet, 1000);
      TestTask o2 = new OrderedTask(new Nexus(nexus, 2), taskSet, 1000);
      TestTask s3 = new SimpleTask(new Nexus(nexus, 3), taskSet, 1000);
      TestTask s4 = new SimpleTask(new Nexus(nexus, 4), taskSet, 500);
      TestTask o5 = new OrderedTask(new Nexus(nexus, 5), taskSet, 500);

      TaskSet set = new DefaultTaskSet(SET_QUEUE_DEPTH);
      TaskManager manager = new DefaultTaskManager(MANAGER_THREAD_COUNT, set);

      // Start task manager
      Thread thread = new Thread(manager);
      _logger.debug("Starting task manager with empty task set: " + manager);
      thread.start();

      // Waiting for 1 seconds
      Thread.sleep(1000);

      // Time: 0

      set.offer(s1);
      set.offer(o2);

      Thread.sleep(100);

      // Time: 100

      assertTrue("S1 finished too quickly", !s1.isDone());
      assertTrue("O2 finished too quickly", !o2.isDone());

      set.offer(s3);
      set.offer(s4);
      set.offer(o5);

      waitForTask(s1, 500);

      // Time: 1000

      assertTrue("S1 finished improperly", s1.isProper());
      assertTrue("O2 finished too quickly", !o2.isDone());
      assertTrue("S3 finished too quickly", !s3.isDone());
      assertTrue("S4 finished too quickly", !s4.isDone());
      assertTrue("O5 finished too quickly", !o5.isDone());

      waitForTask(o2, 500);

      // Time: 2000

      assertTrue("O2 finished improperly", o2.isProper());
      assertTrue("S3 finished too quickly", !s3.isDone());
      assertTrue("S4 finished too quickly", !s4.isDone());
      assertTrue("O5 finished too quickly", !o5.isDone());

      waitForTask(s4, 500);

      // Time: 2500

      assertTrue("S3 finished too quickly", !s3.isDone());
      assertTrue("S4 finished improperly", s4.isProper());
      assertTrue("O5 finished too quickly", !o5.isDone());

      waitForTask(s3, 500);

      // Time: 3000

      assertTrue("S3 finished improperly", s3.isProper());
      assertTrue("O5 finished too quickly", !o5.isDone());

      waitForTask(o5, 500);

      assertTrue("O5 finished improperly", o5.isProper());

      // Shutting down task manager
      thread.interrupt();
      thread.join();

   }

   @Test
   public void testQueueOverflow() throws InterruptedException
   {
      TestTargetTransportPort port = new TestTargetTransportPort(null, true);
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);

      TaskSet set = new DefaultTaskSet(LIMITING_SET_QUEUE_DEPTH);

      for (int i = 0; i < LIMITING_SET_QUEUE_DEPTH; i++)
      {
         set.offer(new SimpleTask(port, new Nexus(nexus, i), taskSet, 0));
      }

      // Offer one too many tasks to task queue

      boolean result =
            set.offer(new SimpleTask(port, new Nexus(nexus, LIMITING_SET_QUEUE_DEPTH + 1), taskSet,
                  0));

      assertTrue("Task set accepted too many tasks", !result);

      assertEquals("Task set did not report TASK SET FULL condition to transport",
            Status.TASK_SET_FULL, port.getLastStatus());

      assertEquals("Task set sent invalid sense data to transport", null, port.getSenseData());

   }

   private void testDuplicateTasks(long tag1, long tag2, boolean expectFailure)
   {
      TestTargetTransportPort port = new TestTargetTransportPort(null, true);
      TaskSet set = new DefaultTaskSet(LIMITING_SET_QUEUE_DEPTH);
      List<TestTask> taskSet = new ArrayList<TestTask>();
      Nexus nexus = new Nexus("initiator", "target", 0);
      Task one = new SimpleTask(port, new Nexus(nexus, tag1), taskSet, 0);
      Task two = new SimpleTask(port, new Nexus(nexus, tag2), taskSet, 0);

      boolean result = set.offer(one);

      assertTrue("Added first task failed", result);

      result = set.offer(two);

      if (result)
      {
         if (expectFailure)
            fail("Adding second task suceeded unexpectedly");
      }
      else
      {
         if (!expectFailure)
            fail("Adding second task failed unexpectedly");

         assertEquals("Task set did not report CHECK CONDITION to transport",
               Status.CHECK_CONDITION, port.getLastStatus());

         try
         {
            SenseData sense = (new SenseDataFactory()).decode(port.getSenseData());

            assertEquals("Task set did not return correct KCQ", KCQ.OVERLAPPED_COMMANDS_ATTEMPTED,
                  sense.getKCQ());

         }
         catch (IOException e)
         {
            e.printStackTrace();
            fail("Could not decode sense data returned from task set");
         }
      }

   }

   @Test
   public void testDuplicateTaggedTasks()
   {
      Random rand = new Random();
      long tag = Math.abs(rand.nextLong());

      testDuplicateTasks(tag, tag, true);
   }

   @Test
   public void testNonDuplicateTaggedTasks()
   {
      Random rand = new Random();
      long tag1 = Math.abs(rand.nextLong());
      long tag2 = Math.abs(rand.nextLong());

      testDuplicateTasks(tag1, tag2, false);
   }

   @Test
   public void testDuplicateUntaggedTasks()
   {
      testDuplicateTasks(-1, -1, true);
   }

}
TOP

Related Classes of org.jscsi.scsi.tasks.management.DefaultTaskSetTest

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.