diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/BazelProfilePhase.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/BazelProfilePhase.java index 0534f65..ed86406 100644 --- a/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/BazelProfilePhase.java +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/BazelProfilePhase.java @@ -17,10 +17,14 @@ public enum BazelProfilePhase { // The order of these is important, it reflects in which order we expect the timestamps of the // phases markers in the Bazel profile to be. + // Names taken from + // https://github.com/bazelbuild/bazel/blob/febfa54dbe62d719ad6dbbfdd12bd6f8c0923b7a/src/main/java/com/google/devtools/build/lib/profiler/ProfilePhase.java#L20-L32 LAUNCH("Launch Blaze"), INIT("Initialize command"), - EVALUATE("Evaluate target patterns"), - DEPENDENCIES("Load and analyze dependencies"), + TARGET_PATTERN_EVAL("Evaluate target patterns"), + ANALYZE("Load and analyze dependencies"), + ANALYZE_AND_EXECUTE("Load, analyze dependencies and build artifacts"), + LICENSE("Analyze licenses"), PREPARE("Prepare for build"), EXECUTE("Build artifacts"), FINISH("Complete build"); diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProvider.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProvider.java index bdecf53..f1dfc1b 100644 --- a/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProvider.java +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProvider.java @@ -103,7 +103,7 @@ EstimatedJobsFlagValue getEstimatedFlagValueJobs() if (evaluateAndDependenciesPhaseSkyframeEvaluators == null) { return new EstimatedJobsFlagValue(ESTIMATED_JOBS_FLAG_VALUE_EMPTY_REASON_EVAL_DEP_MISSING); } - if (executionPhaseSkyframeEvaluators == null + if (executionPhaseSkyframeEvaluatorsMaxValue == null || evaluateAndDependenciesPhaseSkyframeEvaluatorsMaxValue == null) { return new EstimatedJobsFlagValue(ESTIMATED_JOBS_FLAG_VALUE_EMPTY_REASON_EVENTS_MISSING); } @@ -171,13 +171,13 @@ private synchronized void determineEstimatedCoresAvailable() // phases. These phases should use as many cores as there are available, irrespective of // whether the Bazel flag `--jobs` is set or not. Optional start = - bazelPhaseDescriptions.has(BazelProfilePhase.EVALUATE) - ? bazelPhaseDescriptions.get(BazelProfilePhase.EVALUATE) - : bazelPhaseDescriptions.get(BazelProfilePhase.DEPENDENCIES); + bazelPhaseDescriptions.has(BazelProfilePhase.TARGET_PATTERN_EVAL) + ? bazelPhaseDescriptions.get(BazelProfilePhase.TARGET_PATTERN_EVAL) + : bazelPhaseDescriptions.get(BazelProfilePhase.ANALYZE); Optional end = - bazelPhaseDescriptions.has(BazelProfilePhase.DEPENDENCIES) - ? bazelPhaseDescriptions.get(BazelProfilePhase.DEPENDENCIES) - : bazelPhaseDescriptions.get(BazelProfilePhase.EVALUATE); + bazelPhaseDescriptions.has(BazelProfilePhase.ANALYZE) + ? bazelPhaseDescriptions.get(BazelProfilePhase.ANALYZE) + : bazelPhaseDescriptions.get(BazelProfilePhase.TARGET_PATTERN_EVAL); if (start.isEmpty() || end.isEmpty()) { // The profile does not include that data necessary. return; diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsed.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsed.java new file mode 100644 index 0000000..810b9d5 --- /dev/null +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsed.java @@ -0,0 +1,54 @@ +/* + * Copyright 2023 EngFlow 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.engflow.bazel.invocation.analyzer.dataproviders; + +import com.engflow.bazel.invocation.analyzer.core.Datum; + +/** + * Whether evidence was found that Skymeld was used. + * + * @see Project Skymeld GitHub issue + */ +public class SkymeldUsed implements Datum { + private final boolean skymeldUsed; + + public SkymeldUsed(boolean skymeldUsed) { + this.skymeldUsed = skymeldUsed; + } + + public boolean isSkymeldUsed() { + return skymeldUsed; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public String getEmptyReason() { + return null; + } + + @Override + public String getDescription() { + return "Whether the Bazel Profile includes events indicating that Skymeld was used."; + } + + @Override + public String getSummary() { + return String.valueOf(skymeldUsed); + } +} diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsedDataProvider.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsedDataProvider.java new file mode 100644 index 0000000..8692d26 --- /dev/null +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsedDataProvider.java @@ -0,0 +1,50 @@ +/* + * Copyright 2022 EngFlow 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.engflow.bazel.invocation.analyzer.dataproviders; + +import com.engflow.bazel.invocation.analyzer.bazelprofile.BazelProfilePhase; +import com.engflow.bazel.invocation.analyzer.core.DataProvider; +import com.engflow.bazel.invocation.analyzer.core.DatumSupplier; +import com.engflow.bazel.invocation.analyzer.core.DatumSupplierSpecification; +import com.engflow.bazel.invocation.analyzer.core.InvalidProfileException; +import com.engflow.bazel.invocation.analyzer.core.MissingInputException; +import com.engflow.bazel.invocation.analyzer.core.NullDatumException; +import com.google.common.annotations.VisibleForTesting; +import java.util.List; + +/** + * A {@link DataProvider} that returns whether the profile looks like it was generated while using + * Skymeld. + * + * @see Project Skymeld GitHub issue + */ +public class SkymeldUsedDataProvider extends DataProvider { + + @Override + public List> getSuppliers() { + return List.of( + DatumSupplierSpecification.of( + SkymeldUsed.class, DatumSupplier.memoized(this::getSkymeldUsed))); + } + + @VisibleForTesting + SkymeldUsed getSkymeldUsed() + throws InvalidProfileException, MissingInputException, NullDatumException { + BazelPhaseDescriptions bazelPhaseDescriptions = + getDataManager().getDatum(BazelPhaseDescriptions.class); + return new SkymeldUsed( + bazelPhaseDescriptions.get(BazelProfilePhase.ANALYZE_AND_EXECUTE).isPresent()); + } +} diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/suggestionproviders/NegligiblePhaseSuggestionProvider.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/suggestionproviders/NegligiblePhaseSuggestionProvider.java index d69787b..dc1921a 100644 --- a/analyzer/java/com/engflow/bazel/invocation/analyzer/suggestionproviders/NegligiblePhaseSuggestionProvider.java +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/suggestionproviders/NegligiblePhaseSuggestionProvider.java @@ -54,7 +54,10 @@ public class NegligiblePhaseSuggestionProvider extends SuggestionProviderBase { @VisibleForTesting public static final List NON_NEGLIGIBLE_PHASES = List.of( - BazelProfilePhase.EVALUATE, BazelProfilePhase.DEPENDENCIES, BazelProfilePhase.EXECUTE); + BazelProfilePhase.TARGET_PATTERN_EVAL, + BazelProfilePhase.ANALYZE, + BazelProfilePhase.ANALYZE_AND_EXECUTE, + BazelProfilePhase.EXECUTE); // Don't apply this check to profiles shorter than this duration private static final Duration MIN_DURATION = Duration.ofSeconds(30); // Non-negligible phases should be less than this percentage of total duration (1.0 = 1%) diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/ProfileTestBase.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/ProfileTestBase.java index 95a2570..429bbc8 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/ProfileTestBase.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/ProfileTestBase.java @@ -34,6 +34,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; import org.junit.After; import org.junit.BeforeClass; @@ -122,78 +123,37 @@ protected BazelProfile useProfile(WriteBazelProfile.ProfileSection... profileSec /** * Create the Bazel profile events that establish the phases of invocation processing. For a valid - * profile, at least launchStart and finishTime have to be non-null. + * profile, at least {@link BazelProfilePhase#LAUNCH} has to be included in `startTimes`, and + * `finishTime` has to be non-null. * - * @param launchStart timestamp of the Launch Blaze event - * @param initStart timestamp of the Initialize command event - * @param evalStart timestamp of the Evaluate target patterns event - * @param depStart timestamp of the Load and analyze dependencies event - * @param prepStart timestamp of the Prepare for build event - * @param execStart timestamp of the Build artifacts event - * @param finishStart timestamp of the Complete build event + * @param startTimes map of start times of the Bazel profile phases to include * @param finishTime timestamp of the Finishing event * @return array of phase marker events */ protected WriteBazelProfile.ThreadEvent[] createPhaseEvents( - @Nullable Timestamp launchStart, - @Nullable Timestamp initStart, - @Nullable Timestamp evalStart, - @Nullable Timestamp depStart, - @Nullable Timestamp prepStart, - @Nullable Timestamp execStart, - @Nullable Timestamp finishStart, - @Nullable Timestamp finishTime) { + Map startTimes, @Nullable Timestamp finishTime) { List threadEvents = new ArrayList<>(); - if (launchStart != null) { - threadEvents.add( - complete( - BazelProfilePhase.LAUNCH.name, - BazelProfileConstants.CAT_BUILD_PHASE_MARKER, - launchStart, - TimeUtil.getDurationBetween( - launchStart, initStart == null ? Timestamp.ofMicros(0) : initStart))); - } - if (initStart != null) { - threadEvents.add( - instant( - BazelProfilePhase.INIT.name, - BazelProfileConstants.CAT_BUILD_PHASE_MARKER, - initStart)); - } - if (evalStart != null) { - threadEvents.add( - instant( - BazelProfilePhase.EVALUATE.name, - BazelProfileConstants.CAT_BUILD_PHASE_MARKER, - evalStart)); - } - if (depStart != null) { - threadEvents.add( - instant( - BazelProfilePhase.DEPENDENCIES.name, - BazelProfileConstants.CAT_BUILD_PHASE_MARKER, - depStart)); - } - if (prepStart != null) { - threadEvents.add( - instant( - BazelProfilePhase.PREPARE.name, - BazelProfileConstants.CAT_BUILD_PHASE_MARKER, - prepStart)); - } - if (execStart != null) { - threadEvents.add( - instant( - BazelProfilePhase.EXECUTE.name, - BazelProfileConstants.CAT_BUILD_PHASE_MARKER, - execStart)); - } - if (finishStart != null) { - threadEvents.add( - instant( - BazelProfilePhase.FINISH.name, - BazelProfileConstants.CAT_BUILD_PHASE_MARKER, - finishStart)); + for (var entry : startTimes.entrySet()) { + switch (entry.getKey()) { + case LAUNCH: + threadEvents.add( + complete( + entry.getKey().name, + BazelProfileConstants.CAT_BUILD_PHASE_MARKER, + entry.getValue(), + TimeUtil.getDurationBetween( + entry.getValue(), + startTimes.containsKey(BazelProfilePhase.INIT) + ? startTimes.get(BazelProfilePhase.INIT) + : Timestamp.ofMicros(0)))); + break; + default: + threadEvents.add( + instant( + entry.getKey().name, + BazelProfileConstants.CAT_BUILD_PHASE_MARKER, + entry.getValue())); + } } if (finishTime != null) { threadEvents.add( diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhaseDescriptionsTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhaseDescriptionsTest.java index 7dd48cc..f38649b 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhaseDescriptionsTest.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhaseDescriptionsTest.java @@ -26,8 +26,10 @@ public void getOrClosestBeforeShouldReturnSelf() { BazelPhaseDescription description = new BazelPhaseDescription(Timestamp.ofMicros(1), Timestamp.ofMicros(2)); BazelPhaseDescriptions descriptions = - BazelPhaseDescriptions.newBuilder().add(BazelProfilePhase.EVALUATE, description).build(); - assertThat(descriptions.getOrClosestBefore(BazelProfilePhase.EVALUATE).get()) + BazelPhaseDescriptions.newBuilder() + .add(BazelProfilePhase.TARGET_PATTERN_EVAL, description) + .build(); + assertThat(descriptions.getOrClosestBefore(BazelProfilePhase.TARGET_PATTERN_EVAL).get()) .isEqualTo(description); } @@ -40,17 +42,18 @@ public void getOrClosestBeforeShouldReturnEarlier() { BazelPhaseDescriptions descriptions = BazelPhaseDescriptions.newBuilder() .add(BazelProfilePhase.INIT, otherDescription) - .add(BazelProfilePhase.EVALUATE, expectedDescription) + .add(BazelProfilePhase.TARGET_PATTERN_EVAL, expectedDescription) .add(BazelProfilePhase.PREPARE, otherDescription) .build(); - assertThat(descriptions.getOrClosestBefore(BazelProfilePhase.DEPENDENCIES).get()) + assertThat(descriptions.getOrClosestBefore(BazelProfilePhase.ANALYZE).get()) .isEqualTo(expectedDescription); } @Test public void getOrClosestBeforeShouldReturnEmpty() { BazelPhaseDescriptions descriptions = BazelPhaseDescriptions.newBuilder().build(); - assertThat(descriptions.getOrClosestBefore(BazelProfilePhase.EVALUATE).isEmpty()).isTrue(); + assertThat(descriptions.getOrClosestBefore(BazelProfilePhase.TARGET_PATTERN_EVAL).isEmpty()) + .isTrue(); } @Test @@ -58,8 +61,10 @@ public void getOrClosestAfterShouldReturnSelf() { BazelPhaseDescription description = new BazelPhaseDescription(Timestamp.ofMicros(1), Timestamp.ofMicros(2)); BazelPhaseDescriptions descriptions = - BazelPhaseDescriptions.newBuilder().add(BazelProfilePhase.EVALUATE, description).build(); - assertThat(descriptions.getOrClosestAfter(BazelProfilePhase.EVALUATE).get()) + BazelPhaseDescriptions.newBuilder() + .add(BazelProfilePhase.TARGET_PATTERN_EVAL, description) + .build(); + assertThat(descriptions.getOrClosestAfter(BazelProfilePhase.TARGET_PATTERN_EVAL).get()) .isEqualTo(description); } @@ -75,13 +80,14 @@ public void getOrClosestAfterShouldReturnLater() { .add(BazelProfilePhase.PREPARE, expectedDescription) .add(BazelProfilePhase.EXECUTE, otherDescription) .build(); - assertThat(descriptions.getOrClosestAfter(BazelProfilePhase.EVALUATE).get()) + assertThat(descriptions.getOrClosestAfter(BazelProfilePhase.TARGET_PATTERN_EVAL).get()) .isEqualTo(expectedDescription); } @Test public void getOrClosestAfterShouldReturnEmpty() { BazelPhaseDescriptions descriptions = BazelPhaseDescriptions.newBuilder().build(); - assertThat(descriptions.getOrClosestAfter(BazelProfilePhase.EVALUATE).isEmpty()).isTrue(); + assertThat(descriptions.getOrClosestAfter(BazelProfilePhase.TARGET_PATTERN_EVAL).isEmpty()) + .isTrue(); } } diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhasesDataProviderTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhasesDataProviderTest.java index 9078733..c0447b2 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhasesDataProviderTest.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelPhasesDataProviderTest.java @@ -25,6 +25,8 @@ import com.engflow.bazel.invocation.analyzer.core.InvalidProfileException; import com.engflow.bazel.invocation.analyzer.time.TimeUtil; import com.engflow.bazel.invocation.analyzer.time.Timestamp; +import java.util.HashMap; +import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -32,7 +34,8 @@ public class BazelPhasesDataProviderTest extends DataProviderUnitTestBase { private final Timestamp LAUNCH_START = Timestamp.ofMicros(-10_000); private final Timestamp INIT_START = Timestamp.ofMicros(0); private final Timestamp EVAL_START = Timestamp.ofMicros(20_000); - private final Timestamp DEP_START = Timestamp.ofMicros(50_000); + private final Timestamp ANALYZE_START = Timestamp.ofMicros(50_000); + private final Timestamp LICENSE_START = Timestamp.ofMicros(80_000); private final Timestamp PREP_START = Timestamp.ofMicros(90_000); private final Timestamp EXEC_START = Timestamp.ofMicros(140_000); private final Timestamp FINISH_START = Timestamp.ofMicros(200_000); @@ -48,7 +51,18 @@ public void setupTest() throws Exception { } @Test - public void getBazelPhaseDescriptionsShouldWorkWhenAllPhasesArePresent() throws Exception { + public void getBazelPhaseDescriptionsShouldWorkWhenAllPhasesArePresentWithoutSkymeld() + throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE, ANALYZE_START); + startTimes.put(BazelProfilePhase.LICENSE, LICENSE_START); + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + startTimes.put(BazelProfilePhase.EXECUTE, EXEC_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + useProfile( metaData(), trace( @@ -56,15 +70,7 @@ public void getBazelPhaseDescriptionsShouldWorkWhenAllPhasesArePresent() throws 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); BazelPhaseDescriptions descriptions = provider.getBazelPhaseDescriptions(); assertThat(descriptions.get(BazelProfilePhase.LAUNCH).get()) @@ -75,14 +81,18 @@ public void getBazelPhaseDescriptionsShouldWorkWhenAllPhasesArePresent() throws .isEqualTo( new BazelPhaseDescription( INIT_START, TimeUtil.getDurationBetween(INIT_START, EVAL_START))); - assertThat(descriptions.get(BazelProfilePhase.EVALUATE).get()) + assertThat(descriptions.get(BazelProfilePhase.TARGET_PATTERN_EVAL).get()) + .isEqualTo( + new BazelPhaseDescription( + EVAL_START, TimeUtil.getDurationBetween(EVAL_START, ANALYZE_START))); + assertThat(descriptions.get(BazelProfilePhase.ANALYZE).get()) .isEqualTo( new BazelPhaseDescription( - EVAL_START, TimeUtil.getDurationBetween(EVAL_START, DEP_START))); - assertThat(descriptions.get(BazelProfilePhase.DEPENDENCIES).get()) + ANALYZE_START, TimeUtil.getDurationBetween(ANALYZE_START, LICENSE_START))); + assertThat(descriptions.get(BazelProfilePhase.LICENSE).get()) .isEqualTo( new BazelPhaseDescription( - DEP_START, TimeUtil.getDurationBetween(DEP_START, PREP_START))); + LICENSE_START, TimeUtil.getDurationBetween(LICENSE_START, PREP_START))); assertThat(descriptions.get(BazelProfilePhase.PREPARE).get()) .isEqualTo( new BazelPhaseDescription( @@ -97,8 +107,60 @@ public void getBazelPhaseDescriptionsShouldWorkWhenAllPhasesArePresent() throws FINISH_START, TimeUtil.getDurationBetween(FINISH_START, FINISH_TIME))); } + @Test + public void getBazelPhaseDescriptionsShouldWorkWhenAllPhasesArePresentWithSkymeld() + throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE_AND_EXECUTE, ANALYZE_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + + useProfile( + metaData(), + trace( + thread( + 20, + 0, + BazelProfileConstants.THREAD_MAIN, + createPhaseEvents(startTimes, FINISH_TIME)))); + + BazelPhaseDescriptions descriptions = provider.getBazelPhaseDescriptions(); + assertThat(descriptions.get(BazelProfilePhase.LAUNCH).get()) + .isEqualTo( + new BazelPhaseDescription( + LAUNCH_START, TimeUtil.getDurationBetween(LAUNCH_START, INIT_START))); + assertThat(descriptions.get(BazelProfilePhase.INIT).get()) + .isEqualTo( + new BazelPhaseDescription( + INIT_START, TimeUtil.getDurationBetween(INIT_START, EVAL_START))); + assertThat(descriptions.get(BazelProfilePhase.TARGET_PATTERN_EVAL).get()) + .isEqualTo( + new BazelPhaseDescription( + EVAL_START, TimeUtil.getDurationBetween(EVAL_START, ANALYZE_START))); + assertThat(descriptions.get(BazelProfilePhase.ANALYZE_AND_EXECUTE).get()) + .isEqualTo( + new BazelPhaseDescription( + ANALYZE_START, TimeUtil.getDurationBetween(ANALYZE_START, FINISH_START))); + assertThat(descriptions.get(BazelProfilePhase.FINISH).get()) + .isEqualTo( + new BazelPhaseDescription( + FINISH_START, TimeUtil.getDurationBetween(FINISH_START, FINISH_TIME))); + } + @Test public void getBazelPhaseDescriptionsShouldWorkWhenSomePhasesAreMissing() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + startTimes.put(BazelProfilePhase.INIT, INIT_START); + // No BazelProfilePhase.TARGET_PATTERN_EVAL + // No BazelProfilePhase.ANALYZE + // No BazelProfilePhase.LICENSE + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + // No BazelProfilePhase.EXECUTE + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + useProfile( metaData(), trace( @@ -106,15 +168,7 @@ public void getBazelPhaseDescriptionsShouldWorkWhenSomePhasesAreMissing() throws 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - null, - null, - PREP_START, - null, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); BazelPhaseDescriptions descriptions = provider.getBazelPhaseDescriptions(); assertThat(descriptions.get(BazelProfilePhase.LAUNCH).get()) @@ -138,6 +192,9 @@ public void getBazelPhaseDescriptionsShouldWorkWhenSomePhasesAreMissing() throws @Test public void getBazelPhaseDescriptionsShouldWorkWhenAllButLaunchAndFinishPhaseAreMissing() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + useProfile( metaData(), trace( @@ -145,7 +202,7 @@ public void getBazelPhaseDescriptionsShouldWorkWhenAllButLaunchAndFinishPhaseAre 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents(LAUNCH_START, null, null, null, null, null, null, FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); BazelPhaseDescriptions descriptions = provider.getBazelPhaseDescriptions(); assertThat(descriptions.get(BazelProfilePhase.FINISH).get()) @@ -157,6 +214,16 @@ public void getBazelPhaseDescriptionsShouldWorkWhenAllButLaunchAndFinishPhaseAre @Test public void getBazelPhaseDescriptionsShouldThrowWhenTwoMarkersHaveTheSameTimestamp() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE, ANALYZE_START); + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + // Duplicate timestamp. + startTimes.put(BazelProfilePhase.EXECUTE, ANALYZE_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + useProfile( metaData(), trace( @@ -164,29 +231,28 @@ public void getBazelPhaseDescriptionsShouldThrowWhenTwoMarkersHaveTheSameTimesta 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - DEP_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); InvalidProfileException invalidProfileException = assertThrows(InvalidProfileException.class, () -> provider.getBazelPhaseDescriptions()); - assertThat(invalidProfileException) - .hasMessageThat() - .contains(BazelProfilePhase.DEPENDENCIES.name); + assertThat(invalidProfileException).hasMessageThat().contains(BazelProfilePhase.ANALYZE.name); assertThat(invalidProfileException).hasMessageThat().contains(BazelProfilePhase.EXECUTE.name); assertThat(invalidProfileException) .hasMessageThat() - .contains(String.valueOf(DEP_START.getMicros())); + .contains(String.valueOf(ANALYZE_START.getMicros())); } @Test public void getBazelPhaseDescriptionsShouldThrowWhenLaunchPhaseIsMissing() throws Exception { + Map startTimes = new HashMap<>(); + // No BazelProfilePhase.LAUNCH + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE, ANALYZE_START); + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + startTimes.put(BazelProfilePhase.EXECUTE, EXEC_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + useProfile( metaData(), trace( @@ -194,15 +260,7 @@ public void getBazelPhaseDescriptionsShouldThrowWhenLaunchPhaseIsMissing() throw 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - null, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); InvalidProfileException invalidProfileException = assertThrows(InvalidProfileException.class, () -> provider.getBazelPhaseDescriptions()); @@ -211,22 +269,19 @@ public void getBazelPhaseDescriptionsShouldThrowWhenLaunchPhaseIsMissing() throw @Test public void getBazelPhaseDescriptionsShouldThrowWhenFinishPhaseIsMissing() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE, ANALYZE_START); + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + startTimes.put(BazelProfilePhase.EXECUTE, EXEC_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + useProfile( metaData(), trace( - thread( - 20, - 0, - BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - null)))); + thread(20, 0, BazelProfileConstants.THREAD_MAIN, createPhaseEvents(startTimes, null)))); InvalidProfileException invalidProfileException = assertThrows(InvalidProfileException.class, () -> provider.getBazelPhaseDescriptions()); @@ -237,6 +292,16 @@ public void getBazelPhaseDescriptionsShouldThrowWhenFinishPhaseIsMissing() throw @Test public void getTotalDurationShouldWorkWhenAllPhasesArePresent() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE, ANALYZE_START); + startTimes.put(BazelProfilePhase.LICENSE, LICENSE_START); + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + startTimes.put(BazelProfilePhase.EXECUTE, EXEC_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + useProfile( metaData(), trace( @@ -244,15 +309,7 @@ public void getTotalDurationShouldWorkWhenAllPhasesArePresent() throws Exception 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); TotalDuration duration = provider.getTotalDuration(); assertThat(duration.getTotalDuration().isPresent()).isTrue(); @@ -263,6 +320,9 @@ public void getTotalDurationShouldWorkWhenAllPhasesArePresent() throws Exception @Test public void getTotalDurationShouldWorkWhenAllButLaunchAndFinishPhaseAreMissing() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + useProfile( metaData(), trace( @@ -270,7 +330,7 @@ public void getTotalDurationShouldWorkWhenAllButLaunchAndFinishPhaseAreMissing() 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents(LAUNCH_START, null, null, null, null, null, null, FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); TotalDuration duration = provider.getTotalDuration(); assertThat(duration.getTotalDuration().isPresent()).isTrue(); @@ -280,6 +340,16 @@ public void getTotalDurationShouldWorkWhenAllButLaunchAndFinishPhaseAreMissing() @Test public void getTotalDurationShouldThrowWhenLaunchPhasesIsMissing() throws Exception { + Map startTimes = new HashMap<>(); + // No BazelProfilePhase.LAUNCH + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE, ANALYZE_START); + startTimes.put(BazelProfilePhase.LICENSE, LICENSE_START); + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + startTimes.put(BazelProfilePhase.EXECUTE, EXEC_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); + useProfile( metaData(), trace( @@ -287,15 +357,7 @@ public void getTotalDurationShouldThrowWhenLaunchPhasesIsMissing() throws Except 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - null, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, FINISH_TIME)))); InvalidProfileException invalidProfileException = assertThrows(InvalidProfileException.class, () -> provider.getTotalDuration()); @@ -304,22 +366,18 @@ public void getTotalDurationShouldThrowWhenLaunchPhasesIsMissing() throws Except @Test public void getTotalDurationShouldThrowWhenFinishingPhaseIsMissing() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, LAUNCH_START); + startTimes.put(BazelProfilePhase.INIT, INIT_START); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, EVAL_START); + startTimes.put(BazelProfilePhase.ANALYZE, ANALYZE_START); + startTimes.put(BazelProfilePhase.PREPARE, PREP_START); + startTimes.put(BazelProfilePhase.EXECUTE, EXEC_START); + startTimes.put(BazelProfilePhase.FINISH, FINISH_START); useProfile( metaData(), trace( - thread( - 20, - 0, - BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - null)))); + thread(20, 0, BazelProfileConstants.THREAD_MAIN, createPhaseEvents(startTimes, null)))); InvalidProfileException invalidProfileException = assertThrows(InvalidProfileException.class, () -> provider.getTotalDuration()); diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelProfilePhaseTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelProfilePhaseTest.java index d46e2b7..e516d71 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelProfilePhaseTest.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/BazelProfilePhaseTest.java @@ -25,9 +25,15 @@ public class BazelProfilePhaseTest { public void getPreviousWorks() { assertThat(BazelProfilePhase.FINISH.getPrevious()).isEqualTo(BazelProfilePhase.EXECUTE); assertThat(BazelProfilePhase.EXECUTE.getPrevious()).isEqualTo(BazelProfilePhase.PREPARE); - assertThat(BazelProfilePhase.PREPARE.getPrevious()).isEqualTo(BazelProfilePhase.DEPENDENCIES); - assertThat(BazelProfilePhase.DEPENDENCIES.getPrevious()).isEqualTo(BazelProfilePhase.EVALUATE); - assertThat(BazelProfilePhase.EVALUATE.getPrevious()).isEqualTo(BazelProfilePhase.INIT); + assertThat(BazelProfilePhase.PREPARE.getPrevious()).isEqualTo(BazelProfilePhase.LICENSE); + assertThat(BazelProfilePhase.LICENSE.getPrevious()) + .isEqualTo(BazelProfilePhase.ANALYZE_AND_EXECUTE); + assertThat(BazelProfilePhase.ANALYZE_AND_EXECUTE.getPrevious()) + .isEqualTo(BazelProfilePhase.ANALYZE); + assertThat(BazelProfilePhase.ANALYZE.getPrevious()) + .isEqualTo(BazelProfilePhase.TARGET_PATTERN_EVAL); + assertThat(BazelProfilePhase.TARGET_PATTERN_EVAL.getPrevious()) + .isEqualTo(BazelProfilePhase.INIT); assertThat(BazelProfilePhase.INIT.getPrevious()).isEqualTo(BazelProfilePhase.LAUNCH); assertThrows(UnsupportedOperationException.class, () -> BazelProfilePhase.LAUNCH.getPrevious()); } @@ -35,9 +41,14 @@ public void getPreviousWorks() { @Test public void getNextWorks() { assertThat(BazelProfilePhase.LAUNCH.getNext()).isEqualTo(BazelProfilePhase.INIT); - assertThat(BazelProfilePhase.INIT.getNext()).isEqualTo(BazelProfilePhase.EVALUATE); - assertThat(BazelProfilePhase.EVALUATE.getNext()).isEqualTo(BazelProfilePhase.DEPENDENCIES); - assertThat(BazelProfilePhase.DEPENDENCIES.getNext()).isEqualTo(BazelProfilePhase.PREPARE); + assertThat(BazelProfilePhase.INIT.getNext()).isEqualTo(BazelProfilePhase.TARGET_PATTERN_EVAL); + assertThat(BazelProfilePhase.TARGET_PATTERN_EVAL.getNext()) + .isEqualTo(BazelProfilePhase.ANALYZE); + assertThat(BazelProfilePhase.ANALYZE.getNext()) + .isEqualTo(BazelProfilePhase.ANALYZE_AND_EXECUTE); + assertThat(BazelProfilePhase.ANALYZE_AND_EXECUTE.getNext()) + .isEqualTo(BazelProfilePhase.LICENSE); + assertThat(BazelProfilePhase.LICENSE.getNext()).isEqualTo(BazelProfilePhase.PREPARE); assertThat(BazelProfilePhase.PREPARE.getNext()).isEqualTo(BazelProfilePhase.EXECUTE); assertThat(BazelProfilePhase.EXECUTE.getNext()).isEqualTo(BazelProfilePhase.FINISH); assertThrows(UnsupportedOperationException.class, () -> BazelProfilePhase.FINISH.getNext()); diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/DataProvidersTestSuite.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/DataProvidersTestSuite.java index 8d3cc9e..923bed6 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/DataProvidersTestSuite.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/DataProvidersTestSuite.java @@ -27,8 +27,9 @@ CriticalPathDurationDataProviderTest.class, EstimatedCoresDataProviderTest.class, GarbageCollectionStatsDataProviderTest.class, - MergedEventsPresentDataProviderTest.class, LocalActionsDataProviderTest.class, - RemoteCacheMetricsDataProviderTest.class + MergedEventsPresentDataProviderTest.class, + RemoteCacheMetricsDataProviderTest.class, + SkymeldUsedDataProviderTest.class }) public class DataProvidersTestSuite {} diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProviderTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProviderTest.java index 3f32cf0..21b86da 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProviderTest.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/EstimatedCoresDataProviderTest.java @@ -66,8 +66,8 @@ public void shouldReturnEstimatedCoresAvailableAllThreadsWithinRange() throws Ex BazelPhaseDescriptions bazelPhaseDescriptions = BazelPhaseDescriptions.newBuilder() - .add(BazelProfilePhase.EVALUATE, new BazelPhaseDescription(start, within)) - .add(BazelProfilePhase.DEPENDENCIES, new BazelPhaseDescription(within, end)) + .add(BazelProfilePhase.TARGET_PATTERN_EVAL, new BazelPhaseDescription(start, within)) + .add(BazelProfilePhase.ANALYZE, new BazelPhaseDescription(within, end)) .build(); when(dataManager.getDatum(BazelPhaseDescriptions.class)).thenReturn(bazelPhaseDescriptions); @@ -94,8 +94,8 @@ public void shouldReturnEstimatedCoresAvailableSomeThreadsWithinRange() throws E BazelPhaseDescriptions bazelPhaseDescriptions = BazelPhaseDescriptions.newBuilder() - .add(BazelProfilePhase.EVALUATE, new BazelPhaseDescription(start, within)) - .add(BazelProfilePhase.DEPENDENCIES, new BazelPhaseDescription(within, end)) + .add(BazelProfilePhase.TARGET_PATTERN_EVAL, new BazelPhaseDescription(start, within)) + .add(BazelProfilePhase.ANALYZE, new BazelPhaseDescription(within, end)) .build(); when(dataManager.getDatum(BazelPhaseDescriptions.class)).thenReturn(bazelPhaseDescriptions); @@ -120,7 +120,7 @@ public void shouldReturnEstimatedCoresAvailableEvaluatePhaseMarkerMissing() thro BazelPhaseDescriptions bazelPhaseDescriptions = BazelPhaseDescriptions.newBuilder() - .add(BazelProfilePhase.DEPENDENCIES, new BazelPhaseDescription(start, end)) + .add(BazelProfilePhase.ANALYZE, new BazelPhaseDescription(start, end)) .build(); when(dataManager.getDatum(BazelPhaseDescriptions.class)).thenReturn(bazelPhaseDescriptions); @@ -145,7 +145,7 @@ public void shouldReturnEstimatedCoresAvailableDependenciesPhaseMarkerMissing() BazelPhaseDescriptions bazelPhaseDescriptions = BazelPhaseDescriptions.newBuilder() - .add(BazelProfilePhase.EVALUATE, new BazelPhaseDescription(start, end)) + .add(BazelProfilePhase.TARGET_PATTERN_EVAL, new BazelPhaseDescription(start, end)) .build(); when(dataManager.getDatum(BazelPhaseDescriptions.class)).thenReturn(bazelPhaseDescriptions); @@ -191,8 +191,8 @@ public void shouldReturnEmptyEstimatedCoresAvailableWhenMissingEvents() throws E BazelPhaseDescriptions bazelPhaseDescriptions = BazelPhaseDescriptions.newBuilder() - .add(BazelProfilePhase.EVALUATE, new BazelPhaseDescription(start, within1)) - .add(BazelProfilePhase.DEPENDENCIES, new BazelPhaseDescription(within2, end)) + .add(BazelProfilePhase.TARGET_PATTERN_EVAL, new BazelPhaseDescription(start, within1)) + .add(BazelProfilePhase.ANALYZE, new BazelPhaseDescription(within2, end)) .build(); when(dataManager.getDatum(BazelPhaseDescriptions.class)).thenReturn(bazelPhaseDescriptions); @@ -289,7 +289,7 @@ public void shouldReturnEmptyEstimatedCoresUsedWhenExecutePhaseMarkerIsMissing() skyFrameThread(3, within1, Duration.ZERO))); BazelPhaseDescriptions bazelPhaseDescriptions = BazelPhaseDescriptions.newBuilder() - .add(BazelProfilePhase.DEPENDENCIES, new BazelPhaseDescription(start, within1)) + .add(BazelProfilePhase.ANALYZE, new BazelPhaseDescription(start, within1)) .add(BazelProfilePhase.FINISH, new BazelPhaseDescription(within2, end)) .build(); diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsedDataProviderTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsedDataProviderTest.java new file mode 100644 index 0000000..37000fb --- /dev/null +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/dataproviders/SkymeldUsedDataProviderTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2023 EngFlow 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.engflow.bazel.invocation.analyzer.dataproviders; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.when; + +import com.engflow.bazel.invocation.analyzer.bazelprofile.BazelProfilePhase; +import com.engflow.bazel.invocation.analyzer.core.DuplicateProviderException; +import com.engflow.bazel.invocation.analyzer.time.Timestamp; +import org.junit.Before; +import org.junit.Test; + +public class SkymeldUsedDataProviderTest extends DataProviderUnitTestBase { + private SkymeldUsedDataProvider provider; + + @Before + public void setupTest() throws DuplicateProviderException { + provider = new SkymeldUsedDataProvider(); + provider.register(dataManager); + super.dataProvider = provider; + } + + @Test + public void shouldReturnSkymeldNotUsed() throws Exception { + when(dataManager.getDatum(BazelPhaseDescriptions.class)) + .thenReturn(BazelPhaseDescriptions.newBuilder().build()); + assertThat(provider.getSkymeldUsed().isSkymeldUsed()).isFalse(); + } + + @Test + public void shouldReturnSkymeldUsed() throws Exception { + when(dataManager.getDatum(BazelPhaseDescriptions.class)) + .thenReturn( + BazelPhaseDescriptions.newBuilder() + .add( + BazelProfilePhase.ANALYZE_AND_EXECUTE, + new BazelPhaseDescription(Timestamp.ofSeconds(2), Timestamp.ofSeconds(3))) + .build()); + assertThat(provider.getSkymeldUsed().isSkymeldUsed()).isTrue(); + } +} diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/integrationtests/NegligiblePhaseSuggestionProviderIntegrationTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/integrationtests/NegligiblePhaseSuggestionProviderIntegrationTest.java index a93f7f5..c4b2a30 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/integrationtests/NegligiblePhaseSuggestionProviderIntegrationTest.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/integrationtests/NegligiblePhaseSuggestionProviderIntegrationTest.java @@ -25,6 +25,8 @@ import com.engflow.bazel.invocation.analyzer.dataproviders.BazelPhasesDataProvider; import com.engflow.bazel.invocation.analyzer.suggestionproviders.NegligiblePhaseSuggestionProvider; import com.engflow.bazel.invocation.analyzer.time.Timestamp; +import java.util.HashMap; +import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -40,15 +42,16 @@ public void before() throws Exception { @Test public void singleLongPhaseSuggestion() throws Exception { - final Timestamp LAUNCH_START = Timestamp.ofSeconds(0); - final Timestamp INIT_START = Timestamp.ofSeconds(1); - final Timestamp EVAL_START = Timestamp.ofSeconds(2); - final Timestamp DEP_START = Timestamp.ofSeconds(12); + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, Timestamp.ofSeconds(0)); + startTimes.put(BazelProfilePhase.INIT, Timestamp.ofSeconds(1)); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, Timestamp.ofSeconds(2)); + startTimes.put(BazelProfilePhase.ANALYZE, Timestamp.ofSeconds(12)); // Too long - final Timestamp PREP_START = Timestamp.ofSeconds(22); - final Timestamp EXEC_START = Timestamp.ofSeconds(32); - final Timestamp FINISH_START = Timestamp.ofSeconds(99); - final Timestamp FINISH_TIME = Timestamp.ofSeconds(100); + startTimes.put(BazelProfilePhase.PREPARE, Timestamp.ofSeconds(22)); + startTimes.put(BazelProfilePhase.EXECUTE, Timestamp.ofSeconds(32)); + startTimes.put(BazelProfilePhase.FINISH, Timestamp.ofSeconds(99)); + Timestamp finishTime = Timestamp.ofSeconds(100); useProfile( metaData(), @@ -57,15 +60,7 @@ public void singleLongPhaseSuggestion() throws Exception { 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, finishTime)))); SuggestionOutput output = provider.getSuggestions(dataManager); @@ -78,14 +73,11 @@ public void singleLongPhaseSuggestion() throws Exception { @Test public void allLongPhaseSuggestion() throws Exception { - final Timestamp LAUNCH_START = Timestamp.ofSeconds(10); - final Timestamp INIT_START = Timestamp.ofSeconds(20); - final Timestamp EVAL_START = Timestamp.ofSeconds(30); - final Timestamp DEP_START = Timestamp.ofSeconds(40); - final Timestamp PREP_START = Timestamp.ofSeconds(50); - final Timestamp EXEC_START = Timestamp.ofSeconds(60); - final Timestamp FINISH_START = Timestamp.ofSeconds(70); - final Timestamp FINISH_TIME = Timestamp.ofSeconds(80); + Map startTimes = new HashMap<>(); + for (var phase : BazelProfilePhase.values()) { + startTimes.put(phase, Timestamp.ofSeconds(10 * (phase.ordinal() + 1))); + } + Timestamp finishTime = Timestamp.ofSeconds(10 * (BazelProfilePhase.values().length + 1)); useProfile( metaData(), @@ -94,15 +86,7 @@ public void allLongPhaseSuggestion() throws Exception { 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, finishTime)))); SuggestionOutput output = provider.getSuggestions(dataManager); @@ -124,15 +108,42 @@ public void allLongPhaseSuggestion() throws Exception { } @Test - public void shouldNotProduceOutputOnOkayProfile() throws Exception { - final Timestamp LAUNCH_START = Timestamp.ofMicros(0); - final Timestamp INIT_START = Timestamp.ofMicros(1_000); - final Timestamp EVAL_START = Timestamp.ofMicros(2_000); - final Timestamp DEP_START = Timestamp.ofMicros(12_000); - final Timestamp PREP_START = Timestamp.ofMicros(22_000); - final Timestamp EXEC_START = Timestamp.ofMicros(23_000); - final Timestamp FINISH_START = Timestamp.ofMicros(99_000); - final Timestamp FINISH_TIME = Timestamp.ofMicros(100_000); + public void shouldNotProduceOutputOnOkayProfileWithoutSkymeld() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, Timestamp.ofMicros(0)); + startTimes.put(BazelProfilePhase.INIT, Timestamp.ofMicros(1_000)); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, Timestamp.ofMicros(2_000)); + startTimes.put(BazelProfilePhase.ANALYZE, Timestamp.ofMicros(12_000)); + startTimes.put(BazelProfilePhase.PREPARE, Timestamp.ofMicros(22_000)); + startTimes.put(BazelProfilePhase.EXECUTE, Timestamp.ofMicros(23_000)); + startTimes.put(BazelProfilePhase.FINISH, Timestamp.ofMicros(99_000)); + Timestamp finishTime = Timestamp.ofMicros(100_000); + + useProfile( + metaData(), + trace( + thread( + 20, + 0, + BazelProfileConstants.THREAD_MAIN, + createPhaseEvents(startTimes, finishTime)))); + + SuggestionOutput output = provider.getSuggestions(dataManager); + + assertThat(output.hasFailure()).isFalse(); + assertThat(output.getMissingInputList()).isEmpty(); + assertThat(output.getSuggestionList().size()).isEqualTo(0); + } + + @Test + public void shouldNotProduceOutputOnOkayProfileWithSkymeld() throws Exception { + Map startTimes = new HashMap<>(); + startTimes.put(BazelProfilePhase.LAUNCH, Timestamp.ofMicros(0)); + startTimes.put(BazelProfilePhase.INIT, Timestamp.ofMicros(1_000)); + startTimes.put(BazelProfilePhase.TARGET_PATTERN_EVAL, Timestamp.ofMicros(2_000)); + startTimes.put(BazelProfilePhase.ANALYZE_AND_EXECUTE, Timestamp.ofMicros(12_000)); + startTimes.put(BazelProfilePhase.FINISH, Timestamp.ofMicros(99_000)); + Timestamp finishTime = Timestamp.ofMicros(100_000); useProfile( metaData(), @@ -141,15 +152,7 @@ public void shouldNotProduceOutputOnOkayProfile() throws Exception { 20, 0, BazelProfileConstants.THREAD_MAIN, - createPhaseEvents( - LAUNCH_START, - INIT_START, - EVAL_START, - DEP_START, - PREP_START, - EXEC_START, - FINISH_START, - FINISH_TIME)))); + createPhaseEvents(startTimes, finishTime)))); SuggestionOutput output = provider.getSuggestions(dataManager);