/* * Copyright 2015-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 org.junit.Assert.assertThat; import com.facebook.buck.event.BuckEventBus; import com.facebook.buck.event.DefaultBuckEventBus; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.model.BuildId; import com.facebook.buck.testutil.FakeProjectFilesystem; import com.facebook.buck.testutil.integration.TemporaryPaths; import com.facebook.buck.timing.FakeClock; import com.facebook.buck.util.ObjectMappers; import com.fasterxml.jackson.core.type.TypeReference; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedMap; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import org.hamcrest.Matchers; import org.junit.Rule; import org.junit.Test; public class ProgressEstimatorTest { @Rule public final TemporaryPaths tmp = new TemporaryPaths(); public BuckEventBus getBuckEventBus() { return new DefaultBuckEventBus(new FakeClock(0), new BuildId("")); } @Test public void testByDefaultProvidesNoProcessingBuckFilesProgress() { ProjectFilesystem filesystem = new FakeProjectFilesystem(); Path p = filesystem.resolve(ProgressEstimator.PROGRESS_ESTIMATIONS_JSON); ProgressEstimator e = new ProgressEstimator(p, getBuckEventBus()); assertThat(e.getEstimatedProgressOfProcessingBuckFiles().isPresent(), Matchers.equalTo(false)); } @Test public void testByProvidesNoProcessingBuckFilesProgressIfStorageDoesNotExist() throws IOException { Path storagePath = getStorageForTest(); ProgressEstimator estimator = new ProgressEstimator(storagePath, getBuckEventBus()); estimator.setCurrentCommand("project", ImmutableList.of("arg1", "arg2")); estimator.didParseBuckRules(10); assertThat( estimator.getEstimatedProgressOfProcessingBuckFiles().isPresent(), Matchers.equalTo(false)); } @Test public void testProvidesProcessingBuckFilesProgressIfStorageExists() throws IOException { Path storagePath = getStorageForTest(); Map<String, Object> storageContents = ImmutableSortedMap.<String, Object>naturalOrder() .put( "project arg1 arg2", ImmutableSortedMap.<String, Number>naturalOrder() .put(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_RULES, 100) .put(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_BUCK_FILES, 10) .build()) .build(); String contents = ObjectMappers.WRITER.writeValueAsString(storageContents); Files.write(storagePath, contents.getBytes(StandardCharsets.UTF_8)); // path is 2 levels up folder ProgressEstimator estimator = new ProgressEstimator(storagePath, getBuckEventBus()); estimator.setCurrentCommand("project", ImmutableList.of("arg1", "arg2")); estimator.didParseBuckRules(10); assertThat( estimator.getEstimatedProgressOfProcessingBuckFiles().get(), Matchers.closeTo(0.1, 0.01)); } @Test public void testUpdatesStorageWithParsingEstimationsAfterCommandInvocation() throws IOException { Path storagePath = getStorageForTest(); Map<String, Object> storageContents = ImmutableSortedMap.<String, Object>naturalOrder() .put( "project arg1 arg2", ImmutableSortedMap.<String, Number>naturalOrder() .put(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_RULES, 100) .put(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_BUCK_FILES, 10) .build()) .build(); String contents = ObjectMappers.WRITER.writeValueAsString(storageContents); Files.write(storagePath, contents.getBytes(StandardCharsets.UTF_8)); // path is 2 levels up folder ProgressEstimator estimator = new ProgressEstimator(storagePath, getBuckEventBus()); estimator.setCurrentCommand("project", ImmutableList.of("arg1", "arg2")); estimator.didParseBuckRules(10); estimator.didParseBuckRules(30); estimator.didParseBuckRules(10); estimator.didFinishParsing(); Map<String, Map<String, Number>> jsonObject = ObjectMappers.READER.readValue( ObjectMappers.createParser(Files.readAllBytes(storagePath)), new TypeReference<HashMap<String, Map<String, Number>>>() {}); Map<String, Number> storedValues = jsonObject.get("project arg1 arg2"); assertThat( storedValues.get(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_BUCK_FILES).intValue(), Matchers.equalTo(3)); assertThat( storedValues.get(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_RULES).intValue(), Matchers.equalTo(50)); } @Test public void testProvidesProjectGenerationProgressIfStorageExists() throws IOException { Path storagePath = getStorageForTest(); Map<String, Object> storageContents = ImmutableSortedMap.<String, Object>naturalOrder() .put( "project arg1 arg2", ImmutableSortedMap.<String, Number>naturalOrder() .put(ProgressEstimator.EXPECTED_NUMBER_OF_GENERATED_PROJECT_FILES, 10) .build()) .build(); String contents = ObjectMappers.WRITER.writeValueAsString(storageContents); Files.write(storagePath, contents.getBytes(StandardCharsets.UTF_8)); // path is 2 levels up folder ProgressEstimator estimator = new ProgressEstimator(storagePath, getBuckEventBus()); estimator.setCurrentCommand("project", ImmutableList.of("arg1", "arg2")); estimator.didGenerateProjectForTarget(); estimator.didGenerateProjectForTarget(); assertThat( estimator.getEstimatedProgressOfGeneratingProjectFiles().get(), Matchers.closeTo(0.2, 0.01)); } @Test public void testUpdatesStorageWithProjectGenerationEstimationsAfterCommandInvocation() throws IOException { Path storagePath = getStorageForTest(); Map<String, Object> storageContents = ImmutableSortedMap.<String, Object>naturalOrder() .put( "project arg1 arg2", ImmutableSortedMap.<String, Number>naturalOrder() .put(ProgressEstimator.EXPECTED_NUMBER_OF_GENERATED_PROJECT_FILES, 10) .build()) .build(); String contents = ObjectMappers.WRITER.writeValueAsString(storageContents); Files.write(storagePath, contents.getBytes(StandardCharsets.UTF_8)); // path is 2 levels up folder ProgressEstimator estimator = new ProgressEstimator(storagePath, getBuckEventBus()); estimator.setCurrentCommand("project", ImmutableList.of("arg1", "arg2")); estimator.didGenerateProjectForTarget(); estimator.didGenerateProjectForTarget(); estimator.didGenerateProjectForTarget(); estimator.didFinishProjectGeneration(); Map<String, Map<String, Number>> jsonObject = ObjectMappers.READER.readValue( ObjectMappers.createParser(Files.readAllBytes(storagePath)), new TypeReference<HashMap<String, Map<String, Number>>>() {}); Map<String, Number> storedValues = jsonObject.get("project arg1 arg2"); assertThat( storedValues.get(ProgressEstimator.EXPECTED_NUMBER_OF_GENERATED_PROJECT_FILES).intValue(), Matchers.equalTo(3)); } @Test public void testUpdatesStorageWithParsingAndProjectGenerationEstimationsAfterCommandInvocation() throws IOException { Path storagePath = getStorageForTest(); // path is 2 levels up folder ProgressEstimator estimator = new ProgressEstimator(storagePath, getBuckEventBus()); estimator.setCurrentCommand("project", ImmutableList.of("arg1", "arg2")); estimator.didParseBuckRules(10); estimator.didParseBuckRules(20); estimator.didParseBuckRules(15); estimator.didParseBuckRules(2); estimator.didFinishParsing(); estimator.didGenerateProjectForTarget(); estimator.didGenerateProjectForTarget(); estimator.didFinishProjectGeneration(); Map<String, Map<String, Number>> jsonObject = ObjectMappers.READER.readValue( ObjectMappers.createParser(Files.readAllBytes(storagePath)), new TypeReference<HashMap<String, Map<String, Number>>>() {}); Map<String, Number> storedValues = jsonObject.get("project arg1 arg2"); assertThat( storedValues.get(ProgressEstimator.EXPECTED_NUMBER_OF_GENERATED_PROJECT_FILES).intValue(), Matchers.equalTo(2)); assertThat( storedValues.get(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_BUCK_FILES).intValue(), Matchers.equalTo(4)); assertThat( storedValues.get(ProgressEstimator.EXPECTED_NUMBER_OF_PARSED_RULES).intValue(), Matchers.equalTo(47)); } private Path getStorageForTest() throws IOException { return tmp.newFile(); } @Test public void testByDefaultProvidesNoBuildProgress() { ProjectFilesystem filesystem = new FakeProjectFilesystem(); Path p = filesystem.resolve(ProgressEstimator.PROGRESS_ESTIMATIONS_JSON); ProgressEstimator e = new ProgressEstimator(p, getBuckEventBus()); assertThat(e.getApproximateBuildProgress().isPresent(), Matchers.equalTo(false)); } @Test public void testByProvidesCompleteBuildProgressAfterGettingBuildEvents() { ProjectFilesystem filesystem = new FakeProjectFilesystem(); Path p = filesystem.resolve(ProgressEstimator.PROGRESS_ESTIMATIONS_JSON); ProgressEstimator e = new ProgressEstimator(p, getBuckEventBus()); e.didStartBuild(); e.setNumberOfRules(10); e.didFinishBuild(); assertThat(e.getApproximateBuildProgress().isPresent(), Matchers.equalTo(true)); assertThat(e.getApproximateBuildProgress().get(), Matchers.closeTo(1.0, 0.01)); } @Test public void testByProvidesPartialBuildProgressAfterGettingBuildEvents() { ProjectFilesystem filesystem = new FakeProjectFilesystem(); Path p = filesystem.resolve(ProgressEstimator.PROGRESS_ESTIMATIONS_JSON); ProgressEstimator e = new ProgressEstimator(p, getBuckEventBus()); e.didStartBuild(); e.setNumberOfRules(10); e.didStartRule(); e.didStartRule(); e.didStartRule(); e.didStartRule(); e.didSuspendRule(); e.didResumeRule(); e.didSuspendRule(); e.didResumeRule(); e.didSuspendRule(); e.didResumeRule(); e.didSuspendRule(); e.didResumeRule(); e.didFinishRule(); e.didFinishRule(); e.didFinishRule(); e.didFinishRule(); assertThat(e.getApproximateBuildProgress().isPresent(), Matchers.equalTo(true)); assertThat(e.getApproximateBuildProgress().get(), Matchers.greaterThan(0.0)); assertThat(e.getApproximateBuildProgress().get(), Matchers.lessThan(1.0)); } }