diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetCodecTest.java | 73 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetImplTest.java | 63 |
2 files changed, 110 insertions, 26 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetCodecTest.java b/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetCodecTest.java index e9b1d647eb..9341084eec 100644 --- a/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetCodecTest.java +++ b/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetCodecTest.java @@ -17,18 +17,24 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; +import com.google.devtools.build.lib.collect.nestedset.NestedSetStore.InMemoryNestedSetStorageEndpoint; +import com.google.devtools.build.lib.collect.nestedset.NestedSetStore.NestedSetCache; import com.google.devtools.build.lib.collect.nestedset.NestedSetStore.NestedSetStorageEndpoint; import com.google.devtools.build.lib.skyframe.serialization.AutoRegistry; import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs; import com.google.devtools.build.lib.skyframe.serialization.SerializationConstants; import com.google.devtools.build.lib.skyframe.serialization.SerializationResult; import com.google.protobuf.ByteString; +import java.nio.charset.Charset; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; /** Tests for {@link NestedSet} serialization. */ @@ -49,7 +55,7 @@ public class NestedSetCodecTest { ObjectCodecs objectCodecs = new ObjectCodecs( AutoRegistry.get().getBuilder().setAllowDefaultCodec(true).build(), ImmutableMap.of()); - NestedSetCodecTestUtils.checkCodec(objectCodecs, false); + NestedSetCodecTestUtils.checkCodec(objectCodecs, false, false); } @Test @@ -62,7 +68,7 @@ public class NestedSetCodecTest { .add(new NestedSetCodecWithStore<>(NestedSetStore.inMemory())) .build(), ImmutableMap.of()); - NestedSetCodecTestUtils.checkCodec(objectCodecs, true); + NestedSetCodecTestUtils.checkCodec(objectCodecs, true, true); } /** @@ -166,7 +172,68 @@ public class NestedSetCodecTest { .setAllowDefaultCodec(true) .add(new NestedSetCodecWithStore<>(mockNestedSetStore)) .build()); - NestedSet<String> singletonNestedSet = new NestedSet<>(Order.STABLE_ORDER, "a"); + NestedSet<String> singletonNestedSet = + new NestedSetBuilder<String>(Order.STABLE_ORDER).add("a").build(); objectCodecs.serialize(singletonNestedSet); } + + @Test + public void testDeserializationInParallel() throws Exception { + NestedSetStorageEndpoint nestedSetStorageEndpoint = + Mockito.spy(new InMemoryNestedSetStorageEndpoint()); + NestedSetCache emptyNestedSetCache = Mockito.mock(NestedSetCache.class); + NestedSetStore nestedSetStore = + new NestedSetStore( + nestedSetStorageEndpoint, emptyNestedSetCache, MoreExecutors.directExecutor()); + + ObjectCodecs objectCodecs = + new ObjectCodecs( + AutoRegistry.get() + .getBuilder() + .setAllowDefaultCodec(true) + .add(new NestedSetCodecWithStore<>(nestedSetStore)) + .build()); + + NestedSet<String> subset1 = + new NestedSetBuilder<String>(Order.STABLE_ORDER).add("a").add("b").build(); + SettableFuture<byte[]> subset1Future = SettableFuture.create(); + NestedSet<String> subset2 = + new NestedSetBuilder<String>(Order.STABLE_ORDER).add("c").add("d").build(); + SettableFuture<byte[]> subset2Future = SettableFuture.create(); + NestedSet<String> set = + new NestedSetBuilder<String>(Order.STABLE_ORDER) + .addTransitive(subset1) + .addTransitive(subset2) + .build(); + + // We capture the arguments to #put() during serialization, so as to correctly mock results for + // #get() + ArgumentCaptor<ByteString> fingerprintCaptor = ArgumentCaptor.forClass(ByteString.class); + ByteString fingerprint = + nestedSetStore + .computeFingerprintAndStore( + (Object[]) set.getChildren(), objectCodecs.getSerializationContext()) + .fingerprint(); + Mockito.verify(nestedSetStorageEndpoint, Mockito.times(3)) + .put(fingerprintCaptor.capture(), Mockito.any()); + Mockito.doReturn(subset1Future) + .when(nestedSetStorageEndpoint) + .get(fingerprintCaptor.getAllValues().get(0)); + Mockito.doReturn(subset2Future) + .when(nestedSetStorageEndpoint) + .get(fingerprintCaptor.getAllValues().get(1)); + + ListenableFuture<Object[]> deserializationFuture = + nestedSetStore.getContentsAndDeserialize( + fingerprint, objectCodecs.getDeserializationContext()); + // At this point, we expect deserializationFuture to be waiting on both of the underlying + // fetches, which should have both been started. + assertThat(deserializationFuture.isDone()).isFalse(); + Mockito.verify(nestedSetStorageEndpoint, Mockito.times(3)).get(Mockito.any()); + + // Once the underlying fetches complete, we expect deserialization to complete. + subset1Future.set(ByteString.copyFrom("mock bytes", Charset.defaultCharset()).toByteArray()); + subset2Future.set(ByteString.copyFrom("mock bytes", Charset.defaultCharset()).toByteArray()); + assertThat(deserializationFuture.isDone()).isTrue(); + } } diff --git a/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetImplTest.java b/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetImplTest.java index ff4515276b..97fbf8d336 100644 --- a/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetImplTest.java +++ b/src/test/java/com/google/devtools/build/lib/collect/nestedset/NestedSetImplTest.java @@ -18,6 +18,8 @@ import static org.junit.Assert.fail; import com.google.common.collect.Lists; import com.google.common.testing.EqualsTester; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -164,40 +166,55 @@ public class NestedSetImplTest { public void shallowEquality() { // Used below to check that inner nested sets can be compared by reference equality. SetWrapper<Integer> myRef = nest(nest(flat(7, 8)), flat(9)); + // Used to check equality for deserializing nested sets + ListenableFuture<Object[]> contents = Futures.immediateFuture(new Object[] {"a", "b"}); + NestedSet<String> referenceNestedSet = NestedSet.withFuture(Order.STABLE_ORDER, contents); + NestedSet<String> otherReferenceNestedSet = NestedSet.withFuture(Order.STABLE_ORDER, contents); // Each "equality group" contains elements that are equal to one another // (according to equals() and hashCode()), yet distinct from all elements // of all other equality groups. new EqualsTester() - .addEqualityGroup(flat(), - flat(), - nest(flat())) // Empty set elision. - .addEqualityGroup(NestedSetBuilder.<Integer>linkOrder().build()) - .addEqualityGroup(flat(3), - flat(3), - flat(3, 3)) // Element de-duplication. - .addEqualityGroup(flat(4), - nest(flat(4))) // Automatic elision of one-element nested sets. - .addEqualityGroup(NestedSetBuilder.<Integer>linkOrder().add(4).build()) - .addEqualityGroup(nestedSetBuilder("4").build()) // Like flat("4"). - .addEqualityGroup(flat(3, 4), - flat(3, 4)) - // Make a couple sets deep enough that shallowEquals() fails. - // If this test case fails because you improve the representation, just delete it. - .addEqualityGroup(nest(nest(flat(3, 4), flat(5)), nest(flat(6, 7), flat(8)))) - .addEqualityGroup(nest(nest(flat(3, 4), flat(5)), nest(flat(6, 7), flat(8)))) - .addEqualityGroup(nest(myRef), - nest(myRef), - nest(myRef, myRef)) // Set de-duplication. - .addEqualityGroup(nest(3, myRef)) - .addEqualityGroup(nest(4, myRef)) - .testEquals(); + .addEqualityGroup(flat(), flat(), nest(flat())) // Empty set elision. + .addEqualityGroup(NestedSetBuilder.<Integer>linkOrder().build()) + .addEqualityGroup(flat(3), flat(3), flat(3, 3)) // Element de-duplication. + .addEqualityGroup(flat(4), nest(flat(4))) // Automatic elision of one-element nested sets. + .addEqualityGroup(NestedSetBuilder.<Integer>linkOrder().add(4).build()) + .addEqualityGroup(nestedSetBuilder("4").build()) // Like flat("4"). + .addEqualityGroup(flat(3, 4), flat(3, 4)) + // Make a couple sets deep enough that shallowEquals() fails. + // If this test case fails because you improve the representation, just delete it. + .addEqualityGroup(nest(nest(flat(3, 4), flat(5)), nest(flat(6, 7), flat(8)))) + .addEqualityGroup(nest(nest(flat(3, 4), flat(5)), nest(flat(6, 7), flat(8)))) + .addEqualityGroup(nest(myRef), nest(myRef), nest(myRef, myRef)) // Set de-duplication. + .addEqualityGroup(nest(3, myRef)) + .addEqualityGroup(nest(4, myRef)) + .addEqualityGroup( + new SetWrapper<>(referenceNestedSet), new SetWrapper<>(otherReferenceNestedSet)) + .testEquals(); // Some things that are not tested by the above: // - ordering among direct members // - ordering among transitive sets } + @Test + public void shallowInequality() { + assertThat(nestedSetBuilder("a").build().shallowEquals(null)).isFalse(); + Object[] contents = {"a", "b"}; + assertThat( + NestedSet.withFuture(Order.STABLE_ORDER, Futures.immediateFuture(contents)) + .shallowEquals(null)) + .isFalse(); + + // shallowEquals() should require reference equality for underlying futures + assertThat( + NestedSet.withFuture(Order.STABLE_ORDER, Futures.immediateFuture(contents)) + .shallowEquals( + NestedSet.withFuture(Order.STABLE_ORDER, Futures.immediateFuture(contents)))) + .isFalse(); + } + /** Checks that the builder always return a nested set with the correct order. */ @Test public void correctOrder() { |