/* * 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 com.facebook.buck.rules.AddToRuleKey; import com.facebook.buck.rules.BuildRule; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.FakeBuildRule; import com.facebook.buck.rules.RuleKey; import com.facebook.buck.rules.RuleKeyAppendable; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.util.cache.NullFileHashCache; import java.util.HashMap; import java.util.Map; import org.junit.Assert; import org.junit.Test; public class RuleKeyDiagnosticsTest { @Test public void testTraversal() { SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder( new BuildRuleResolver( TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer())); SourcePathResolver sourcePathResolver = new SourcePathResolver(ruleFinder); RuleKeyAppendable app0 = sink -> sink.setReflectively("k0", "v0"); RuleKeyAppendable app1 = sink -> sink.setReflectively("k1", "v1"); RuleKeyAppendable app2 = sink -> sink.setReflectively("k2", "v2").setReflectively("k20", app0); RuleKeyAppendable app3 = sink -> sink.setReflectively("k3", "v3").setReflectively("k30", app0); RuleKeyAppendable app4 = sink -> sink.setReflectively("k42", app2).setReflectively("k43", app3); BuildRule dep1 = new FakeBuildRule("//fake:dep1"); BuildRule dep2 = new FakeBuildRule("//fake:dep2") { @AddToRuleKey RuleKeyAppendable a4 = app4; }; BuildRule rule1 = new FakeBuildRule("//fake:rule1", dep1, dep2) { @AddToRuleKey RuleKeyAppendable a1 = app1; @AddToRuleKey RuleKeyAppendable a4 = app4; }; RuleKeyFactoryWithDiagnostics<RuleKey> factory = new DefaultRuleKeyFactory(0, new NullFileHashCache(), sourcePathResolver, ruleFinder); RuleKeyDiagnostics<RuleKey, String> ruleKeyDiagnostics1 = new RuleKeyDiagnostics<>( rule -> factory.buildForDiagnostics(rule, new StringRuleKeyHasher()), appendable -> factory.buildForDiagnostics(appendable, new StringRuleKeyHasher())); Map<RuleKey, String> diagKeys1 = new HashMap<>(); { Map<RuleKey, Integer> count11 = new HashMap<>(); ruleKeyDiagnostics1.processRule( dep2, result -> { diagKeys1.put(result.ruleKey, result.diagKey); count11.put(result.ruleKey, 1 + count11.getOrDefault(result.ruleKey, 0)); }); // elements {dep2, app4, app3, app2, app0}, each visited once Assert.assertEquals( "Unexpected invocation count: " + count11, 5, count11.values().stream().mapToInt(c -> c).sum()); } { Map<RuleKey, Integer> count12 = new HashMap<>(); ruleKeyDiagnostics1.processRule( rule1, result -> { diagKeys1.put(result.ruleKey, result.diagKey); count12.put(result.ruleKey, 1 + count12.getOrDefault(result.ruleKey, 0)); }); // only new elements {rule1, app1}, each visited once Assert.assertEquals( "Unexpected invocation count: " + count12, 2, count12.values().stream().mapToInt(c -> c).sum()); } // now visit rules in different order RuleKeyDiagnostics<RuleKey, String> ruleKeyDiagnostics2 = new RuleKeyDiagnostics<>( rule -> factory.buildForDiagnostics(rule, new StringRuleKeyHasher()), appendable -> factory.buildForDiagnostics(appendable, new StringRuleKeyHasher())); Map<RuleKey, String> diagKeys2 = new HashMap<>(); { Map<RuleKey, Integer> count21 = new HashMap<>(); ruleKeyDiagnostics2.processRule( rule1, result -> { diagKeys2.put(result.ruleKey, result.diagKey); count21.put(result.ruleKey, 1 + count21.getOrDefault(result.ruleKey, 0)); }); // elements {rule1, app4, app3, app2, app1, app0}, each visited once Assert.assertEquals( "Unexpected invocation count: " + count21, 6, count21.values().stream().mapToInt(c -> c).sum()); } { Map<RuleKey, Integer> count22 = new HashMap<>(); ruleKeyDiagnostics2.processRule( dep2, result -> { diagKeys2.put(result.ruleKey, result.diagKey); count22.put(result.ruleKey, 1 + count22.getOrDefault(result.ruleKey, 0)); }); // only new elements {dep2}, each visited once Assert.assertEquals( "Unexpected invocation count: " + count22, 1, count22.values().stream().mapToInt(c -> c).sum()); } Assert.assertEquals(diagKeys1, diagKeys2); } }