/* * Copyright 2017-present Facebook, Inc. * * 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.facebook.buck.rules.keys; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import com.facebook.buck.io.ArchiveMemberPath; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.rules.BuildRuleType; import com.facebook.buck.rules.DefaultBuildTargetSourcePath; import com.facebook.buck.rules.RuleKey; import com.facebook.buck.rules.SourceRoot; import com.facebook.buck.util.sha1.Sha1HashCode; import com.google.common.hash.HashCode; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.junit.Test; public abstract class AbstractRuleKeyHasherTest<HASH> { private static final RuleKey RULE_KEY_1 = new RuleKey("a002b39af204cdfaa5fdb67816b13867c32ac52c"); private static final RuleKey RULE_KEY_2 = new RuleKey("b67816b13867c32ac52ca002b39af204cdfaa5fd"); private static final BuildTarget TARGET_1 = BuildTargetFactory.newInstance(Paths.get("/root"), "//example/base:one"); private static final BuildTarget TARGET_2 = BuildTargetFactory.newInstance(Paths.get("/root"), "//example/base:one#flavor"); protected Number[] getNumbersForUniquenessTest() { return new Number[] { /* int */ 0, /* int */ 42, (long) 0, (long) 42, (short) 0, (short) 42, (byte) 0, (byte) 42, (float) 0, (float) 42, (double) 0, (double) 42, }; } @Test public void testUniqueness() { List<HASH> hashes = new ArrayList<>(); hashes.add(newHasher().hash()); hashes.add(newHasher().putKey("").hash()); hashes.add(newHasher().putKey("42").hash()); hashes.add(newHasher().putKey("4").putKey("2").hash()); hashes.add(newHasher().putNull().hash()); hashes.add(newHasher().putBoolean(true).hash()); hashes.add(newHasher().putBoolean(false).hash()); for (Number number : getNumbersForUniquenessTest()) { hashes.add(newHasher().putNumber(number).hash()); } hashes.add(newHasher().putString("").hash()); hashes.add(newHasher().putString("42").hash()); hashes.add(newHasher().putString("4").putString("2").hash()); hashes.add(newHasher().putBytes(new byte[0]).hash()); hashes.add(newHasher().putBytes(new byte[] {42}).hash()); hashes.add(newHasher().putBytes(new byte[] {42, 42}).hash()); hashes.add(newHasher().putPattern(Pattern.compile("")).hash()); hashes.add(newHasher().putPattern(Pattern.compile("42")).hash()); hashes.add( newHasher().putPattern(Pattern.compile("4")).putPattern(Pattern.compile("2")).hash()); hashes.add( newHasher().putSha1(Sha1HashCode.of("a002b39af204cdfaa5fdb67816b13867c32ac52c")).hash()); hashes.add( newHasher().putSha1(Sha1HashCode.of("b67816b13867c32ac52ca002b39af204cdfaa5fd")).hash()); hashes.add(newHasher().putPath(Paths.get(""), HashCode.fromInt(0)).hash()); hashes.add(newHasher().putPath(Paths.get(""), HashCode.fromInt(42)).hash()); hashes.add(newHasher().putPath(Paths.get("42"), HashCode.fromInt(0)).hash()); hashes.add(newHasher().putPath(Paths.get("42"), HashCode.fromInt(42)).hash()); hashes.add(newHasher().putPath(Paths.get("42/42"), HashCode.fromInt(42)).hash()); hashes.add( newHasher().putArchiveMemberPath(newArchiveMember("", ""), HashCode.fromInt(0)).hash()); hashes.add( newHasher().putArchiveMemberPath(newArchiveMember("", ""), HashCode.fromInt(42)).hash()); hashes.add( newHasher().putArchiveMemberPath(newArchiveMember("42", "42"), HashCode.fromInt(0)).hash()); hashes.add( newHasher() .putArchiveMemberPath(newArchiveMember("42", "42"), HashCode.fromInt(42)) .hash()); hashes.add( newHasher() .putArchiveMemberPath(newArchiveMember("42/42", "42/42"), HashCode.fromInt(42)) .hash()); hashes.add(newHasher().putNonHashingPath("").hash()); hashes.add(newHasher().putNonHashingPath("42").hash()); hashes.add(newHasher().putNonHashingPath("4").putNonHashingPath("2").hash()); hashes.add(newHasher().putSourceRoot(new SourceRoot("")).hash()); hashes.add(newHasher().putSourceRoot(new SourceRoot("42")).hash()); hashes.add( newHasher().putSourceRoot(new SourceRoot("4")).putSourceRoot(new SourceRoot("2")).hash()); hashes.add(newHasher().putRuleKey(RULE_KEY_1).hash()); hashes.add(newHasher().putRuleKey(RULE_KEY_2).hash()); hashes.add(newHasher().putBuildRuleType(BuildRuleType.of("")).hash()); hashes.add(newHasher().putBuildRuleType(BuildRuleType.of("42")).hash()); hashes.add( newHasher() .putBuildRuleType(BuildRuleType.of("4")) .putBuildRuleType(BuildRuleType.of("2")) .hash()); hashes.add(newHasher().putBuildTarget(TARGET_1).hash()); hashes.add(newHasher().putBuildTarget(TARGET_2).hash()); hashes.add( newHasher().putBuildTargetSourcePath(new DefaultBuildTargetSourcePath(TARGET_1)).hash()); hashes.add( newHasher().putBuildTargetSourcePath(new DefaultBuildTargetSourcePath(TARGET_2)).hash()); hashes.add(newHasher().putContainer(RuleKeyHasher.Container.LIST, 0).hash()); hashes.add(newHasher().putContainer(RuleKeyHasher.Container.LIST, 42).hash()); hashes.add(newHasher().putContainer(RuleKeyHasher.Container.MAP, 0).hash()); hashes.add(newHasher().putContainer(RuleKeyHasher.Container.MAP, 42).hash()); hashes.add(newHasher().putWrapper(RuleKeyHasher.Wrapper.SUPPLIER).hash()); hashes.add(newHasher().putWrapper(RuleKeyHasher.Wrapper.OPTIONAL).hash()); hashes.add(newHasher().putWrapper(RuleKeyHasher.Wrapper.EITHER_LEFT).hash()); hashes.add(newHasher().putWrapper(RuleKeyHasher.Wrapper.EITHER_RIGHT).hash()); hashes.add(newHasher().putWrapper(RuleKeyHasher.Wrapper.BUILD_RULE).hash()); hashes.add(newHasher().putWrapper(RuleKeyHasher.Wrapper.APPENDABLE).hash()); // all of the hashes should be different for (int i = 0; i < hashes.size(); i++) { for (int j = 0; j < i; j++) { assertNotEquals(String.format("Collision [%d] = [%d]", i, j), hashes.get(i), hashes.get(j)); } } } @Test public void testConsistency() { // same sequence of operations should produce the same hash assertEquals(newHasher().hash(), newHasher().hash()); assertEquals(newHasher().putKey("abc").hash(), newHasher().putKey("abc").hash()); assertEquals(newHasher().putNull().hash(), newHasher().putNull().hash()); assertEquals(newHasher().putBoolean(false).hash(), newHasher().putBoolean(false).hash()); assertEquals(newHasher().putBoolean(true).hash(), newHasher().putBoolean(true).hash()); assertEquals(newHasher().putNumber(4).hash(), newHasher().putNumber(4).hash()); assertEquals(newHasher().putNumber((long) 4).hash(), newHasher().putNumber((long) 4).hash()); assertEquals(newHasher().putNumber((short) 4).hash(), newHasher().putNumber((short) 4).hash()); assertEquals(newHasher().putNumber((byte) 4).hash(), newHasher().putNumber((byte) 4).hash()); assertEquals(newHasher().putNumber((float) 4).hash(), newHasher().putNumber((float) 4).hash()); assertEquals( newHasher().putNumber((double) 4).hash(), newHasher().putNumber((double) 4).hash()); assertEquals( newHasher().putBytes(new byte[] {42}).hash(), newHasher().putBytes(new byte[] {42}).hash()); assertEquals( newHasher().putPattern(Pattern.compile("42")).hash(), newHasher().putPattern(Pattern.compile("42")).hash()); assertEquals( newHasher().putPath(Paths.get("42/42"), HashCode.fromInt(42)).hash(), newHasher().putPath(Paths.get("42/42"), HashCode.fromInt(42)).hash()); assertEquals( newHasher() .putArchiveMemberPath(newArchiveMember("42/42", "42/42"), HashCode.fromInt(42)) .hash(), newHasher() .putArchiveMemberPath(newArchiveMember("42/42", "42/42"), HashCode.fromInt(42)) .hash()); assertEquals( newHasher().putNonHashingPath("42").hash(), newHasher().putNonHashingPath("42").hash()); assertEquals( newHasher().putSourceRoot(new SourceRoot("42")).hash(), newHasher().putSourceRoot(new SourceRoot("42")).hash()); assertEquals( newHasher().putRuleKey(RULE_KEY_1).hash(), newHasher().putRuleKey(RULE_KEY_1).hash()); assertEquals( newHasher().putBuildRuleType(BuildRuleType.of("42")).hash(), newHasher().putBuildRuleType(BuildRuleType.of("42")).hash()); assertEquals( newHasher().putBuildTarget(TARGET_1).hash(), newHasher().putBuildTarget(TARGET_1).hash()); assertEquals( newHasher().putBuildTargetSourcePath(new DefaultBuildTargetSourcePath(TARGET_1)).hash(), newHasher().putBuildTargetSourcePath(new DefaultBuildTargetSourcePath(TARGET_1)).hash()); } protected ArchiveMemberPath newArchiveMember(String archivePath, String memberPath) { return ArchiveMemberPath.of(Paths.get(archivePath), Paths.get(memberPath)); } protected abstract RuleKeyHasher<HASH> newHasher(); }