[rdct] launcher: add tests with remote-dev launcher placement

GitOrigin-RevId: ed36ec2ef878238ae918b40a808a76903456c600
This commit is contained in:
Ivan Pashchenko
2022-09-05 18:15:13 +02:00
committed by intellij-monorepo-bot
parent 715a2dbb57
commit cc8936d302
4 changed files with 196 additions and 87 deletions

View File

@@ -939,6 +939,21 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "futures"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.24"
@@ -946,6 +961,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@@ -954,12 +970,34 @@ version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
[[package]]
name = "futures-executor"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
[[package]]
name = "futures-macro"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.24"
@@ -972,14 +1010,23 @@ version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
[[package]]
name = "futures-timer"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]]
name = "futures-util"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
@@ -2157,6 +2204,31 @@ dependencies = [
"serde",
]
[[package]]
name = "rstest"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9c9dc66cc29792b663ffb5269be669f1613664e69ad56441fdb895c2347b930"
dependencies = [
"futures",
"futures-timer",
"rstest_macros",
"rustc_version",
]
[[package]]
name = "rstest_macros"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5015e68a0685a95ade3eee617ff7101ab6a3fc689203101ca16ebc16f2b89c66"
dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"rustc_version",
"syn",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
@@ -2175,6 +2247,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "rustfix"
version = "0.6.1"
@@ -3044,6 +3125,7 @@ dependencies = [
"log",
"native-dialog",
"path-absolutize",
"rstest",
"serde",
"serde_json",
"simplelog",

View File

@@ -36,6 +36,9 @@ anyhow = { version = "1.0.62", features = ["std", "backtrace"] }
cargo-deny = "0.12.2" # checks licenses / vulns
cargo-about = "0.5.1" # generates license report
[dev-dependencies]
rstest = "0.15.0"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9.3"

View File

@@ -1,18 +1,21 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
mod tests_util;
#[cfg(test)]
mod tests {
use std::process::ExitStatus;
use crate::tests_util::{IntellijMainDumpedLaunchParameters, prepare_test_env, run_launcher};
use crate::tests_util::{IntellijMainDumpedLaunchParameters, LayoutKind, prepare_test_env, run_launcher};
use rstest::*;
#[cfg(any(target_os = "macos", target_os = "linux"))]
use {
std::os::unix::process::ExitStatusExt
};
#[test]
fn correct_launcher_startup_test() {
let test = prepare_test_env();
#[rstest]
#[case::desktop(&LayoutKind::Desktop)]
#[case::remote_dev(&LayoutKind::RemoteDev)]
fn correct_launcher_startup_test(#[case] layout_kind: &LayoutKind) {
let test = prepare_test_env(layout_kind);
let status = &run_launcher(&test).exit_status;
let exit_status_string = exit_status_to_string(status);
@@ -24,6 +27,45 @@ mod tests {
);
}
#[rstest]
#[case::desktop(&LayoutKind::Desktop)]
#[case::remote_dev(&LayoutKind::RemoteDev)]
fn classpath_test(#[case] layout_kind: &LayoutKind) {
let dump = run_launcher_and_get_dump(layout_kind);
let classpath = &dump.systemProperties["java.class.path"];
assert!(
classpath.contains("app.jar"),
"app.jar is not present in classpath"
);
}
#[rstest]
#[case::desktop(&LayoutKind::Desktop)]
#[case::remote_dev(&LayoutKind::RemoteDev)]
fn additional_jvm_arguments_in_product_info_test(#[case] layout_kind: &LayoutKind) {
let dump = run_launcher_and_get_dump(layout_kind);
let idea_vendor_name_vm_option = dump.vmOptions.iter().find(|&vm| vm.starts_with("-Didea.vendor.name=JetBrains"));
assert!(
idea_vendor_name_vm_option.is_some(),
"Didn't find vmoption which should be set throught product-info.json additionJvmArguments field in launch section"
);
}
#[rstest]
#[case::desktop(&LayoutKind::Desktop)]
#[case::remote_dev(&LayoutKind::RemoteDev)]
fn arguments_test(#[case] layout_kind: &LayoutKind) {
let dump = run_launcher_and_get_dump(layout_kind);
let first_arg = &dump.cmdArguments[1];
assert_eq!(
first_arg,
"--output"
);
}
#[cfg(target_os = "windows")]
fn exit_status_to_string(status: &ExitStatus) -> String {
let exit_code = option_to_string(status.code());
@@ -45,43 +87,10 @@ mod tests {
}
}
#[test]
fn classpath_test() {
let dump = run_launcher_and_get_dump();
let classpath = &dump.systemProperties["java.class.path"];
assert!(
classpath.contains("app.jar"),
"app.jar is not present in classpath"
);
}
#[test]
fn additional_jvm_arguments_in_product_info_test() {
let dump = run_launcher_and_get_dump();
let idea_vendor_name_vm_option = dump.vmOptions.iter().find(|&vm| vm.starts_with("-Didea.vendor.name=JetBrains"));
assert!(
idea_vendor_name_vm_option.is_some(),
"Didn't find vmoption which should be set throught product-info.json additionJvmArguments field in launch section"
);
}
#[test]
fn arguments_test() {
let dump = run_launcher_and_get_dump();
let first_arg = &dump.cmdArguments[1];
assert_eq!(
first_arg,
"--output"
);
}
fn run_launcher_and_get_dump() -> IntellijMainDumpedLaunchParameters {
let test = prepare_test_env();
fn run_launcher_and_get_dump(layout_kind: &LayoutKind) -> IntellijMainDumpedLaunchParameters {
let test = prepare_test_env(layout_kind);
let result = run_launcher(&test);
assert!(result.exit_status.success(), "Launcher didn't exit successfully");
result.dump.expect("Launcher exited successfully, but there is no output")
}
}
}

View File

@@ -10,18 +10,18 @@ use std::process::{Command, ExitStatus, Output};
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Once;
use std::time::SystemTime;
use utils::get_path_from_env_var;
use utils::{get_path_from_env_var, PathExt};
static INIT: Once = Once::new();
static mut SHARED: Option<TestEnvironmentShared> = None;
pub struct TestEnvironment {
pub launcher_path: PathBuf,
pub working_dir: PathBuf
pub test_root_dir: PathBuf
}
pub fn prepare_test_env() -> TestEnvironment {
let result = match prepare_test_env_impl() {
pub fn prepare_test_env(layout_kind: &LayoutKind) -> TestEnvironment {
let result = match prepare_test_env_impl(layout_kind) {
Ok(x) => x,
Err(e) => {
panic!("Failed to prepare test environment: {e:?}")
@@ -31,7 +31,7 @@ pub fn prepare_test_env() -> TestEnvironment {
result
}
fn prepare_test_env_impl() -> Result<TestEnvironment> {
fn prepare_test_env_impl(layout_kind: &LayoutKind) -> Result<TestEnvironment> {
INIT.call_once(|| {
let shared = init_test_environment_once().expect("Failed to init shared test environment");
unsafe {
@@ -47,7 +47,8 @@ fn prepare_test_env_impl() -> Result<TestEnvironment> {
let test_number = shared.test_counter.fetch_add(1, Ordering::SeqCst);
// create tmp dir
let dir_name = shared.start_unix_timestamp_nanos + u128::from(test_number);
let timestamp = shared.start_unix_timestamp_nanos;
let dir_name = format!("{timestamp}_{test_number}");
let test_dir = env::temp_dir().join(dir_name.to_string());
create_dir(&test_dir).context(format!("Failed to create temp directory: {test_dir:?}"))?;
@@ -59,14 +60,14 @@ fn prepare_test_env_impl() -> Result<TestEnvironment> {
&product_info_path,
)?;
let launcher_dir = resolve_launcher_dir(&test_dir);
let launcher_dir = resolve_launcher_dir(&test_dir, layout_kind);
env::set_current_dir(&launcher_dir)?;
let launcher_path = launcher_dir.join("xplat-launcher");
let result = TestEnvironment {
launcher_path,
working_dir: test_dir
test_root_dir: test_dir
};
Ok(result)
@@ -179,6 +180,11 @@ pub fn get_child_dir(parent: &Path, prefix: &str) -> io::Result<PathBuf> {
));
}
pub enum LayoutKind {
Desktop,
RemoteDev
}
#[cfg(target_os = "linux")]
pub fn layout_launcher(
target_dir: &Path,
@@ -194,6 +200,10 @@ pub fn layout_launcher(
// │ └── idea64.vmoptions
// ├── lib/
// │ └── app.jar
// ├── plugins/
// │ └── remote-dev-server
// │ └── bin
// │ └── xplat-launcher
// ├── jbr/
// └── product-info.json
@@ -204,19 +214,19 @@ pub fn layout_launcher(
layout_launcher_impl(
target_dir,
vec![ "lib", "bin" ],
vec![
"bin/idea64.vmoptions",
"lib/test.jar"
],
HashMap::from([
vec![
(launcher.as_path(), "bin/xplat-launcher"),
(launcher.as_path(), "plugins/remote-dev-server/bin/xplat-launcher"),
(intellij_main_mock_jar, "lib/app.jar"),
(product_info_absolute_path, "product-info.json"),
]),
HashMap::from([
],
vec![
(jbr_absolute_path, "jbr")
])
]
)?;
Ok(())
@@ -240,6 +250,10 @@ pub fn layout_launcher(
// │ └── product-info.json
// ├── lib/
// │ └── app.jar
// ├── plugins/
// │ └── remote-dev-server
// │ └── bin
// │ └── xplat-launcher
// └── jbr/
let launcher = get_testing_binary_root(project_root).join("xplat-launcher");
@@ -249,24 +263,19 @@ pub fn layout_launcher(
layout_launcher_impl(
target_dir,
vec![
"Contents",
"Contents/Resources",
"Contents/lib",
"Contents/bin"
],
vec![
"Contents/bin/idea.vmoptions",
"Contents/lib/test.jar"
],
HashMap::from([
vec![
(launcher.as_path(), "Contents/bin/xplat-launcher"),
(launcher.as_path(), "Contents/plugins/remote-dev-server/bin/xplat-launcher"),
(intellij_main_mock_jar, "Contents/lib/app.jar"),
(product_info_absolute_path, "Contents/Resources/product-info.json"),
]),
HashMap::from([
],
vec![
(jbr_absolute_path, "Contents/jbr")
])
]
)?;
Ok(())
@@ -288,6 +297,10 @@ pub fn layout_launcher(
// ├── lib/
// │ └── app.jar
// ├── jbr/
// ├── plugins/
// │ └── remote-dev-server
// │ └── bin
// │ └── xplat-launcher
// └── product-info.json
let launcher = get_testing_binary_root(project_root).join("xplat-launcher.exe");
@@ -297,19 +310,19 @@ pub fn layout_launcher(
layout_launcher_impl(
target_dir,
vec![ "lib", "bin" ],
vec![
"bin/idea64.exe.vmoptions",
"lib/test.jar"
],
HashMap::from([
vec![
(launcher.as_path(), "bin/xplat-launcher.exe"),
(launcher.as_path(), "plugins/remote-dev-server/bin/xplat-launcher.exe"),
(intellij_main_mock_jar, "lib/app.jar"),
(product_info_absolute_path, "product-info.json"),
]),
HashMap::from([
],
vec![
(jbr_absolute_path, "jbr")
])
]
)?;
Ok(())
@@ -333,29 +346,27 @@ fn get_testing_binary_root(project_root: &Path) -> PathBuf {
fn layout_launcher_impl(
target_dir: &Path,
create_dirs: Vec<&str>,
create_files: Vec<&str>,
copy_files: HashMap<&Path, &str>,
symlink_dirs: HashMap<&Path, &str>
copy_files: Vec<(&Path, &str)>,
symlink_dirs: Vec<(&Path, &str)>
) -> Result<()> {
for dir in create_dirs {
let path = &target_dir.join(dir);
create_dir(path).context(format!("Failed to create dir {path:?}"))?;
}
for file in create_files {
let path = &target_dir.join(file);
File::create(path).context(format!("Failed to create file {path:?}"))?;
let target = &target_dir.join(file);
fs::create_dir_all(target.parent_or_err()?)?;
File::create(target).context(format!("Failed to create file {target:?}"))?;
}
for (source, target_relative) in copy_files {
let target = &target_dir.join(target_relative);
fs::create_dir_all(target.parent_or_err()?)?;
fs::copy(source, target).context(format!("Failed to copy from {source:?} to {target:?}"))?;
}
for (source, target_relative) in symlink_dirs {
let target = &target_dir.join(target_relative);
symlink(source, target)?;
fs::create_dir_all(target.parent_or_err()?)?;
symlink(source, target).context(format!("Failed to create symlink {target:?} pointing to {source:?}"))?;
}
Ok(())
@@ -377,11 +388,15 @@ fn symlink(source: &Path, target: &Path) -> Result<()> {
Ok(())
}
pub fn resolve_launcher_dir(test_dir: &Path) -> PathBuf {
if cfg!(target_os = "macos") {
test_dir.join("Contents").join("bin")
} else {
test_dir.join("bin")
pub fn resolve_launcher_dir(test_dir: &Path, layout_kind: &LayoutKind) -> PathBuf {
let root = match cfg!(target_os = "macos") {
true => test_dir.join("Contents"),
false => test_dir.to_path_buf()
};
match layout_kind {
LayoutKind::Desktop => root.join("bin"),
LayoutKind::RemoteDev => root.join("plugins/remote-dev-server/bin")
}
}
@@ -414,14 +429,14 @@ pub fn run_launcher(test: &TestEnvironment) -> LauncherRunResult {
}
fn run_launcher_impl(test: &TestEnvironment) -> Result<LauncherRunResult> {
let output_file = test.working_dir.join("output.json");
let output_file = test.test_root_dir.join("output.json");
let mut launcher_process = Command::new(&test.launcher_path)
.current_dir(&test.working_dir)
.current_dir(&test.test_root_dir)
.args(["--output", &output_file.to_string_lossy()])
.env(xplat_launcher::DO_NOT_SHOW_ERROR_UI_ENV_VAR, "1")
.spawn()
.expect("Failed to spawn launcher process");
.context("Failed to spawn launcher process")?;
let started = time::Instant::now();