/* * Copyright 2013-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.event.listener; import static com.facebook.buck.event.TestEventConfigurator.configureTestEventAtTime; import static org.junit.Assert.assertEquals; import com.facebook.buck.artifact_cache.CacheResult; import com.facebook.buck.artifact_cache.HttpArtifactCacheEvent; import com.facebook.buck.event.ActionGraphEvent; import com.facebook.buck.event.BuckEventBus; import com.facebook.buck.event.BuckEventBusFactory; import com.facebook.buck.event.ConsoleEvent; import com.facebook.buck.event.InstallEvent; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.parser.ParseEvent; import com.facebook.buck.rules.BuildEvent; import com.facebook.buck.rules.BuildRuleDurationTracker; import com.facebook.buck.rules.BuildRuleEvent; import com.facebook.buck.rules.BuildRuleKeys; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.BuildRuleStatus; import com.facebook.buck.rules.BuildRuleSuccessType; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.FakeBuildRule; import com.facebook.buck.rules.RuleKey; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.test.TestResultSummaryVerbosity; import com.facebook.buck.testutil.TestConsole; import com.facebook.buck.timing.Clock; import com.facebook.buck.timing.IncrementingFakeClock; import com.facebook.buck.util.environment.DefaultExecutionEnvironment; import com.facebook.buck.util.unit.SizeUnit; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; import java.nio.file.FileSystem; import java.nio.file.Path; import java.util.Locale; import java.util.Optional; import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; public class SimpleConsoleEventBusListenerTest { private static final String TARGET_ONE = "TARGET_ONE"; private static final String TARGET_TWO = "TARGET_TWO"; private static final String SEVERE_MESSAGE = "This is a sample severe message."; private static final String FINISHED_DOWNLOAD_STRING = "[-] DOWNLOADING... (0.00 B/S AVG, TOTAL: 0.00 B, 0 Artifacts)"; private BuildRuleDurationTracker durationTracker; private BuckEventBus eventBus; private TestConsole console; @Before public void setUp() { FileSystem vfs = Jimfs.newFileSystem(Configuration.unix()); Path logPath = vfs.getPath("log.txt"); durationTracker = new BuildRuleDurationTracker(); Clock fakeClock = new IncrementingFakeClock(TimeUnit.SECONDS.toNanos(1)); eventBus = BuckEventBusFactory.newInstance(fakeClock); console = new TestConsole(); SimpleConsoleEventBusListener listener = new SimpleConsoleEventBusListener( console, fakeClock, TestResultSummaryVerbosity.of(false, false), Locale.US, logPath, new DefaultExecutionEnvironment( ImmutableMap.copyOf(System.getenv()), System.getProperties())); eventBus.register(listener); } @Test public void testSimpleBuild() { BuildTarget fakeTarget = BuildTargetFactory.newInstance("//banana:stand"); ImmutableSet<BuildTarget> buildTargets = ImmutableSet.of(fakeTarget); Iterable<String> buildArgs = Iterables.transform(buildTargets, Object::toString); FakeBuildRule fakeRule = new FakeBuildRule( fakeTarget, new SourcePathResolver( new SourcePathRuleFinder( new BuildRuleResolver( TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))), ImmutableSortedSet.of()); final long threadId = 0; BuildEvent.Started buildEventStarted = BuildEvent.started(buildArgs); eventBus.postWithoutConfiguring( configureTestEventAtTime(buildEventStarted, 0L, TimeUnit.MILLISECONDS, threadId)); ParseEvent.Started parseStarted = ParseEvent.started(buildTargets); eventBus.postWithoutConfiguring( configureTestEventAtTime(parseStarted, 0L, TimeUnit.MILLISECONDS, threadId)); assertOutput("", console); eventBus.postWithoutConfiguring( configureTestEventAtTime( ParseEvent.finished(parseStarted, 10, Optional.empty()), 400L, TimeUnit.MILLISECONDS, threadId)); String expectedOutput = "[-] PARSING BUCK FILES...FINISHED 0.4s\n"; assertOutput(expectedOutput, console); BuildRuleEvent.Started started = BuildRuleEvent.started(fakeRule, durationTracker); eventBus.postWithoutConfiguring( configureTestEventAtTime(started, 600L, TimeUnit.MILLISECONDS, threadId)); HttpArtifactCacheEvent.Scheduled storeScheduledOne = ArtifactCacheTestUtils.postStoreScheduled(eventBus, threadId, TARGET_ONE, 700L); HttpArtifactCacheEvent.Scheduled storeScheduledTwo = ArtifactCacheTestUtils.postStoreScheduled(eventBus, threadId, TARGET_TWO, 700L); HttpArtifactCacheEvent.Started storeStartedOne = ArtifactCacheTestUtils.postStoreStarted(eventBus, threadId, 710L, storeScheduledOne); eventBus.postWithoutConfiguring( configureTestEventAtTime( BuildRuleEvent.finished( started, BuildRuleKeys.of(new RuleKey("aaaa")), BuildRuleStatus.SUCCESS, CacheResult.miss(), Optional.empty(), Optional.of(BuildRuleSuccessType.BUILT_LOCALLY), Optional.empty(), Optional.empty(), Optional.empty()), 1000L, TimeUnit.MILLISECONDS, threadId)); eventBus.postWithoutConfiguring( configureTestEventAtTime( BuildEvent.finished(buildEventStarted, 0), 1234L, TimeUnit.MILLISECONDS, threadId)); expectedOutput += "BUILT 0.4s //banana:stand\n" + "[-] BUILDING...FINISHED 0.8s\n" + "WAITING FOR HTTP CACHE UPLOADS 0.00 B (0 COMPLETE/0 FAILED/1 UPLOADING/1 PENDING)\n" + FINISHED_DOWNLOAD_STRING + "\n"; assertOutput(expectedOutput, console); eventBus.postWithoutConfiguring( configureTestEventAtTime( ConsoleEvent.severe(SEVERE_MESSAGE), 1500L, TimeUnit.MILLISECONDS, threadId)); expectedOutput += SEVERE_MESSAGE + "\n"; assertOutput(expectedOutput, console); InstallEvent.Started installEventStarted = configureTestEventAtTime( InstallEvent.started(fakeTarget), 2500L, TimeUnit.MILLISECONDS, threadId); eventBus.postWithoutConfiguring(installEventStarted); assertOutput(expectedOutput, console); eventBus.postWithoutConfiguring( configureTestEventAtTime( InstallEvent.finished(installEventStarted, true, Optional.empty(), Optional.empty()), 4000L, TimeUnit.MILLISECONDS, threadId)); expectedOutput += "[-] INSTALLING...FINISHED 1.5s\n"; assertOutput(expectedOutput, console); long artifactSizeOne = SizeUnit.MEGABYTES.toBytes(1.5); ArtifactCacheTestUtils.postStoreFinished( eventBus, threadId, artifactSizeOne, 5015L, true, storeStartedOne); HttpArtifactCacheEvent.Started storeStartedTwo = ArtifactCacheTestUtils.postStoreStarted(eventBus, threadId, 5020L, storeScheduledTwo); long artifactSizeTwo = 600; ArtifactCacheTestUtils.postStoreFinished( eventBus, threadId, artifactSizeTwo, 5020L, false, storeStartedTwo); eventBus.postWithoutConfiguring( configureTestEventAtTime( HttpArtifactCacheEvent.newShutdownEvent(), 6000L, TimeUnit.MILLISECONDS, threadId)); expectedOutput += "[-] HTTP CACHE UPLOAD...FINISHED 1.50 MB (1 COMPLETE/1 FAILED/0 UPLOADING/0 PENDING)\n"; assertOutput(expectedOutput, console); } @Test public void testJobSummaryIsDisplayed() { BuildEvent.RuleCountCalculated ruleCountCalculated = BuildEvent.ruleCountCalculated(ImmutableSet.of(), 10); eventBus.post(ruleCountCalculated); BuildTarget fakeTarget = BuildTargetFactory.newInstance("//banana:stand"); ImmutableSet<BuildTarget> buildTargets = ImmutableSet.of(fakeTarget); Iterable<String> buildArgs = Iterables.transform(buildTargets, Object::toString); BuildEvent.Started buildEventStarted = BuildEvent.started(buildArgs); eventBus.postWithoutConfiguring( configureTestEventAtTime( buildEventStarted, 200L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); eventBus.postWithoutConfiguring( configureTestEventAtTime( BuildEvent.finished(buildEventStarted, 0), 1234L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); assertOutput( "[-] BUILDING...FINISHED 1.0s (0/10 JOBS, 0 UPDATED, 0 [0.0%] CACHE MISS)\n" + FINISHED_DOWNLOAD_STRING + "\n", console); } @Test public void testBuildTimeDoesNotDisplayNegativeOffset() { BuildTarget fakeTarget = BuildTargetFactory.newInstance("//banana:stand"); ImmutableSet<BuildTarget> buildTargets = ImmutableSet.of(fakeTarget); Iterable<String> buildArgs = Iterables.transform(buildTargets, Object::toString); // Do a full parse and action graph cycle before the build event starts // This sequencing occurs when running `buck project` ParseEvent.Started parseStarted = ParseEvent.started(buildTargets); eventBus.postWithoutConfiguring( configureTestEventAtTime(parseStarted, 100L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); eventBus.postWithoutConfiguring( configureTestEventAtTime( ParseEvent.finished(parseStarted, 10, Optional.empty()), 300L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); String expectedOutput = "[-] PARSING BUCK FILES...FINISHED 0.2s\n"; assertOutput(expectedOutput, console); ActionGraphEvent.Started actionGraphStarted = ActionGraphEvent.started(); eventBus.postWithoutConfiguring( configureTestEventAtTime( actionGraphStarted, 300L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); eventBus.postWithoutConfiguring( configureTestEventAtTime( ActionGraphEvent.finished(actionGraphStarted), 500L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); BuildEvent.Started buildEventStarted = BuildEvent.started(buildArgs); eventBus.postWithoutConfiguring( configureTestEventAtTime( buildEventStarted, 500L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); eventBus.postWithoutConfiguring( configureTestEventAtTime( BuildEvent.finished(buildEventStarted, 0), 600L, TimeUnit.MILLISECONDS, /* threadId */ 0L)); expectedOutput += "[-] BUILDING...FINISHED 0.1s\n"; expectedOutput += FINISHED_DOWNLOAD_STRING + "\n"; assertOutput(expectedOutput, console); } private void assertOutput(String expectedOutput, TestConsole console) { assertEquals("", console.getTextWrittenToStdOut()); assertEquals(expectedOutput, console.getTextWrittenToStdErr()); } }