diff options
author | janakr <janakr@google.com> | 2017-08-17 17:49:50 +0200 |
---|---|---|
committer | Irina Iancu <elenairina@google.com> | 2017-08-18 09:01:03 +0200 |
commit | b86f8b06f5f4832b51e3be0de9d32170a79371ee (patch) | |
tree | 154fe134c52fafccd35b7e086c7076666491901d /src/test/java/com/google/devtools/build/lib/skyframe/serialization | |
parent | 7321812d556f659b65952d5205250230e19d76cb (diff) |
Open-source Skyframe serialization, and make AppleConfiguration serializable as a pilot. Currently not hooked up to anything, but will be shortly.
PiperOrigin-RevId: 165583517
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/skyframe/serialization')
11 files changed, 499 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/AbstractObjectCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/AbstractObjectCodecTest.java new file mode 100644 index 0000000000..4fa00b33ef --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/AbstractObjectCodecTest.java @@ -0,0 +1,107 @@ +// Copyright 2017 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.skyframe.serialization; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.protobuf.CodedInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import javax.annotation.Nullable; +import org.junit.Before; +import org.junit.Test; + +/** Common ObjectCodec tests. */ +public abstract class AbstractObjectCodecTest<T> { + + @Nullable protected ObjectCodec<T> underTest; + @Nullable protected ImmutableList<T> subjects; + + /** + * Override to false to skip testDeserializeBadDataThrowsSerializationException(). Codecs that + * cannot distinguish good and bad data should do this. + */ + protected boolean shouldTestDeserializeBadData = true; + + /** Construct with the given codec and subjects. */ + protected AbstractObjectCodecTest( + ObjectCodec<T> underTest, @SuppressWarnings("unchecked") T... subjects) { + this.underTest = underTest; + this.subjects = ImmutableList.copyOf(subjects); + } + + /** + * Construct without a codec and subjects. They must be set in the subclass's constructor instead. + * + * <p>This is useful if the logic for creating the codec and/or subjects is non-trivial. Using + * this super constructor, the logic can be placed in the subclass's constructor; whereas if using + * the above super constructor, the logic must be factored into a static method. + */ + protected AbstractObjectCodecTest() {} + + @Before + public void checkInitialized() { + Preconditions.checkNotNull(underTest); + Preconditions.checkNotNull(subjects); + } + + @Test + public void testSuccessfulSerializationDeserialization() throws Exception { + for (T subject : subjects) { + byte[] serialized = toBytes(subject); + Object deserialized = fromBytes(serialized); + verifyDeserialization(deserialized, subject); + } + } + + @Test + public void testSerializationRoundTripBytes() throws Exception { + for (T subject : subjects) { + byte[] serialized = toBytes(subject); + T deserialized = fromBytes(serialized); + byte[] reserialized = toBytes(deserialized); + assertThat(reserialized).isEqualTo(serialized); + } + } + + @Test + public void testDeserializeBadDataThrowsSerializationException() { + if (!shouldTestDeserializeBadData) { + return; + } + try { + underTest.deserialize(CodedInputStream.newInstance("junk".getBytes(StandardCharsets.UTF_8))); + fail("Expected exception"); + } catch (SerializationException | IOException e) { + // Expected. + } + } + + protected T fromBytes(byte[] bytes) throws SerializationException, IOException { + return TestUtils.fromBytes(underTest, bytes); + } + + /** Serialize subject using the {@link ObjectCodec} under test. */ + protected byte[] toBytes(T subject) throws IOException, SerializationException { + return TestUtils.toBytes(underTest, subject); + } + + protected void verifyDeserialization(Object deserialized, T subject) { + assertThat(deserialized).isEqualTo(subject); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/BUILD b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/BUILD new file mode 100644 index 0000000000..4111713cbd --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/BUILD @@ -0,0 +1,63 @@ +TEST_BASE_FILES = [ + "AbstractObjectCodecTest.java", + "TestUtils.java", +] + +java_library( + name = "serialization-test-base", + testonly = 1, + srcs = TEST_BASE_FILES, + visibility = [ + "//src/test/java/com/google/devtools/build/lib:__subpackages__", + ], + deps = [ + "//src/main/java/com/google/devtools/build/lib/skyframe/serialization", + "//third_party:guava", + "//third_party:jsr305", + "//third_party:junit4", + "//third_party:truth", + "//third_party/protobuf:protobuf_java", + ], +) + +java_library( + name = "serialization-tests", + testonly = 1, + srcs = glob( + [ + "*.java", + ], + exclude = TEST_BASE_FILES, + ), + deps = [ + ":serialization-test-base", + "//src/main/java/com/google/devtools/build/lib:build-base", + "//src/main/java/com/google/devtools/build/lib:packages-internal", + "//src/main/java/com/google/devtools/build/lib:util", + "//src/main/java/com/google/devtools/build/lib:vfs", + "//src/main/java/com/google/devtools/build/lib/skyframe/serialization", + "//third_party:guava", + "//third_party:guava-testlib", + "//third_party:jsr305", + "//third_party:junit4", + "//third_party:mockito", + "//third_party:truth", + ], +) + +java_test( + name = "SerializationTests", + test_class = "com.google.devtools.build.lib.AllTests", + runtime_deps = [ + ":serialization-tests", + "//src/test/java/com/google/devtools/build/lib:test_runner", + ], +) + +filegroup( + name = "srcs", + srcs = glob(["**"]), + visibility = [ + "//src/test/java/com/google/devtools/build/lib/skyframe:__subpackages__", + ], +) diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/EnumCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/EnumCodecTest.java new file mode 100644 index 0000000000..c71d554b5b --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/EnumCodecTest.java @@ -0,0 +1,33 @@ +// Copyright 2017 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.skyframe.serialization; + +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link EnumCodec}. */ +@RunWith(JUnit4.class) +public class EnumCodecTest extends AbstractObjectCodecTest<EnumCodecTest.DummyEnum> { + + /** Test enum (dummy comment for lint). */ + public enum DummyEnum { + DUMB_ONE, + DUMB_TWO + } + + public EnumCodecTest() { + super(new EnumCodec<>(DummyEnum.class), DummyEnum.DUMB_ONE, DummyEnum.DUMB_TWO); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/FastStringCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/FastStringCodecTest.java new file mode 100644 index 0000000000..6aef73edd6 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/FastStringCodecTest.java @@ -0,0 +1,53 @@ +// Copyright 2017 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.skyframe.serialization; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link FastStringCodec}. */ +@RunWith(JUnit4.class) +public class FastStringCodecTest extends AbstractObjectCodecTest<String> { + + public FastStringCodecTest() { + super( + new FastStringCodec(), + "ow now brown cow. ow now brown cow", + "(╯°□°)╯︵┻━┻ string with utf8/ascii", + "string with ascii/utf8 (╯°□°)╯︵┻━┻", + "last character utf8 ╯", + "last char only non-ascii ƒ", + "ƒ", + "╯", + "", + Character.toString((char) 0xc3));; + } + + // hashCode is stored in String. Because we're using Unsafe to bypass standard String + // constructors, make sure it still works. + @Test + public void testEqualsAndHashCodePreserved() throws Exception { + String original1 = "hello world"; + String original2 = "dlrow olleh"; + + // Equals tester tests equals and hash code. + new EqualsTester() + .addEqualityGroup(original1, fromBytes(toBytes(original1))) + .addEqualityGroup(original2, fromBytes(toBytes(original2))) + .testEquals(); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/ImmutableListCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/ImmutableListCodecTest.java new file mode 100644 index 0000000000..23f38557e2 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/ImmutableListCodecTest.java @@ -0,0 +1,33 @@ +// Copyright 2017 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.skyframe.serialization; + +import com.google.common.collect.ImmutableList; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link ImmutableListCodec}. */ +@RunWith(JUnit4.class) +public class ImmutableListCodecTest extends AbstractObjectCodecTest<ImmutableList<String>> { + + @SuppressWarnings("unchecked") + public ImmutableListCodecTest() { + super( + new ImmutableListCodec<>(new StringCodec()), + ImmutableList.of(), + ImmutableList.of("foo"), + ImmutableList.of("bar", "baz")); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/LabelCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/LabelCodecTest.java new file mode 100644 index 0000000000..4dc1b14bf2 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/LabelCodecTest.java @@ -0,0 +1,29 @@ +// Copyright 2017 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.skyframe.serialization; + +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.cmdline.LabelSyntaxException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Basic tests for {@link LabelCodec}. */ +@RunWith(JUnit4.class) +public class LabelCodecTest extends AbstractObjectCodecTest<Label> { + + public LabelCodecTest() throws LabelSyntaxException { + super(new LabelCodec(), Label.parseAbsolute("//foo/bar:baz")); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PackageIdentifierCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PackageIdentifierCodecTest.java new file mode 100644 index 0000000000..9bc860af02 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PackageIdentifierCodecTest.java @@ -0,0 +1,30 @@ +// Copyright 2017 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.skyframe.serialization; + +import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import com.google.devtools.build.lib.vfs.PathFragment; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Basic tests for {@link PackageIdentifierCodec}. */ +@RunWith(JUnit4.class) +public class PackageIdentifierCodecTest extends AbstractObjectCodecTest<PackageIdentifier> { + + public PackageIdentifierCodecTest() throws Exception { + super( + new PackageIdentifierCodec(), PackageIdentifier.create("@foo", PathFragment.create("bar"))); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PathFragmentCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PathFragmentCodecTest.java new file mode 100644 index 0000000000..4ce91f849c --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PathFragmentCodecTest.java @@ -0,0 +1,28 @@ +// Copyright 2017 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.skyframe.serialization; + +import com.google.devtools.build.lib.vfs.PathFragment; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Basic tests for {@link PathFragmentCodec}. */ +@RunWith(JUnit4.class) +public class PathFragmentCodecTest extends AbstractObjectCodecTest<PathFragment> { + + public PathFragmentCodecTest() { + super(new PathFragmentCodec(), PathFragment.create("/a/path/fragment/with/lots/of/parts")); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/RepositoryNameCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/RepositoryNameCodecTest.java new file mode 100644 index 0000000000..97e38edc1c --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/RepositoryNameCodecTest.java @@ -0,0 +1,54 @@ +// Copyright 2017 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.skyframe.serialization; + +import static org.junit.Assert.fail; + +import com.google.devtools.build.lib.cmdline.LabelSyntaxException; +import com.google.devtools.build.lib.cmdline.RepositoryName; +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link RepositoryNameCodec}. */ +@RunWith(JUnit4.class) +public class RepositoryNameCodecTest extends AbstractObjectCodecTest<RepositoryName> { + + // Set 0th byte (isMain) false, so that we'll try to read a string from the rest of the + // data and fail. + public static final byte[] INVALID_ENCODED_REPOSITORY_NAME = new byte[] {0, 10, 9, 8, 7}; + + public RepositoryNameCodecTest() throws LabelSyntaxException { + super( + new RepositoryNameCodec(), + RepositoryName.create(RepositoryName.DEFAULT.getName()), + RepositoryName.create(RepositoryName.MAIN.getName()), + RepositoryName.create("@externalandshouldntexistinthisworkspace")); + } + + // The default bad data test from AbstractObjectCodecTest doesn't play nice with boolean prefixed + // encodings. + @Override + @Test + public void testDeserializeBadDataThrowsSerializationException() { + try { + fromBytes(INVALID_ENCODED_REPOSITORY_NAME); + fail("Expected exception"); + } catch (SerializationException | IOException e) { + // Expected. + } + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/StringCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/StringCodecTest.java new file mode 100644 index 0000000000..423ffdca3d --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/StringCodecTest.java @@ -0,0 +1,27 @@ +// Copyright 2017 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.skyframe.serialization; + +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Basic tests for {@link StringCodec}. */ +@RunWith(JUnit4.class) +public class StringCodecTest extends AbstractObjectCodecTest<String> { + + public StringCodecTest() { + super(new StringCodec(), "usually precomputed and supports weird unicodes: (╯°□°)╯︵┻━┻ "); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/TestUtils.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/TestUtils.java new file mode 100644 index 0000000000..df84b38479 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/TestUtils.java @@ -0,0 +1,42 @@ +// Copyright 2017 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.skyframe.serialization; + +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** Helpers for serialization tests. */ +class TestUtils { + + private TestUtils() {} + + /** Serialize a value to a new byte array. */ + static <T> byte[] toBytes(ObjectCodec<T> codec, T value) + throws IOException, SerializationException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + CodedOutputStream codedOut = CodedOutputStream.newInstance(bytes); + codec.serialize(value, codedOut); + codedOut.flush(); + return bytes.toByteArray(); + } + + /** Deserialize a value from a byte array. */ + static <T> T fromBytes(ObjectCodec<T> codec, byte[] bytes) + throws SerializationException, IOException { + return codec.deserialize(CodedInputStream.newInstance(bytes)); + } +} |