@@ -0,0 +1,1487 @@
+package water;%0A%0Aimport org.junit.Assert;%0Aimport org.junit.BeforeClass;%0Aimport org.junit.Test;%0Aimport water.api.UnlockTask;%0Aimport water.fvec.Frame;%0Aimport water.util.Log;%0A%0Apublic class UnlockTest extends TestUtil %7B%0A  @BeforeClass%0A  public static void stall() %7B stall_till_cloudsize(3); %7D%0A%0A  static class DJob extends Job %7B%0A    DJob(Key a) %7B super(a,%22DJob%22,1); %7D%0A  %7D%0A%0A  @Test%0A  public void run() %7B%0A    // Put chunks into KV store%0A    Frame f = new TestUtil().parse_test_file(%22smalldata/junit/syn_2659x1049.csv.gz%22);%0A    // Create two lockable frames in KV store%0A    Frame fr1 = new Frame(Key.make(), f.names(), f.vecs());%0A    Frame fr2 = new Frame(Key.make(), f.names(), f.vecs());%0A    DJob dj = new DJob(Key.make());%0A    // Lock the frames against writes%0A    fr1.delete_and_lock(dj._key);%0A    fr2.delete_and_lock(dj._key);%0A    int i = 0;%0A    try %7B%0A      // try to delete the write-locked frames -%3E will throw an exception%0A      fr1.delete();%0A      fr2.delete(); // won't be reached%0A    %7D catch (Throwable t) %7B%0A      Log.info(%22Correctly caught exception: %22 + t.getClass()); //either AssertionError if local or DistributedException if remote%0A      i++;%0A    %7D finally %7B%0A      // second attempt: will unlock and delete properly%0A      new UnlockTask().doAllNodes(); // without this line, there will be a leak (and assertion won't be shown)%0A      fr1.delete();%0A      fr2.delete();%0A      f.delete();%0A      Log.info(%22Able to delete after unlocking.%22);%0A    %7D%0A    Assert.assertTrue(i == 1);%0A  %7D%0A%7D%0A

Add JUnit test for UnlockKeys.