/*
* 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.rust;
import static org.junit.Assert.assertThat;
import com.facebook.buck.testutil.integration.BuckBuildLog;
import com.facebook.buck.testutil.integration.ProjectWorkspace;
import com.facebook.buck.testutil.integration.TemporaryPaths;
import com.facebook.buck.testutil.integration.TestDataHelper;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.ProcessExecutor;
import java.io.IOException;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class RustBinaryIntegrationTest {
@Rule public TemporaryPaths tmp = new TemporaryPaths();
@Rule public ExpectedException thrown = ExpectedException.none();
@Before
public void ensureRustIsAvailable() throws IOException, InterruptedException {
RustAssumptions.assumeRustCompilerAvailable();
}
@Test
public void simpleBinary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
workspace.runBuckBuild("//:xyzzy").assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:xyzzy");
workspace.resetBuildLogFile();
ProcessExecutor.Result result =
workspace.runCommand(
workspace.resolve("buck-out/gen/xyzzy#binary,default/xyzzy").toString());
assertThat(result.getExitCode(), Matchers.equalTo(0));
assertThat(result.getStdout().get(), Matchers.containsString("Hello, world!"));
assertThat(result.getStderr().get(), Matchers.blankString());
}
@Test
public void simpleBinaryUnflavored() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
workspace
.runBuckCommand("build", "--config", "rust.unflavored_binaries=true", "//:xyzzy")
.assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:xyzzy");
workspace.resetBuildLogFile();
ProcessExecutor.Result result =
workspace.runCommand(workspace.resolve("buck-out/gen/xyzzy#binary/xyzzy").toString());
assertThat(result.getExitCode(), Matchers.equalTo(0));
assertThat(result.getStdout().get(), Matchers.containsString("Hello, world!"));
assertThat(result.getStderr().get(), Matchers.blankString());
}
@Test
public void simpleBinaryCheck() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
workspace.runBuckBuild("//:xyzzy#check").assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:xyzzy#check");
workspace.resetBuildLogFile();
thrown.expect(IOException.class);
thrown.expectMessage(Matchers.containsString("No such file or directory"));
workspace.runCommand(
workspace.resolve("buck-out/gen/xyzzy#binary,check,default/xyzzy").toString());
}
@Test
public void simpleBinaryWarnings() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
assertThat(
workspace.runBuckBuild("//:xyzzy").assertSuccess().getStderr(),
Matchers.allOf(
Matchers.containsString(
"warning: constant item is never used: `foo`, #[warn(dead_code)] on by default"),
Matchers.containsString(
"warning: constant `foo` should have an upper case name such as `FOO`,")));
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:xyzzy");
workspace.resetBuildLogFile();
}
@Test
public void simpleAliasedBinary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
workspace.runBuckBuild("//:xyzzy_aliased").assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:xyzzy_aliased");
workspace.resetBuildLogFile();
ProcessExecutor.Result result =
workspace.runCommand(
workspace.resolve("buck-out/gen/xyzzy_aliased#binary,default/xyzzy").toString());
assertThat(result.getExitCode(), Matchers.equalTo(0));
assertThat(result.getStdout().get(), Matchers.containsString("Hello, world!"));
assertThat(result.getStderr().get(), Matchers.blankString());
}
@Test
public void simpleCrateRootBinary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
workspace.runBuckBuild("//:xyzzy_crate_root").assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:xyzzy_crate_root");
workspace.resetBuildLogFile();
ProcessExecutor.Result result =
workspace.runCommand(
workspace
.resolve("buck-out/gen/xyzzy_crate_root#binary,default/xyzzy_crate_root")
.toString());
assertThat(result.getExitCode(), Matchers.equalTo(0));
assertThat(result.getStdout().get(), Matchers.containsString("Another top-level source"));
assertThat(result.getStderr().get(), Matchers.blankString());
}
@Test
public void binaryWithGeneratedSource() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_generated", tmp);
workspace.setUp();
workspace.runBuckBuild("//:thing").assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:thing");
workspace.resetBuildLogFile();
ProcessExecutor.Result result =
workspace.runCommand(
workspace.resolve("buck-out/gen/thing#binary,default/thing").toString());
assertThat(result.getExitCode(), Matchers.equalTo(0));
assertThat(
result.getStdout().get(), Matchers.containsString("info is: this is generated info"));
assertThat(result.getStderr().get(), Matchers.blankString());
}
@Test
public void rustBinaryCompilerArgs() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
assertThat(
workspace
.runBuckCommand(
"run", "--config", "rust.rustc_flags=--this-is-a-bad-option", "//:xyzzy")
.getStderr(),
Matchers.containsString("Unrecognized option: 'this-is-a-bad-option'."));
}
@Test
public void rustBinaryCompilerBinaryArgs() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
assertThat(
workspace
.runBuckCommand(
"run", "--config", "rust.rustc_binary_flags=--this-is-a-bad-option", "//:xyzzy")
.getStderr(),
Matchers.containsString("Unrecognized option: 'this-is-a-bad-option'."));
}
@Test
public void rustBinaryCompilerLibraryArgs() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
workspace
.runBuckCommand(
"run", "--config", "rust.rustc_library_flags=--this-is-a-bad-option", "//:xyzzy")
.assertSuccess();
}
@Test
public void rustBinaryCompilerArgs2() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
assertThat(
workspace
.runBuckCommand(
"run", "--config", "rust.rustc_flags=--verbose --this-is-a-bad-option", "//:xyzzy")
.getStderr(),
Matchers.containsString("Unrecognized option: 'this-is-a-bad-option'."));
}
@Test
public void rustBinaryRuleCompilerArgs() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:xyzzy_flags").getStderr(),
Matchers.containsString("Unrecognized option: 'this-is-a-bad-option'."));
}
@Test
public void buildAfterChangeWorks() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "simple_binary", tmp);
workspace.setUp();
workspace.runBuckBuild("//:xyzzy").assertSuccess();
workspace.writeContentsToPath(
workspace.getFileContents("main.rs") + "// this is a comment", "main.rs");
}
@Test
public void binaryWithLibrary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_library", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"),
Matchers.containsString("I have a message to deliver to you")));
}
@Test
public void binaryWithLibraryCheck() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_library", tmp);
workspace.setUp();
workspace.runBuckBuild("//:hello#check").assertSuccess();
BuckBuildLog buildLog = workspace.getBuildLog();
buildLog.assertTargetBuiltLocally("//:hello#check");
workspace.resetBuildLogFile();
// XXX check messenger.rmeta exists
thrown.expect(IOException.class);
thrown.expectMessage(Matchers.containsString("No such file or directory"));
workspace.runCommand(
workspace.resolve("buck-out/gen/hello#binary,check,default/hello").toString());
}
@Test
public void binaryWithSharedLibrary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_library", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello-shared").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"),
Matchers.containsString("I have a message to deliver to you")));
}
@Test
public void binaryWithHyphenatedLibrary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_library", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hyphen").assertSuccess().getStdout(),
Matchers.containsString("Hyphenated: Audrey fforbes-Hamilton"));
}
@Test
public void binaryWithAliasedLibrary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_library", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello_alias").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"),
Matchers.containsString("I have a message to deliver to you")));
}
@Test
public void binaryWithStaticCxxDep() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_cxx_dep", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:addtest_static").assertSuccess().getStdout(),
Matchers.containsString("10 + 15 = 25"));
}
@Test
public void binaryWithSharedCxxDep() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_cxx_dep", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:addtest_shared").assertSuccess().getStdout(),
Matchers.containsString("10 + 15 = 25"));
}
@Test
public void binaryWithPrebuiltStaticCxxDep() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_cxx_dep", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:addtest_prebuilt_static").assertSuccess().getStdout(),
Matchers.containsString("10 + 15 = 25"));
}
@Test
public void binaryWithPrebuiltSharedCxxDep() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_cxx_dep", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:addtest_prebuilt_shared").assertSuccess().getStdout(),
Matchers.containsString("10 + 15 = 25"));
}
@Test
public void binaryWithLibraryWithDep() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_library_with_dep", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"),
Matchers.containsString("I have a message to deliver to you"),
Matchers.containsString("thing handled")));
}
@Test
public void binaryWithLibraryWithTriangleDep() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_library_with_dep", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:transitive").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello from transitive"),
Matchers.containsString("I have a message to deliver to you"),
Matchers.containsString("thing handled")));
}
@Test
public void featureProvidedWorks() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "feature_test", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:with_feature").assertSuccess().getStdout(),
Matchers.containsString("Hello, world!"));
}
@Test
public void featureNotProvidedFails() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "feature_test", tmp);
workspace.setUp();
workspace.runBuckBuild("//:without_feature").assertFailure();
}
@Test
public void featureWithDoubleQuoteErrors() throws IOException, InterruptedException {
thrown.expect(HumanReadableException.class);
thrown.expectMessage(Matchers.containsString("contains an invalid feature name"));
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "feature_test", tmp);
workspace.setUp();
workspace.runBuckBuild("//:illegal_feature_name").assertFailure();
}
@Test
public void moduleImportsSuccessfully() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "module_import", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:greeter").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"),
Matchers.containsString("I have a message to deliver to you")));
}
@Test
public void underspecifiedSrcsErrors() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "module_import", tmp);
workspace.setUp();
assertThat(
workspace.runBuckBuild("//:greeter_fail").assertFailure().getStderr(),
Matchers.containsString("file not found for module `messenger`"));
}
@Test
public void binaryWithPrebuiltLibrary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_prebuilt", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"), Matchers.containsString("plain old foo")));
}
@Test
public void binaryWithAliasedPrebuiltLibrary() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_prebuilt", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello_alias").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"), Matchers.containsString("plain old foo")));
}
@Test
public void binaryWithPrebuiltLibraryWithDependency() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "binary_with_prebuilt", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello_foobar").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Hello, world!"),
Matchers.containsString("this is foo, and here is my friend bar"),
Matchers.containsString("plain old bar")));
}
@Test
public void cxxWithRustDependency() throws IOException, InterruptedException {
ProjectWorkspace workspace =
TestDataHelper.createProjectWorkspaceForScenario(this, "cxx_with_rust_dep", tmp);
workspace.setUp();
assertThat(
workspace.runBuckCommand("run", "//:hello").assertSuccess().getStdout(),
Matchers.allOf(
Matchers.containsString("Calling helloer"),
Matchers.containsString("I'm printing hello!"),
Matchers.containsString("Helloer called")));
}
}