/** Test ensureValid returns true after acquire */
 public void testValidAfterAcquire() throws IOException {
   Path tempPath = createTempDir();
   Directory dir = getDirectory(tempPath);
   Lock l = dir.obtainLock("commit");
   l.ensureValid(); // no exception
   l.close();
   dir.close();
 }
  /** Test closing locks twice */
  public void testDoubleClose() throws IOException {
    Path tempPath = createTempDir();
    Directory dir = getDirectory(tempPath);

    Lock l = dir.obtainLock("commit");
    l.close();
    l.close(); // close again, should be no exception

    dir.close();
  }
  /** Test obtaining and releasing locks, checking validity */
  public void testBasics() throws IOException {
    Path tempPath = createTempDir();
    Directory dir = getDirectory(tempPath);

    Lock l = dir.obtainLock("commit");
    // shouldn't be able to get the lock twice
    expectThrows(
        LockObtainFailedException.class,
        () -> {
          dir.obtainLock("commit");
        });
    l.close();

    // Make sure we can obtain first one again:
    l = dir.obtainLock("commit");
    l.close();

    dir.close();
  }
 @Override
 public void close() {
   if (closed.compareAndSet(false, true) && locks != null) {
     for (Lock lock : locks) {
       try {
         logger.trace("releasing lock [{}]", lock);
         lock.close();
       } catch (IOException e) {
         logger.trace("failed to release lock [{}]", e, lock);
       }
     }
   }
 }
  /** Test ensureValid throws exception after close */
  public void testInvalidAfterClose() throws IOException {
    Path tempPath = createTempDir();
    Directory dir = getDirectory(tempPath);

    Lock l = dir.obtainLock("commit");
    l.close();

    expectThrows(
        AlreadyClosedException.class,
        () -> {
          l.ensureValid();
        });

    dir.close();
  }