public void testUseBlockIO() {

    String remoteHost = TEST_HOST;
    int nIterations = 100;
    for (int i = 0; i < nIterations; ++i) {
      Set<Boolean> blockModes = new HashSet<Boolean>(Arrays.asList(new Boolean[] {false, true}));
      for (boolean useBlockIO : blockModes) {
        Client client = new ClientImpl(remoteHost, TEST_PORT, useBlockIO);

        Object[] tubeNames = pushWatchedTubes(client);

        String srcString = "testUseBlockIO";

        // producer
        client.useTube((String) tubeNames[1]);
        long jobId = client.put(65536, 0, 120, srcString.getBytes());
        assertTrue(jobId > 0);

        // consumer
        Job job = client.reserve(null);
        assertNotNull(job);
        long newJobId = job.getJobId();
        assertEquals(jobId, newJobId);

        String dstString = new String(job.getData());
        assertEquals(srcString, dstString);

        client.delete(job.getJobId());

        popWatchedTubes(client, tubeNames);
        client.close();
      }
    }
  }
  public void testReserve() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);

    String srcString = "testReserve";

    // producer
    client.useTube((String) tubeNames[1]);
    long jobId = client.put(65536, 0, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    // consumer
    Job job = client.reserve(null);
    assertNotNull(job);
    long newJobId = job.getJobId();
    assertEquals(jobId, newJobId);

    String dstString = new String(job.getData());
    assertEquals(srcString, dstString);

    client.delete(job.getJobId());

    popWatchedTubes(client, tubeNames);
  }
  public void testBinaryData() {

    for (boolean useBlockIO : new boolean[] {false, true}) {
      Client client = new ClientImpl(TEST_HOST, TEST_PORT, useBlockIO);

      Object[] tubeNames = pushWatchedTubes(client);

      byte[] srcBytes = new byte[256];
      for (int i = 0; i < srcBytes.length; ++i) {
        srcBytes[i] = (byte) i;
      }

      // producer
      client.useTube((String) tubeNames[1]);
      long jobId = client.put(65536, 0, 120, srcBytes);
      assertTrue(jobId > 0);

      // consumer
      Job job = client.reserve(null);
      assertNotNull(job);
      long newJobId = job.getJobId();
      assertEquals(jobId, newJobId);

      // verify bytes
      byte[] dstBytes = job.getData();
      assertEquals(srcBytes.length, dstBytes.length);
      for (int i = 0; i < srcBytes.length; ++i) {
        assertEquals(srcBytes[i], dstBytes[i]);
      }

      client.delete(job.getJobId());

      popWatchedTubes(client, tubeNames);
    }
  }
  // ****************************************************************
  // Consumer methods
  // peek-related
  // ****************************************************************
  public void testPeek() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);
    client.useTube((String) tubeNames[1]);

    Job job = client.peek(-1);
    assertNull(job);
    job = client.peek(0);
    assertNull(job);

    String srcString = "testPeek-";

    int nJobs = 3;
    long[] jobIds = new long[nJobs];

    // producer
    for (int i = 0; i < nJobs; ++i) {
      client.useTube((String) tubeNames[1]);
      long jobId = client.put(65536, 0, 120, (srcString + i).getBytes());
      assertTrue(jobId > 0);
      jobIds[i] = jobId;
    }

    // peek 'em once
    for (int i = 0; i < nJobs; ++i) {
      job = client.peek(jobIds[i]);
      assertNotNull(job);
      assertEquals(jobIds[i], job.getJobId());
    }

    // peek 'em again
    for (int i = 0; i < nJobs; ++i) {
      job = client.peek(jobIds[i]);
      assertNotNull(job);
      assertEquals(jobIds[i], job.getJobId());
    }

    // reserve and delete
    for (int i = 0; i < nJobs; ++i) {
      job = client.reserve(null);
      assertNotNull(job);
      assertEquals(jobIds[i], job.getJobId());
      client.delete(job.getJobId());
    }

    // peek one last time
    for (int i = 0; i < nJobs; ++i) {
      job = client.peek(jobIds[i]);
      assertNull(job);
    }

    popWatchedTubes(client, tubeNames);
  }
  public void testBuryKick() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);

    String srcString = "testBuryKick";

    // nothing to bury
    boolean ok = false;
    ok = client.bury(0, 65536);
    assertFalse(ok);

    // producer
    client.useTube((String) tubeNames[1]);
    long jobId = client.put(65536, 0, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    // we haven't reserved, so we can't bury
    ok = client.bury(jobId, 65536);
    assertFalse(ok);

    // we can bury
    Job job = client.reserve(0);
    assertNotNull(job);
    ok = client.bury(jobId, 65536);
    assertTrue(ok);

    // nothing to reserve
    job = client.reserve(0);
    assertNull(job);

    // kick nothing
    int count = client.kick(0);
    assertEquals(0, count);
    job = client.reserve(0);
    assertNull(job);

    // kick something
    count = client.kick(1);
    assertEquals(1, count);
    job = client.reserve(0);
    assertNotNull(job);
    assertEquals(jobId, job.getJobId());
    assertEquals(srcString, new String(job.getData()));

    client.delete(jobId);

    popWatchedTubes(client, tubeNames);
  }
  public void testBuried() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);
    client.useTube((String) tubeNames[1]);

    String srcString = "testPeekBuried";

    // peekBuried
    Job job = client.peekBuried();
    assertNull(job);

    // producer
    long jobId = client.put(65536, 0, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    // peekBuried
    job = client.peekBuried();
    assertNull(job);

    // reserve and bury
    job = client.reserve(null);
    assertNotNull(job);
    assertEquals(jobId, job.getJobId());
    client.bury(job.getJobId(), 65536);

    // peekBuried
    job = client.peekBuried();
    assertNotNull(job);
    assertEquals(jobId, job.getJobId());

    // delete
    client.delete(jobId);

    // peekBuried
    job = client.peekBuried();
    assertNull(job);

    popWatchedTubes(client, tubeNames);
  }
  public void testReserveWithTimeout() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);

    String srcString = "testReserveWithTimeout";

    int timeoutSeconds = 2;

    // producer
    client.useTube((String) tubeNames[1]);
    long putMillis = System.currentTimeMillis();
    long jobId = client.put(65536, timeoutSeconds, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    // consumer
    Job job = client.reserve(timeoutSeconds);
    long getMillis = System.currentTimeMillis();

    assertNotNull(job);
    long newJobId = job.getJobId();
    assertEquals(jobId, newJobId);

    String dstString = new String(job.getData());
    assertEquals(srcString, dstString);

    long deltaSeconds = (getMillis - putMillis) / 1000;
    assertTrue(deltaSeconds >= timeoutSeconds);

    client.delete(job.getJobId());

    // now try to achieve a TIMED_OUT
    jobId = client.put(65536, 2 * timeoutSeconds, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    job = client.reserve(timeoutSeconds);
    assertNull(job);

    popWatchedTubes(client, tubeNames);
  }
  public void testDelayed() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);
    client.useTube((String) tubeNames[1]);

    String srcString = "testPeekDelay";
    int delaySeconds = 2;

    // producer
    client.useTube((String) tubeNames[1]);
    // note we adjust delay
    long jobId = client.put(65536, delaySeconds, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    // peekDelayed
    Job job = client.peekDelayed();
    assertNotNull(job);
    assertEquals(jobId, job.getJobId());

    try {
      Thread.sleep(delaySeconds * 1000);
    } catch (Exception e) {

    }

    // reserve and delete
    job = client.reserve(null);
    assertNotNull(job);
    assertEquals(jobId, job.getJobId());
    client.delete(job.getJobId());

    // peek one last time
    job = client.peekDelayed();
    assertNull(job);

    popWatchedTubes(client, tubeNames);
  }
  public void testRelease() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);

    String srcString = "testReserveWithTimeout";

    int timeoutSeconds = 2;

    // producer
    client.useTube((String) tubeNames[1]);
    long jobId = client.put(65536, timeoutSeconds, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    // not found
    boolean ok = client.release(jobId, 65536, 0);
    assertFalse(ok);

    Job job = client.reserve(null);
    assertNotNull(job);
    assertEquals(jobId, job.getJobId());

    // quick release
    ok = client.release(jobId, 65536, 0);
    assertTrue(ok);

    job = client.reserve(null);
    assertNotNull(job);
    assertEquals(jobId, job.getJobId());

    ok = client.delete(jobId);
    assertTrue(ok);

    ok = client.release(jobId, 65536, 0);
    assertFalse(ok);

    popWatchedTubes(client, tubeNames);
  }
  public void testDelete() {

    Client client = new ClientImpl(TEST_HOST, TEST_PORT);

    Object[] tubeNames = pushWatchedTubes(client);

    String srcString = "testDelete";

    client.useTube((String) tubeNames[1]);
    long jobId = client.put(65536, 0, 120, srcString.getBytes());
    assertTrue(jobId > 0);

    Job job = client.reserve(null);
    assertNotNull(job);
    boolean ok = client.delete(job.getJobId());
    assertTrue(ok);

    // delete a second time
    ok = client.delete(job.getJobId());
    assertFalse(ok);

    popWatchedTubes(client, tubeNames);
  }