@Test public void ruleKeyDoesNotChangeWhenOnlyDependencyRuleKeyChanges() throws Exception { ProjectFilesystem filesystem = new FakeProjectFilesystem(); BuildRuleResolver resolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathResolver pathResolver = new SourcePathResolver(resolver); Path depOutput = Paths.get("output"); FakeBuildRule dep = resolver.addToIndex( new FakeBuildRule(BuildTargetFactory.newInstance("//:dep"), filesystem, pathResolver)); dep.setOutputFile(depOutput.toString()); filesystem.writeContentsToPath("hello", dep.getPathToOutput()); FakeFileHashCache hashCache = new FakeFileHashCache(ImmutableMap.of(filesystem.resolve(depOutput), HashCode.fromInt(0))); BuildRule rule = GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:rule")) .setOut("out") .setSrcs(ImmutableList.<SourcePath>of(new BuildTargetSourcePath(dep.getBuildTarget()))) .build(resolver, filesystem); RuleKey inputKey1 = new InputBasedRuleKeyBuilderFactory(0, hashCache, pathResolver).build(rule); RuleKey inputKey2 = new InputBasedRuleKeyBuilderFactory(0, hashCache, pathResolver).build(rule); assertThat(inputKey1, Matchers.equalTo(inputKey2)); }
@Test public void testCreateRelativeSymlinkToFilesInRoot() throws IOException { ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmp.getRoot()); tmp.newFile("biz.txt"); Path pathToDesiredLinkUnderProjectRoot = Paths.get("gamma.txt"); Path pathToExistingFileUnderProjectRoot = Paths.get("biz.txt"); Path relativePath = MorePaths.createRelativeSymlink( pathToDesiredLinkUnderProjectRoot, pathToExistingFileUnderProjectRoot, projectFilesystem); assertEquals("biz.txt", relativePath.toString()); Path absolutePathToDesiredLinkUnderProjectRoot = projectFilesystem.resolve(pathToDesiredLinkUnderProjectRoot); assertTrue(Files.isSymbolicLink(absolutePathToDesiredLinkUnderProjectRoot)); Path targetOfSymbolicLink = Files.readSymbolicLink(absolutePathToDesiredLinkUnderProjectRoot); assertEquals(relativePath, targetOfSymbolicLink); Path absolutePathToExistingFileUnderProjectRoot = projectFilesystem.resolve(pathToExistingFileUnderProjectRoot); Files.write(absolutePathToExistingFileUnderProjectRoot, "Hello, World!".getBytes()); String dataReadFromSymlink = new String(Files.readAllBytes(absolutePathToDesiredLinkUnderProjectRoot)); assertEquals("Hello, World!", dataReadFromSymlink); }
@Test public void testOutputFailed() throws IOException { ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmpDir.getRoot().toPath()); ChromeTraceBuildListener listener = new ChromeTraceBuildListener( projectFilesystem, new FakeClock(1409702151000000000L), new ObjectMapper(), Locale.US, TimeZone.getTimeZone("America/Los_Angeles"), /* tracesToKeep */ 3, false); try { assumeTrue("Can make the root directory read-only", tmpDir.getRoot().setReadOnly()); listener.outputTrace(new BuildId("BUILD_ID")); fail("Expected an exception."); } catch (HumanReadableException e) { assertEquals( "Unable to write trace file: java.nio.file.AccessDeniedException: " + projectFilesystem.resolve(BuckConstant.BUCK_OUTPUT_PATH), e.getMessage()); } finally { tmpDir.getRoot().setWritable(true); } }
@BeforeClass public static void createParser() { ProjectFilesystem filesystem = new FakeProjectFilesystem(); FakeBuckConfig buckConfig = new FakeBuckConfig(); ParserConfig parserConfig = new ParserConfig(buckConfig); PythonBuckConfig pythonBuckConfig = new PythonBuckConfig(buckConfig, new ExecutableFinder()); ImmutableSet<Description<?>> descriptions = ImmutableSet.of( new RemoteFileDescription(new ExplodingDownloader()), new PrebuiltJarDescription()); DefaultProjectBuildFileParserFactory parserFactory = new DefaultProjectBuildFileParserFactory( filesystem.getRootPath(), pythonBuckConfig.getPythonInterpreter(), parserConfig.getAllowEmptyGlobs(), parserConfig.getBuildFileName(), parserConfig.getDefaultIncludes(), descriptions); buildFileParser = parserFactory.createParser( new TestConsole(), ImmutableMap.<String, String>of(), BuckEventBusFactory.newInstance()); }
@Test public void canCompressTraces() throws IOException { ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmpDir.getRoot().toPath()); ChromeTraceBuildListener listener = new ChromeTraceBuildListener( projectFilesystem, new FakeClock(1409702151000000000L), new ObjectMapper(), Locale.US, TimeZone.getTimeZone("America/Los_Angeles"), /* tracesToKeep */ 1, true); listener.outputTrace(new BuildId("BUILD_ID")); Path tracePath = Paths.get("buck-out/log/traces/build.2014-09-02.16-55-51.BUILD_ID.trace.gz"); assertTrue(projectFilesystem.exists(tracePath)); BufferedReader reader = new BufferedReader( new InputStreamReader( new GZIPInputStream(projectFilesystem.newFileInputStream(tracePath)))); List<?> elements = new Gson().fromJson(reader, List.class); assertThat(elements, notNullValue()); }
public Optional<Path> checkPathExists(String pathString, String errorMsg) { Path path = Paths.get(pathString); if (projectFilesystem.exists(path)) { return Optional.of(projectFilesystem.getPathForRelativePath(path)); } throw new HumanReadableException(errorMsg + path); }
private static boolean inputFilesUnderSymlink( // We use Collection<Path> instead of Iterable<Path> to prevent // accidentally passing in Path, since Path itself is Iterable<Path>. Collection<Path> inputs, ProjectFilesystem projectFilesystem, Map<Path, Path> symlinkExistenceCache, Map<Path, Path> newSymlinksEncountered) throws IOException { boolean result = false; for (Path input : inputs) { for (int i = 1; i < input.getNameCount(); i++) { Path subpath = input.subpath(0, i); Path resolvedSymlink = symlinkExistenceCache.get(subpath); if (resolvedSymlink != null) { LOG.debug("Detected cached symlink %s -> %s", subpath, resolvedSymlink); newSymlinksEncountered.put(subpath, resolvedSymlink); result = true; } else if (projectFilesystem.isSymLink(subpath)) { Path symlinkTarget = projectFilesystem.resolve(subpath).toRealPath(); Path relativeSymlinkTarget = projectFilesystem.getPathRelativeToProjectRoot(symlinkTarget).or(symlinkTarget); LOG.debug("Detected symbolic link %s -> %s", subpath, relativeSymlinkTarget); newSymlinksEncountered.put(subpath, relativeSymlinkTarget); symlinkExistenceCache.put(subpath, relativeSymlinkTarget); result = true; } } } return result; }
private ImmutableMap<Path, Path> getExpandedSourcePaths( ExecutionContext context, ImmutableMap<Path, Path> paths) throws IOException { ProjectFilesystem projectFilesystem = context.getProjectFilesystem(); ImmutableMap.Builder<Path, Path> sources = ImmutableMap.builder(); for (ImmutableMap.Entry<Path, Path> ent : paths.entrySet()) { if (ent.getValue().toString().endsWith(SRC_ZIP)) { Path destinationDirectory = projectFilesystem.resolve(tempDir.resolve(ent.getKey())); Files.createDirectories(destinationDirectory); ImmutableList<Path> zipPaths = Unzip.extractZipFile( projectFilesystem.resolve(ent.getValue()), destinationDirectory, Unzip.ExistingFileMode.OVERWRITE); for (Path path : zipPaths) { Path modulePath = destinationDirectory.relativize(path); sources.put(modulePath, path); } } else { sources.put(ent.getKey(), ent.getValue()); } } return sources.build(); }
@Test public void testAppleDynamicLibraryWithDsym() throws Exception { assumeTrue(Platform.detect() == Platform.MACOS); assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX)); ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "apple_library_shared", tmp); workspace.setUp(); ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath()); ProjectWorkspace.ProcessResult result = workspace.runBuckCommand( "build", "//Libraries/TestLibrary:TestLibrary#shared,macosx-x86_64,dwarf-and-dsym", "--config", "cxx.cflags=-g"); result.assertSuccess(); Path output = tmp.getRoot() .resolve(filesystem.getBuckPaths().getGenDir()) .resolve("Libraries/TestLibrary/TestLibrary#macosx-x86_64,shared") .resolve("libLibraries_TestLibrary_TestLibrary.dylib"); assertThat(Files.exists(output), is(true)); Path dsymPath = tmp.getRoot() .resolve(filesystem.getBuckPaths().getGenDir()) .resolve("Libraries/TestLibrary") .resolve("TestLibrary#apple-dsym,macosx-x86_64,shared.dSYM"); assertThat(Files.exists(dsymPath), is(true)); AppleDsymTestUtil.checkDsymFileHasDebugSymbol("+[TestClass answer]", workspace, dsymPath); }
public static int parseAndWriteBuckCompatibleDepfile( ExecutionContext context, ProjectFilesystem filesystem, HeaderPathNormalizer headerPathNormalizer, HeaderVerification headerVerification, Path sourceDepFile, Path destDepFile, Path inputPath, Path outputPath) throws IOException { // Process the dependency file, fixing up the paths, and write it out to it's final location. // The paths of the headers written out to the depfile are the paths to the symlinks from the // root of the repo if the compilation included them from the header search paths pointing to // the symlink trees, or paths to headers relative to the source file if the compilation // included them using source relative include paths. To handle both cases we check for the // prerequisites both in the values and the keys of the replacement map. Logger.get(Depfiles.class).debug("Processing dependency file %s as Makefile", sourceDepFile); ImmutableMap<String, Object> params = ImmutableMap.<String, Object>of("input", inputPath, "output", outputPath); try (InputStream input = filesystem.newFileInputStream(sourceDepFile); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); OutputStream output = filesystem.newFileOutputStream(destDepFile); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output)); SimplePerfEvent.Scope perfEvent = SimplePerfEvent.scope( context.getBuckEventBus(), PerfEventId.of("depfile-parse"), params)) { ImmutableList<String> prereqs = Depfiles.parseDepfile(reader).getPrereqs(); // Skip the first prereq, as it's the input source file. Preconditions.checkState(inputPath.toString().equals(prereqs.get(0))); ImmutableList<String> headers = prereqs.subList(1, prereqs.size()); for (String rawHeader : headers) { Path header = Paths.get(rawHeader).normalize(); Optional<Path> absolutePath = headerPathNormalizer.getAbsolutePathForUnnormalizedPath(header); if (absolutePath.isPresent()) { Preconditions.checkState(absolutePath.get().isAbsolute()); writer.write(absolutePath.get().toString()); writer.newLine(); } else if (headerVerification.getMode() != HeaderVerification.Mode.IGNORE && !headerVerification.isWhitelisted(header.toString())) { context .getBuckEventBus() .post( ConsoleEvent.create( headerVerification.getMode() == HeaderVerification.Mode.ERROR ? Level.SEVERE : Level.WARNING, "%s: included an untracked header \"%s\"", inputPath, header)); if (headerVerification.getMode() == HeaderVerification.Mode.ERROR) { return 1; } } } } return 0; }
private void assertCompDir(Path compDir, Optional<String> failure) throws Exception { ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRoot().toPath()); CxxPlatform platform = DefaultCxxPlatforms.build(new CxxBuckConfig(new FakeBuckConfig())); // Build up the paths to various files the archive step will use. ImmutableList<String> compiler = platform.getCc().getCommandPrefix(new SourcePathResolver(new BuildRuleResolver())); Path output = filesystem.resolve(Paths.get("output.o")); Path relativeInput = Paths.get("input.c"); Path input = filesystem.resolve(relativeInput); filesystem.writeContentsToPath("int main() {}", relativeInput); ImmutableList.Builder<String> preprocessorCommand = ImmutableList.builder(); preprocessorCommand.addAll(compiler); ImmutableList.Builder<String> compilerCommand = ImmutableList.builder(); compilerCommand.addAll(compiler); compilerCommand.add("-g"); DebugPathSanitizer sanitizer = new DebugPathSanitizer(200, File.separatorChar, compDir, ImmutableBiMap.<Path, Path>of()); // Build an archive step. CxxPreprocessAndCompileStep step = new CxxPreprocessAndCompileStep( CxxPreprocessAndCompileStep.Operation.COMPILE_MUNGE_DEBUGINFO, output, relativeInput, CxxSource.Type.C, Optional.of(preprocessorCommand.build()), Optional.of(compilerCommand.build()), ImmutableMap.<Path, Path>of(), sanitizer); // Execute the archive step and verify it ran successfully. ExecutionContext executionContext = TestExecutionContext.newBuilder() .setProjectFilesystem(new ProjectFilesystem(tmp.getRoot().toPath())) .build(); TestConsole console = (TestConsole) executionContext.getConsole(); int exitCode = step.execute(executionContext); if (failure.isPresent()) { assertNotEquals("compile step succeeded", 0, exitCode); assertThat( console.getTextWrittenToStdErr(), console.getTextWrittenToStdErr(), Matchers.containsString(failure.get())); } else { assertEquals("compile step failed: " + console.getTextWrittenToStdErr(), 0, exitCode); // Verify that we find the expected compilation dir embedded in the file. String contents = new String(Files.readAllBytes(output)); assertThat(contents, Matchers.containsString(sanitizer.getCompilationDirectory())); } // Cleanup. Files.delete(input); Files.deleteIfExists(output); }
@Test public void usesCorrectCommandForPreprocess() { // Setup some dummy values for inputs to the CxxPreprocessAndCompile. SourcePathResolver pathResolver = new SourcePathResolver( new BuildRuleResolver(TargetGraph.EMPTY, new BuildTargetNodeToBuildRuleTransformer())); BuildTarget target = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); ProjectFilesystem filesystem = new FakeProjectFilesystem(); ImmutableList<String> platformFlags = ImmutableList.of("-Dtest=blah"); ImmutableList<String> ruleFlags = ImmutableList.of("-Dfoo=bar"); Path output = Paths.get("test.ii"); Path depFile = Paths.get("test.ii.dep"); Path input = Paths.get("test.cpp"); Path prefixHeader = Paths.get("prefix.pch"); CxxPreprocessAndCompile buildRule = CxxPreprocessAndCompile.preprocess( params, pathResolver, new PreprocessorDelegate( pathResolver, DEFAULT_SANITIZER, DEFAULT_WORKING_DIR, DEFAULT_PREPROCESSOR, platformFlags, ruleFlags, ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), ImmutableSet.<Path>of(), DEFAULT_FRAMEWORK_ROOTS, DEFAULT_FRAMEWORK_PATH_SEARCH_PATH_FUNCTION, Optional.<SourcePath>of(new FakeSourcePath(filesystem, prefixHeader.toString())), ImmutableList.of(CxxHeaders.builder().build())), output, new FakeSourcePath(input.toString()), DEFAULT_INPUT_TYPE, DEFAULT_SANITIZER); // Verify it uses the expected command. ImmutableList<String> expectedPreprocessCommand = ImmutableList.<String>builder() .add("preprocessor") .add("-Dtest=blah") .add("-Dfoo=bar") .add("-include") .add(filesystem.resolve(prefixHeader).toString()) .add("-x", "c++") .add("-E") .add("-MD") .add("-MF") .add(depFile.toString() + ".tmp") .add(input.toString()) .build(); ImmutableList<String> actualPreprocessCommand = buildRule.makeMainStep().getCommand(); assertEquals(expectedPreprocessCommand, actualPreprocessCommand); }
public long getOutputSize() throws IOException { long size = 0; for (Path path : getRecordedDirsAndFiles()) { if (projectFilesystem.isFile(path)) { size += projectFilesystem.getFileSize(path); } } return size; }
@Test public void skipsFirstCacheBecauseIgnored() throws IOException { Path path = Paths.get("world.txt"); Path fullPath = tmp.getRootPath().resolve(path); ProjectFilesystem filesystem = new ProjectFilesystem(tmp.getRootPath(), ImmutableSet.of(path)); filesystem.touch(path); DefaultFileHashCache innerCache = new DefaultFileHashCache(filesystem); StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache)); expectedException.expect(NoSuchFileException.class); cache.get(fullPath); }
@Override public int execute(ExecutionContext context) throws InterruptedException { ProjectFilesystem filesystem = context.getProjectFilesystem(); try { filesystem.move(source, destination, options); } catch (IOException e) { context.logError(e, "error moving %s -> %s", source, destination); return 1; } return 0; }
/** * Looks through filtered drawables for files not of the target density and replaces them with * scaled versions. * * <p>Any drawables found by this step didn't have equivalents in the target density. If they are * of a higher density, we can replicate what Android does and downscale them at compile-time. */ private void scaleUnmatchedDrawables(ExecutionContext context) throws IOException, InterruptedException { ResourceFilters.Density targetDensity = ResourceFilters.Density.ORDERING.max(targetDensities); // Go over all the images that remain after filtering. Preconditions.checkNotNull(drawableFinder); Collection<Path> drawables = drawableFinder.findDrawables(inResDirToOutResDirMap.values(), filesystem); for (Path drawable : drawables) { if (drawable.toString().endsWith(".9.png")) { // Skip nine-patch for now. continue; } ResourceFilters.Qualifiers qualifiers = new ResourceFilters.Qualifiers(drawable); ResourceFilters.Density density = qualifiers.density; // If the image has a qualifier but it's not the right one. Preconditions.checkNotNull(targetDensities); if (!targetDensities.contains(density)) { // Replace density qualifier with target density using regular expression to match // the qualifier in the context of a path to a drawable. String fromDensity = (density == ResourceFilters.Density.NO_QUALIFIER ? "" : "-") + density.toString(); Path destination = Paths.get( MorePaths.pathWithUnixSeparators(drawable) .replaceFirst( "((?:^|/)drawable[^/]*)" + Pattern.quote(fromDensity) + "(-|$|/)", "$1-" + targetDensity + "$2")); double factor = targetDensity.value() / density.value(); if (factor >= 1.0) { // There is no point in up-scaling, or converting between drawable and drawable-mdpi. continue; } // Make sure destination folder exists and perform downscaling. filesystem.createParentDirs(destination); Preconditions.checkNotNull(imageScaler); imageScaler.scale(factor, drawable, destination, context); // Delete source file. filesystem.deleteFileAtPath(drawable); // Delete newly-empty directories to prevent missing resources errors in apkbuilder. Path parent = drawable.getParent(); if (filesystem.listFiles(parent).length == 0) { filesystem.deleteFileAtPath(parent); } } } }
@Test public void testGetBuildStepsWhenThereAreNoClassesToDex() throws IOException, InterruptedException { JavaLibrary javaLibrary = createMock(JavaLibrary.class); expect(javaLibrary.getClassNamesToHashes()) .andReturn(ImmutableSortedMap.<String, HashCode>of()); BuildContext context = createMock(BuildContext.class); FakeBuildableContext buildableContext = new FakeBuildableContext(); ProjectFilesystem projectFilesystem = createMock(ProjectFilesystem.class); replayAll(); BuildTarget buildTarget = BuildTargetFactory.newInstance("//foo:bar"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(buildTarget).setProjectFilesystem(projectFilesystem).build(); DexProducedFromJavaLibrary preDex = new DexProducedFromJavaLibrary( params, new SourcePathResolver(new BuildRuleResolver()), javaLibrary); List<Step> steps = preDex.getBuildSteps(context, buildableContext); verifyAll(); resetAll(); expect(projectFilesystem.resolve(Paths.get("buck-out/gen/foo"))) .andReturn(Paths.get("/home/user/buck-out/gen/foo")); expect(projectFilesystem.resolve(Paths.get("buck-out/gen/foo/bar.dex.jar"))) .andReturn(Paths.get("/home/user/buck-out/gen/foo/bar.dex.jar")); replayAll(); ExecutionContext executionContext = TestExecutionContext.newBuilder().build(); MoreAsserts.assertSteps( "Do not generate a .dex.jar file.", ImmutableList.of( String.format("rm -f %s", Paths.get("/home/user/buck-out/gen/foo/bar.dex.jar")), String.format("mkdir -p %s", Paths.get("/home/user/buck-out/gen/foo")), "record_empty_dx"), steps, executionContext); verifyAll(); resetAll(); replayAll(); Step recordArtifactAndMetadataStep = steps.get(2); assertThat(recordArtifactAndMetadataStep.getShortName(), startsWith("record_")); int exitCode = recordArtifactAndMetadataStep.execute(executionContext); assertEquals(0, exitCode); verifyAll(); }
/** * Writes the metadata currently stored in memory to the directory returned by {@link * BuildInfo#getPathToMetadataDirectory(BuildTarget)}. */ public void writeMetadataToDisk(boolean clearExistingMetadata) throws IOException { if (clearExistingMetadata) { projectFilesystem.deleteRecursivelyIfExists(pathToMetadataDirectory); } projectFilesystem.mkdirs(pathToMetadataDirectory); for (Map.Entry<String, String> entry : Iterables.concat(metadataToWrite.entrySet(), getBuildMetadata().entrySet())) { projectFilesystem.writeContentsToPath( entry.getValue(), pathToMetadataDirectory.resolve(entry.getKey())); } }
private int handleGet(Request baseRequest, HttpServletResponse response) throws IOException { if (!artifactCache.isPresent()) { response.getWriter().write("Serving local cache is disabled for this instance."); return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } String path = baseRequest.getUri().getPath(); String[] pathElements = path.split("/"); if (pathElements.length != 4 || !pathElements[2].equals("key")) { response.getWriter().write("Incorrect url format."); return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } RuleKey ruleKey = RuleKey.TO_RULE_KEY.apply(pathElements[3]); Path temp = null; try { temp = projectFilesystem.createTempFile(BuckConstant.SCRATCH_PATH, "outgoing_rulekey", ".tmp"); projectFilesystem.createParentDirs(temp); CacheResult fetchResult; try { fetchResult = artifactCache.get().fetch(ruleKey, temp); } catch (InterruptedException e) { LOG.error(e, "Interrupted when fetching from local cache."); e.printStackTrace(response.getWriter()); return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } if (!fetchResult.getType().isSuccess()) { return HttpServletResponse.SC_NOT_FOUND; } final Path tempFinal = temp; HttpArtifactCacheBinaryProtocol.FetchResponse fetchResponse = new HttpArtifactCacheBinaryProtocol.FetchResponse( ImmutableSet.of(ruleKey), fetchResult.getMetadata(), new ByteSource() { @Override public InputStream openStream() throws IOException { return projectFilesystem.newFileInputStream(tempFinal); } }); fetchResponse.write(response.getOutputStream()); response.setContentLengthLong(fetchResponse.getContentLength()); return HttpServletResponse.SC_OK; } finally { if (temp != null) { projectFilesystem.deleteFileAtPathIfExists(temp); } } }
@Test public void usesFirstCache() throws IOException { ProjectFilesystem filesystem = FakeProjectFilesystem.createJavaOnlyFilesystem(); Path path = Paths.get("world.txt"); filesystem.touch(path); Path fullPath = filesystem.resolve(path); DefaultFileHashCache innerCache = new DefaultFileHashCache(filesystem); StackedFileHashCache cache = new StackedFileHashCache(ImmutableList.of(innerCache)); cache.get(fullPath); assertTrue(innerCache.willGet(path)); }
@Override public StepExecutionResult execute(ExecutionContext context) throws InterruptedException { // Build the process, redirecting output to the provided output file. In general, // it's undesirable that both stdout and stderr are being redirected to the same // input stream. However, due to the nature of OS pipe buffering, we can't really // maintain the natural interleaving of multiple output streams in a way that we // can correctly associate both stdout/stderr streams to the one correct test out // of the many that ran. So, our best bet is to just combine them all into stdout, // so they get properly interleaved with the test start and end messages that we // use when we parse the test output. ProcessBuilder builder = new ProcessBuilder(); builder.command(command); builder.redirectOutput(filesystem.resolve(output).toFile()); builder.redirectErrorStream(true); Process process; try { process = BgProcessKiller.startProcess(builder); } catch (IOException e) { context.logError(e, "Error starting command %s", command); return StepExecutionResult.ERROR; } // Run the test process, saving the exit code. ProcessExecutor executor = context.getProcessExecutor(); ImmutableSet<ProcessExecutor.Option> options = ImmutableSet.of(ProcessExecutor.Option.EXPECTING_STD_OUT); ProcessExecutor.Result result = executor.execute( process, options, /* stdin */ Optional.<String>absent(), /* timeOutMs */ testRuleTimeoutMs, /* timeOutHandler */ Optional.<Function<Process, Void>>absent()); if (result.isTimedOut()) { throw new HumanReadableException( "Timed out after %d ms running test command %s", testRuleTimeoutMs.or(-1L), command); } // Since test binaries return a non-zero exit code when unittests fail, save the exit code // to a file rather than signalling a step failure. try (FileOutputStream stream = new FileOutputStream(filesystem.resolve(exitCode).toFile())) { stream.write((Integer.toString(result.getExitCode())).getBytes()); } catch (IOException e) { context.logError(e, "Error saving exit code to %s", exitCode); return StepExecutionResult.ERROR; } return StepExecutionResult.SUCCESS; }
public OCamlBuildStep( SourcePathResolver resolver, ProjectFilesystem filesystem, OCamlBuildContext ocamlContext, ImmutableMap<String, String> cCompilerEnvironment, ImmutableList<String> cCompiler, ImmutableMap<String, String> cxxCompilerEnvironment, ImmutableList<String> cxxCompiler) { this.resolver = resolver; this.filesystem = filesystem; this.ocamlContext = ocamlContext; this.cCompilerEnvironment = cCompilerEnvironment; this.cCompiler = cCompiler; this.cxxCompilerEnvironment = cxxCompilerEnvironment; this.cxxCompiler = cxxCompiler; hasGeneratedSources = ocamlContext.getLexInput().size() > 0 || ocamlContext.getYaccInput().size() > 0; this.depToolStep = new OCamlDepToolStep( filesystem.getRootPath(), this.ocamlContext.getSourcePathResolver(), this.ocamlContext.getOcamlDepTool().get(), ocamlContext.getMLInput(), this.ocamlContext.getIncludeFlags(/* isBytecode */ false, /* excludeDeps */ true)); }
private int executeCCompilation( ExecutionContext context, ImmutableList.Builder<Path> linkerInputs) throws IOException, InterruptedException { ImmutableList.Builder<String> cCompileFlags = ImmutableList.builder(); cCompileFlags.addAll(ocamlContext.getCCompileFlags()); cCompileFlags.addAll(ocamlContext.getCommonCFlags()); CxxPreprocessorInput cxxPreprocessorInput = ocamlContext.getCxxPreprocessorInput(); for (SourcePath cSrc : ocamlContext.getCInput()) { Path outputPath = ocamlContext.getCOutput(resolver.getAbsolutePath(cSrc)); linkerInputs.add(outputPath); Step compileStep = new OCamlCCompileStep( resolver, filesystem.getRootPath(), new OCamlCCompileStep.Args( cCompilerEnvironment, cCompiler, ocamlContext.getOcamlCompiler().get(), outputPath, cSrc, cCompileFlags.build(), ImmutableMap.copyOf(cxxPreprocessorInput.getIncludes().getNameToPathMap()))); int compileExitCode = compileStep.execute(context); if (compileExitCode != 0) { return compileExitCode; } } return 0; }
private StepExecutionResult executeCCompilation( ExecutionContext context, ImmutableList.Builder<Path> linkerInputs) throws IOException, InterruptedException { ImmutableList.Builder<String> cCompileFlags = ImmutableList.builder(); cCompileFlags.addAll(ocamlContext.getCCompileFlags()); cCompileFlags.addAll(ocamlContext.getCommonCFlags()); CxxPreprocessorInput cxxPreprocessorInput = ocamlContext.getCxxPreprocessorInput(); for (SourcePath cSrc : ocamlContext.getCInput()) { Path outputPath = ocamlContext.getCOutput(resolver.getAbsolutePath(cSrc)); linkerInputs.add(outputPath); Step compileStep = new OCamlCCompileStep( resolver, filesystem.getRootPath(), new OCamlCCompileStep.Args( cCompilerEnvironment, cCompiler, ocamlContext.getOcamlCompiler().get(), ocamlContext.getOCamlInteropIncludesDir(), outputPath, cSrc, cCompileFlags.build(), cxxPreprocessorInput.getIncludes())); StepExecutionResult compileExecutionResult = compileStep.execute(context); if (!compileExecutionResult.isSuccess()) { return compileExecutionResult; } } return StepExecutionResult.SUCCESS; }
private ImmutableList<String> getExtraFlagsForHeaderMaps(ProjectFilesystem filesystem) throws IOException { // This works around OS X being amusing about the location of temp directories. return PREPROCESSOR_SUPPORTS_HEADER_MAPS ? ImmutableList.of("-I", filesystem.getBuckPaths().getBuckOut().toString()) : ImmutableList.<String>of(); }
private ImmutableSortedSet<Path> getRecordedOutputDirsAndFiles() throws IOException { final ImmutableSortedSet.Builder<Path> paths = ImmutableSortedSet.naturalOrder(); // Add files from output directories. for (final Path output : pathsToOutputs) { projectFilesystem.walkRelativeFileTree( output, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { paths.add(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { paths.add(dir); return FileVisitResult.CONTINUE; } }); } return paths.build(); }
@Test public void shouldFindNeededDependenciesFromSymbols() throws IOException, InterruptedException { ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "symbol_finder", temporaryFolder); workspace.setUp(); ProjectFilesystem projectFilesystem = new ProjectFilesystem(temporaryFolder.getRootPath()); ImmutableMap<String, String> environment = ImmutableMap.copyOf(System.getenv()); Config rawConfig = Config.createDefaultConfig( projectFilesystem.getRootPath(), ImmutableMap.<String, ImmutableMap<String, String>>of()); BuckConfig config = new BuckConfig( rawConfig, projectFilesystem, Architecture.detect(), Platform.detect(), environment); ImmutableSet<Description<?>> allDescriptions = DefaultKnownBuildRuleTypes.getDefaultKnownBuildRuleTypes(projectFilesystem) .getAllDescriptions(); BuckEventBus buckEventBus = BuckEventBusFactory.newInstance(); MissingSymbolsHandler missingSymbolsHandler = MissingSymbolsHandler.create( projectFilesystem, allDescriptions, config, buckEventBus, new TestConsole(), DEFAULT_JAVAC_OPTIONS, environment); MissingSymbolEvent missingSymbolEvent = MissingSymbolEvent.create( BuildTargetFactory.newInstance(workspace.getDestPath(), "//java/com/example/b:b"), "com.example.a.A", MissingSymbolEvent.SymbolType.Java); ImmutableSetMultimap<BuildTarget, BuildTarget> neededDeps = missingSymbolsHandler.getNeededDependencies(ImmutableList.of(missingSymbolEvent)); assertEquals( "MissingSymbolsHandler failed to find the needed dependency.", neededDeps, ImmutableSetMultimap.of( BuildTargetFactory.newInstance(workspace.getDestPath(), "//java/com/example/b:b"), BuildTargetFactory.newInstance(workspace.getDestPath(), "//java/com/example/a:a"))); }
@Test public void testDeleteFiles() throws IOException { ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmpDir.getRoot().toPath()); String tracePath = String.format("%s/build.trace", BuckConstant.BUCK_TRACE_DIR); File traceFile = new File(tmpDir.getRoot(), tracePath); projectFilesystem.createParentDirs(tracePath); traceFile.createNewFile(); traceFile.setLastModified(0); for (int i = 0; i < 10; ++i) { File oldResult = new File( tmpDir.getRoot(), String.format("%s/build.100%d.trace", BuckConstant.BUCK_TRACE_DIR, i)); oldResult.createNewFile(); oldResult.setLastModified(TimeUnit.SECONDS.toMillis(i)); } ChromeTraceBuildListener listener = new ChromeTraceBuildListener( projectFilesystem, new FakeClock(1409702151000000000L), new ObjectMapper(), Locale.US, TimeZone.getTimeZone("America/Los_Angeles"), /* tracesToKeep */ 3, false); listener.deleteOldTraces(); ImmutableList<String> files = FluentIterable.from(Arrays.asList(projectFilesystem.listFiles(BuckConstant.BUCK_TRACE_DIR))) .transform( new Function<File, String>() { @Override public String apply(File input) { return input.getName(); } }) .toList(); assertEquals(4, files.size()); assertEquals( ImmutableSortedSet.of( "build.trace", "build.1009.trace", "build.1008.trace", "build.1007.trace"), ImmutableSortedSet.copyOf(files)); }
private void createFiles(ProjectFilesystem filesystem, String... paths) throws IOException { Path root = filesystem.getRootPath(); for (String path : paths) { Path resolved = root.resolve(path); Files.createDirectories(resolved.getParent()); Files.write(resolved, "".getBytes(UTF_8)); } }
@Test public void testPackagedResourceOnIndividualFile() throws IOException { ProjectFilesystem filesystem = new FakeProjectFilesystem(); PackagedResource packagedResource = PackagedResourceTestUtil.getPackagedResource(filesystem, "testdata/packaged_resource_one"); assertThat(packagedResource.getFilenamePath().toString(), is("packaged_resource_one")); assertThat( packagedResource.getResourceIdentifier(), is( "com.facebook.buck.testutil.packaged_resource.PackagedResourceTestUtil" + "#testdata/packaged_resource_one")); String fileContent = filesystem.readFileIfItExists(packagedResource.get()).get(); assertThat(fileContent, is("abc")); }