blob: 3302d33f7f6a9661105732de57626ea7683b0f71 [file] [log] [blame]
// Copyright 2014 Google Inc. All rights reserved.
//
// 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.google.devtools.build.lib.testutil;
import com.google.common.io.Files;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.util.BlazeClock;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Set;
/**
* This is a specialization of {@link ChattyAssertsTestCase} that's useful for
* implementing tests of the "foundation" library.
*/
public abstract class FoundationTestCase extends ChattyAssertsTestCase {
protected Path rootDirectory;
protected Path outputBase;
protected Path actionOutputBase;
// May be overridden by subclasses:
protected Reporter reporter;
protected EventCollector eventCollector;
private Scratch scratch;
// Individual tests can opt-out of this handler if they expect an error, by
// calling reporter.removeHandler(failFastHandler).
protected static final EventHandler failFastHandler = new EventHandler() {
@Override
public void handle(Event event) {
if (EventKind.ERRORS.contains(event.getKind())) {
fail(event.toString());
}
}
};
protected static final EventHandler printHandler = new EventHandler() {
@Override
public void handle(Event event) {
System.out.println(event);
}
};
@Override
protected void setUp() throws Exception {
super.setUp();
scratch = new Scratch(createFileSystem());
outputBase = scratchDir("/usr/local/google/_blaze_jrluser/FAKEMD5/");
rootDirectory = scratchDir("/" + TestConstants.TEST_WORKSPACE_DIRECTORY);
copySkylarkFilesIfExist();
actionOutputBase = scratchDir("/usr/local/google/_blaze_jrluser/FAKEMD5/action_out/");
eventCollector = new EventCollector(EventKind.ERRORS_AND_WARNINGS);
reporter = new Reporter(eventCollector);
reporter.addHandler(failFastHandler);
}
/*
* Creates the file system; override to inject FS behavior.
*/
protected FileSystem createFileSystem() {
return new InMemoryFileSystem(BlazeClock.instance());
}
private void copySkylarkFilesIfExist() throws IOException {
scratchFile(rootDirectory.getRelative("devtools/blaze/rules/BUILD").getPathString());
scratchFile(rootDirectory.getRelative("rules/BUILD").getPathString());
copySkylarkFilesIfExist("devtools/blaze/rules/staging", "devtools/blaze/rules/staging");
copySkylarkFilesIfExist("devtools/blaze/bazel/tools/build_rules", "rules");
}
private void copySkylarkFilesIfExist(String from, String to) throws IOException {
File rulesDir = new File(from);
if (rulesDir.exists() && rulesDir.isDirectory()) {
for (String fileName : rulesDir.list()) {
File file = new File(from + "/" + fileName);
if (file.isFile() && fileName.endsWith(".bzl")) {
String context = loadFile(file);
Path path = rootDirectory.getRelative(to + "/" + fileName);
if (path.exists()) {
overwriteScratchFile(path.getPathString(), context);
} else {
scratchFile(path.getPathString(), context);
}
}
}
}
}
@Override
protected void tearDown() throws Exception {
Thread.interrupted(); // Clear any interrupt pending against this thread,
// so that we don't cause later tests to fail.
super.tearDown();
}
/**
* A scratch filesystem that is completely in-memory. Since this file system
* is "cached" in a private (but *not* static) field in the test class,
* each testFoo method in junit sees a fresh filesystem.
*/
protected FileSystem scratchFS() {
return scratch.getFileSystem();
}
/**
* Create a scratch file in the scratch filesystem, with the given pathName,
* consisting of a set of lines. The method returns a Path instance for the
* scratch file.
*/
protected Path scratchFile(String pathName, String... lines)
throws IOException {
return scratch.file(pathName, lines);
}
/**
* Like {@code scratchFile}, but the file is first deleted if it already
* exists.
*/
protected Path overwriteScratchFile(String pathName, String... lines) throws IOException {
return scratch.overwriteFile(pathName, lines);
}
/**
* Deletes the specified scratch file, using the same specification as {@link Path#delete}.
*/
protected boolean deleteScratchFile(String pathName) throws IOException {
return scratch.deleteFile(pathName);
}
/**
* Create a scratch file in the given filesystem, with the given pathName,
* consisting of a set of lines. The method returns a Path instance for the
* scratch file.
*/
protected Path scratchFile(FileSystem fs, String pathName, String... lines)
throws IOException {
return scratch.file(fs, pathName, lines);
}
/**
* Create a scratch file in the given filesystem, with the given pathName,
* consisting of a set of lines. The method returns a Path instance for the
* scratch file.
*/
protected Path scratchFile(FileSystem fs, String pathName, byte[] content)
throws IOException {
return scratch.file(fs, pathName, content);
}
/**
* Create a directory in the scratch filesystem, with the given path name.
*/
public Path scratchDir(String pathName) throws IOException {
return scratch.dir(pathName);
}
/**
* If "expectedSuffix" is not a suffix of "actual", fails with an informative
* assertion.
*/
protected void assertEndsWith(String expectedSuffix, String actual) {
if (!actual.endsWith(expectedSuffix)) {
fail("\"" + actual + "\" does not end with "
+ "\"" + expectedSuffix + "\"");
}
}
/**
* If "expectedPrefix" is not a prefix of "actual", fails with an informative
* assertion.
*/
protected void assertStartsWith(String expectedPrefix, String actual) {
if (!actual.startsWith(expectedPrefix)) {
fail("\"" + actual + "\" does not start with "
+ "\"" + expectedPrefix + "\"");
}
}
// Mix-in assertions:
protected void assertNoEvents() {
JunitTestUtils.assertNoEvents(eventCollector);
}
protected Event assertContainsEvent(String expectedMessage) {
return JunitTestUtils.assertContainsEvent(eventCollector,
expectedMessage);
}
protected Event assertContainsEvent(String expectedMessage, Set<EventKind> kinds) {
return JunitTestUtils.assertContainsEvent(eventCollector,
expectedMessage,
kinds);
}
protected void assertContainsEventWithFrequency(String expectedMessage,
int expectedFrequency) {
JunitTestUtils.assertContainsEventWithFrequency(eventCollector, expectedMessage,
expectedFrequency);
}
protected void assertDoesNotContainEvent(String expectedMessage) {
JunitTestUtils.assertDoesNotContainEvent(eventCollector,
expectedMessage);
}
protected Event assertContainsEventWithWordsInQuotes(String... words) {
return JunitTestUtils.assertContainsEventWithWordsInQuotes(
eventCollector, words);
}
protected void assertContainsEventsInOrder(String... expectedMessages) {
JunitTestUtils.assertContainsEventsInOrder(eventCollector, expectedMessages);
}
@SuppressWarnings({"unchecked", "varargs"})
protected static <T> void assertContainsSublist(List<T> arguments,
T... expectedSublist) {
JunitTestUtils.assertContainsSublist(arguments, expectedSublist);
}
@SuppressWarnings({"unchecked", "varargs"})
protected static <T> void assertDoesNotContainSublist(List<T> arguments,
T... expectedSublist) {
JunitTestUtils.assertDoesNotContainSublist(arguments, expectedSublist);
}
protected static <T> void assertContainsSubset(Iterable<T> arguments,
Iterable<T> expectedSubset) {
JunitTestUtils.assertContainsSubset(arguments, expectedSubset);
}
protected String loadFile(File file) throws IOException {
return Files.toString(file, Charset.defaultCharset());
}
}