// Copyright 2018 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.lib.collect.nestedset; import static com.google.common.truth.Truth.assertThat; import com.google.common.base.Objects; import com.google.common.util.concurrent.ListenableFuture; import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs; import com.google.devtools.build.lib.skyframe.serialization.SerializationContext; import com.google.devtools.build.lib.skyframe.serialization.SerializationException; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester; import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester.VerificationFunction; import java.io.IOException; /** Utilities for testing NestedSet serialization. */ public class NestedSetCodecTestUtils { private static final NestedSet SHARED_NESTED_SET = NestedSetBuilder.stableOrder().add("e").build(); @AutoCodec static class HasNestedSet { private final NestedSet nestedSetField; @VisibleForSerialization HasNestedSet(NestedSet nestedSetField) { this.nestedSetField = nestedSetField; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } HasNestedSet that = (HasNestedSet) o; return Objects.equal(nestedSetField.getChildren(), that.nestedSetField.getChildren()); } @Override public int hashCode() { return Objects.hashCode(nestedSetField); } } /** Perform serialization/deserialization checks for several simple NestedSet examples. */ public static void checkCodec( ObjectCodecs objectCodecs, boolean allowFutureBlocking, boolean assertSymmetricEquality) throws Exception { new SerializationTester( NestedSetBuilder.emptySet(Order.STABLE_ORDER), NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER), NestedSetBuilder.create(Order.STABLE_ORDER, "a"), NestedSetBuilder.create(Order.STABLE_ORDER, "a", "b", "c"), NestedSetBuilder.stableOrder() .add("a") .add("b") .addTransitive( NestedSetBuilder.stableOrder() .add("c") .addTransitive(SHARED_NESTED_SET) .build()) .addTransitive( NestedSetBuilder.stableOrder() .add("d") .addTransitive(SHARED_NESTED_SET) .build()) .addTransitive(NestedSetBuilder.emptySet(Order.STABLE_ORDER)) .build(), NestedSetBuilder.create( Order.STABLE_ORDER, new HasNestedSet(NestedSetBuilder.create(Order.STABLE_ORDER, "a")))) .setObjectCodecs(objectCodecs) .makeMemoizingAndAllowFutureBlocking(allowFutureBlocking) .setVerificationFunction(verificationFunction(assertSymmetricEquality)) .runTests(); } public static ListenableFuture writeToStoreFuture( NestedSetStore store, NestedSet nestedSet, SerializationContext serializationContext) throws IOException, SerializationException { return store .computeFingerprintAndStore((Object[]) nestedSet.getChildren(), serializationContext) .writeStatus(); } private static VerificationFunction> verificationFunction( boolean assertSymmetricEquality) { return (subject, deserialized) -> { if (assertSymmetricEquality) { assertThat(subject).isEqualTo(deserialized); assertThat(deserialized).isEqualTo(subject); } assertThat(subject.getOrder()).isEqualTo(deserialized.getOrder()); assertThat(subject.toSet()).isEqualTo(deserialized.toSet()); verifyStructure(subject.getChildren(), deserialized.getChildren()); }; } private static void verifyStructure(Object lhs, Object rhs) { if (lhs == NestedSet.EMPTY_CHILDREN) { assertThat(rhs).isSameAs(NestedSet.EMPTY_CHILDREN); } else if (lhs instanceof Object[]) { assertThat(rhs).isInstanceOf(Object[].class); Object[] lhsArray = (Object[]) lhs; Object[] rhsArray = (Object[]) rhs; int n = lhsArray.length; assertThat(rhsArray).hasLength(n); for (int i = 0; i < n; ++i) { verifyStructure(lhsArray[i], rhsArray[i]); } } else { assertThat(lhs).isEqualTo(rhs); } } }