From dcb8834ca29e5451a8f49359b9e8c3c114d18647 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 10:18:49 -0400 Subject: [PATCH 01/31] Explore testing on windows --- .../{amalthea-ci.yml => test-linux.yml} | 11 +++-- .github/workflows/test-windows.yml | 43 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) rename .github/workflows/{amalthea-ci.yml => test-linux.yml} (86%) create mode 100644 .github/workflows/test-windows.yml diff --git a/.github/workflows/amalthea-ci.yml b/.github/workflows/test-linux.yml similarity index 86% rename from .github/workflows/amalthea-ci.yml rename to .github/workflows/test-linux.yml index 5fa5d0593..2c924098a 100644 --- a/.github/workflows/amalthea-ci.yml +++ b/.github/workflows/test-linux.yml @@ -1,4 +1,4 @@ -name: "Amalthea Tests" +name: "Testing - Linux" on: push: @@ -26,20 +26,23 @@ jobs: - uses: dtolnay/rust-toolchain@nightly if: matrix.config.rust == 'nightly' + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + - name: Setup Build Environment run: | sudo apt-get update sudo apt-get install -y build-essential r-base-dev libsodium-dev - name: Build - id: amalthea-build + id: build run: | cargo build --verbose - # Ubuntu runners already have a version of R installed. # Unit tests "automatically" find and set `R_HOME` if it isn't set by # calling `R RHOME`. See the testing version of `start_r()` for this. - name: Run Unit Tests - id: amalthea-test + id: build run: | cargo test --verbose diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml new file mode 100644 index 000000000..567481892 --- /dev/null +++ b/.github/workflows/test-windows.yml @@ -0,0 +1,43 @@ +name: "Testing - Windows" + +on: + push: + branches: + - main + pull_request: + +jobs: + + windows: + runs-on: windows-latest + name: "Unit Tests on Windows (rust: ${{ matrix.config.rust }})" + strategy: + fail-fast: false + matrix: + config: + - { rust: 'stable' } + - { rust: 'nightly' } + timeout-minutes: 30 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@nightly + if: matrix.config.rust == 'nightly' + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - name: Build + id: build + run: | + cargo build --verbose + + # Unit tests "automatically" find and set `R_HOME` if it isn't set by + # calling `R RHOME`. See the testing version of `start_r()` for this. + - name: Run Unit Tests + id: build + run: | + cargo test --verbose From 2f9a43b38ad05cea0c3d10c27fd2e2d59f0bbfb7 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 10:20:23 -0400 Subject: [PATCH 02/31] Don't need `r-base-dev`, right? --- .github/workflows/test-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 2c924098a..3caaa2432 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -33,7 +33,7 @@ jobs: - name: Setup Build Environment run: | sudo apt-get update - sudo apt-get install -y build-essential r-base-dev libsodium-dev + sudo apt-get install -y build-essential libsodium-dev - name: Build id: build From a2f3da2f0fb93c47668632cc48ec1f9771571ee3 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 10:22:54 -0400 Subject: [PATCH 03/31] Fix typo --- .github/workflows/test-linux.yml | 2 +- .github/workflows/test-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 3caaa2432..29b1ebbfe 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -43,6 +43,6 @@ jobs: # Unit tests "automatically" find and set `R_HOME` if it isn't set by # calling `R RHOME`. See the testing version of `start_r()` for this. - name: Run Unit Tests - id: build + id: test run: | cargo test --verbose diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 567481892..013046675 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -38,6 +38,6 @@ jobs: # Unit tests "automatically" find and set `R_HOME` if it isn't set by # calling `R RHOME`. See the testing version of `start_r()` for this. - name: Run Unit Tests - id: build + id: test run: | cargo test --verbose From 0241dde0c95472f0a83c910fa35cb68508048317 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 10:34:06 -0400 Subject: [PATCH 04/31] I think `cargo build` before `cargo test` is redundant? --- .github/workflows/test-linux.yml | 5 ----- .github/workflows/test-windows.yml | 5 ----- 2 files changed, 10 deletions(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 29b1ebbfe..f67b51b9c 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -35,11 +35,6 @@ jobs: sudo apt-get update sudo apt-get install -y build-essential libsodium-dev - - name: Build - id: build - run: | - cargo build --verbose - # Unit tests "automatically" find and set `R_HOME` if it isn't set by # calling `R RHOME`. See the testing version of `start_r()` for this. - name: Run Unit Tests diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 013046675..395e5ae63 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -30,11 +30,6 @@ jobs: with: use-public-rspm: true - - name: Build - id: build - run: | - cargo build --verbose - # Unit tests "automatically" find and set `R_HOME` if it isn't set by # calling `R RHOME`. See the testing version of `start_r()` for this. - name: Run Unit Tests From 1f1488a7e3e0108d0f991e477f49ad75c8a4ef80 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 13:45:46 -0400 Subject: [PATCH 05/31] Write in binary mode to ensure `eol` is respected on Windows --- .../src/modules/positron/r_data_explorer.R | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/crates/ark/src/modules/positron/r_data_explorer.R b/crates/ark/src/modules/positron/r_data_explorer.R index 62807f478..3845dc006 100644 --- a/crates/ark/src/modules/positron/r_data_explorer.R +++ b/crates/ark/src/modules/positron/r_data_explorer.R @@ -327,13 +327,31 @@ export_selection <- function(x, format = c("csv", "tsv", "html"), include_header } write_delim <- function(x, delim, include_header) { + # Must open in binary write mode, otherwise even though we set + # `eol = "\n"`, on Windows it will still write `\r\n`. tmp <- tempfile() - defer(unlink(tmp)) + con <- file(tmp, open = "wb") - utils::write.table(x, tmp, sep = delim, row.names = FALSE, col.names = include_header, quote = FALSE, na = "") - # We use size - 1 because we don't want to read the last newline character - # that creates problems when pasting the content in spreadsheets - readChar(tmp, file.info(tmp)$size - 1L) + defer({ + close(con) + unlink(tmp) + }) + + utils::write.table( + x = x, + file = con, + sep = delim, + eol = "\n", + row.names = FALSE, + col.names = include_header, + quote = FALSE, + na = "" + ) + + # We use `size - 1` because we don't want to read the last newline character + # as that creates problems when pasting the content in spreadsheets. + # `file.info()$size` reports the size in bytes, hence `useBytes = TRUE`. + readChar(tmp, file.info(tmp)$size - 1L, useBytes = TRUE) } write_html <- function(x, include_header) { From a3f32935edfa86bbce9942c15f07374c648a0b7b Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 14:00:34 -0400 Subject: [PATCH 06/31] Ensure file is closed before getting file size --- .../src/modules/positron/r_data_explorer.R | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/crates/ark/src/modules/positron/r_data_explorer.R b/crates/ark/src/modules/positron/r_data_explorer.R index 3845dc006..d63ca6e78 100644 --- a/crates/ark/src/modules/positron/r_data_explorer.R +++ b/crates/ark/src/modules/positron/r_data_explorer.R @@ -327,15 +327,27 @@ export_selection <- function(x, format = c("csv", "tsv", "html"), include_header } write_delim <- function(x, delim, include_header) { - # Must open in binary write mode, otherwise even though we set - # `eol = "\n"`, on Windows it will still write `\r\n`. - tmp <- tempfile() - con <- file(tmp, open = "wb") + path <- tempfile() + defer(unlink(path)) - defer({ - close(con) - unlink(tmp) - }) + write_delim_impl(x, path, delim, include_header) + + # We use `size - 1` because we don't want to read the last newline character + # as that creates problems when pasting the content in spreadsheets. + # `file.info()$size` reports the size in bytes, hence `useBytes = TRUE`. + readChar(path, file.info(path)$size - 1L, useBytes = TRUE) +} + +write_delim_impl <- function(x, path, delim, include_header) { + # Scope the `con` lifetime to just this helper. + # We need to `close()` the connection before we try and get the + # `file.info()$size`. + + # Must open in binary write mode, otherwise even though we set + # `eol = "\n"` on Windows it will still write `\r\n` due to the C + # level `vfprintf()` call. + con <- file(path, open = "wb") + defer(close(con)) utils::write.table( x = x, @@ -347,11 +359,6 @@ write_delim <- function(x, delim, include_header) { quote = FALSE, na = "" ) - - # We use `size - 1` because we don't want to read the last newline character - # as that creates problems when pasting the content in spreadsheets. - # `file.info()$size` reports the size in bytes, hence `useBytes = TRUE`. - readChar(tmp, file.info(tmp)$size - 1L, useBytes = TRUE) } write_html <- function(x, include_header) { From 23dc802cbbed7c790543981b8b7145514a328d63 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 14:15:08 -0400 Subject: [PATCH 07/31] Can it even roundtrip correctly? --- crates/ark/src/data_explorer/format.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/ark/src/data_explorer/format.rs b/crates/ark/src/data_explorer/format.rs index 04855c9f1..2cb2d55bb 100644 --- a/crates/ark/src/data_explorer/format.rs +++ b/crates/ark/src/data_explorer/format.rs @@ -750,18 +750,19 @@ mod tests { ColumnValue::FormattedValue("aa".to_string()), ]); + options.max_value_length = 1000; let data = harp::parse_eval_global(r#"c("ボルテックス")"#).unwrap(); let formatted = format_column(data.sexp, &options); assert_eq!(formatted, vec![ColumnValue::FormattedValue( - "ボルテ".to_string() + "ボルテックス".to_string() ),]); - options.max_value_length = 4; - let data = harp::parse_eval_global(r#"c("नमस्ते")"#).unwrap(); - let formatted = format_column(data.sexp, &options); - assert_eq!(formatted, vec![ColumnValue::FormattedValue( - "नमस्".to_string() - ),]); + // options.max_value_length = 4; + // let data = harp::parse_eval_global(r#"c("नमस्ते")"#).unwrap(); + // let formatted = format_column(data.sexp, &options); + // assert_eq!(formatted, vec![ColumnValue::FormattedValue( + // "नमस्".to_string() + // ),]); }) } } From f2af98eaa4c629adc9c8162df0aa846b8b1cd903 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 14:36:45 -0400 Subject: [PATCH 08/31] Did it get into R right? --- crates/ark/src/data_explorer/format.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/ark/src/data_explorer/format.rs b/crates/ark/src/data_explorer/format.rs index 2cb2d55bb..1e51bacd9 100644 --- a/crates/ark/src/data_explorer/format.rs +++ b/crates/ark/src/data_explorer/format.rs @@ -751,11 +751,15 @@ mod tests { ]); options.max_value_length = 1000; - let data = harp::parse_eval_global(r#"c("ボルテックス")"#).unwrap(); - let formatted = format_column(data.sexp, &options); - assert_eq!(formatted, vec![ColumnValue::FormattedValue( - "ボルテックス".to_string() - ),]); + let _ = harp::parse_eval_global(r#"x <- c("ボルテックス")"#).unwrap(); + let data = harp::parse_eval_global(r#"Encoding(x)"#).unwrap(); + let data = String::try_from(data).unwrap(); + let _ = harp::parse_eval_global(r#"rm(x)"#).unwrap(); + assert_eq!(data, "UTF-8".to_string()); + // let formatted = format_column(data.sexp, &options); + // assert_eq!(formatted, vec![ColumnValue::FormattedValue( + // "ボルテックス".to_string() + // ),]); // options.max_value_length = 4; // let data = harp::parse_eval_global(r#"c("नमस्ते")"#).unwrap(); From b3f82694f71b56c2c6c6a4ad2a4367fa1a1e21a2 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 15:10:06 -0400 Subject: [PATCH 09/31] See if `&str` to `RObject` loses encoding --- crates/ark/src/data_explorer/format.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/crates/ark/src/data_explorer/format.rs b/crates/ark/src/data_explorer/format.rs index 1e51bacd9..45a87c0b0 100644 --- a/crates/ark/src/data_explorer/format.rs +++ b/crates/ark/src/data_explorer/format.rs @@ -439,6 +439,8 @@ impl Into for FormattedValue { #[cfg(test)] mod tests { + use harp::utils::r_envir_set; + use super::*; use crate::fixtures::r_test; @@ -751,11 +753,18 @@ mod tests { ]); options.max_value_length = 1000; - let _ = harp::parse_eval_global(r#"x <- c("ボルテックス")"#).unwrap(); - let data = harp::parse_eval_global(r#"Encoding(x)"#).unwrap(); + let text = RObject::from(r#"x <- c("ボルテックス")"#); + unsafe { r_envir_set("text", text.sexp, R_GlobalEnv) }; + let data = harp::parse_eval_global(r#"Encoding(text)"#).unwrap(); let data = String::try_from(data).unwrap(); - let _ = harp::parse_eval_global(r#"rm(x)"#).unwrap(); + let _ = harp::parse_eval_global(r#"rm(text)"#).unwrap(); assert_eq!(data, "UTF-8".to_string()); + + // let _ = harp::parse_eval_global(r#"x <- c("ボルテックス")"#).unwrap(); + // let data = harp::parse_eval_global(r#"Encoding(x)"#).unwrap(); + // let data = String::try_from(data).unwrap(); + // let _ = harp::parse_eval_global(r#"rm(x)"#).unwrap(); + // assert_eq!(data, "UTF-8".to_string()); // let formatted = format_column(data.sexp, &options); // assert_eq!(formatted, vec![ColumnValue::FormattedValue( // "ボルテックス".to_string() From 62d61d5ae8d1dfa44cc9a5d7ce96b1afa0766de5 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 15:33:22 -0400 Subject: [PATCH 10/31] What is the encoding? --- crates/ark/src/data_explorer/format.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/ark/src/data_explorer/format.rs b/crates/ark/src/data_explorer/format.rs index 45a87c0b0..d514b8546 100644 --- a/crates/ark/src/data_explorer/format.rs +++ b/crates/ark/src/data_explorer/format.rs @@ -760,6 +760,10 @@ mod tests { let _ = harp::parse_eval_global(r#"rm(text)"#).unwrap(); assert_eq!(data, "UTF-8".to_string()); + let data = harp::parse_eval_global("Sys.getlocale()").unwrap(); + let data = String::try_from(data).unwrap(); + assert_eq!(data, "wrong".to_string()); + // let _ = harp::parse_eval_global(r#"x <- c("ボルテックス")"#).unwrap(); // let data = harp::parse_eval_global(r#"Encoding(x)"#).unwrap(); // let data = String::try_from(data).unwrap(); From e1d28e4382018f8d4d744898a66eda0d8402e6d4 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 15:55:24 -0400 Subject: [PATCH 11/31] What about the windows version? --- crates/ark/src/data_explorer/format.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/ark/src/data_explorer/format.rs b/crates/ark/src/data_explorer/format.rs index d514b8546..9261a4484 100644 --- a/crates/ark/src/data_explorer/format.rs +++ b/crates/ark/src/data_explorer/format.rs @@ -760,7 +760,13 @@ mod tests { let _ = harp::parse_eval_global(r#"rm(text)"#).unwrap(); assert_eq!(data, "UTF-8".to_string()); - let data = harp::parse_eval_global("Sys.getlocale()").unwrap(); + // let data = harp::parse_eval_global("Sys.getlocale()").unwrap(); + // let data = String::try_from(data).unwrap(); + // assert_eq!(data, "wrong".to_string()); + + let data = + harp::parse_eval_global("paste0(capture.output(sessionInfo()), collapse = ' ')") + .unwrap(); let data = String::try_from(data).unwrap(); assert_eq!(data, "wrong".to_string()); From 86a3611f77bd6159b443b3da57d8e200e0d59136 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 16:14:59 -0400 Subject: [PATCH 12/31] make sure build.rs is actually being called --- crates/ark/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/ark/build.rs b/crates/ark/build.rs index cf0a1a9f3..762c97c86 100644 --- a/crates/ark/build.rs +++ b/crates/ark/build.rs @@ -35,6 +35,8 @@ fn main() { let build_date = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true); println!("cargo:rustc-env=BUILD_DATE={}", build_date); + panic!("oh no"); + // Embed an Application Manifest file on Windows. // Documented to do nothing on non-Windows. let resource = Path::new("resources") From c8b373483b0aa3aca81ad529a3ee63cfbba07712 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 16:23:11 -0400 Subject: [PATCH 13/31] panic after to get stderr output --- crates/ark/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ark/build.rs b/crates/ark/build.rs index 762c97c86..ac7ec4fc2 100644 --- a/crates/ark/build.rs +++ b/crates/ark/build.rs @@ -35,12 +35,12 @@ fn main() { let build_date = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true); println!("cargo:rustc-env=BUILD_DATE={}", build_date); - panic!("oh no"); - // Embed an Application Manifest file on Windows. // Documented to do nothing on non-Windows. let resource = Path::new("resources") .join("manifest") .join("ark-manifest.rc"); embed_resource::compile(resource, embed_resource::NONE); + + panic!("oh no"); } From 09c02c877d99d000c6440da28b799e79244d6d2e Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 16:49:59 -0400 Subject: [PATCH 14/31] Remove panic --- crates/ark/build.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/ark/build.rs b/crates/ark/build.rs index ac7ec4fc2..cf0a1a9f3 100644 --- a/crates/ark/build.rs +++ b/crates/ark/build.rs @@ -41,6 +41,4 @@ fn main() { .join("manifest") .join("ark-manifest.rc"); embed_resource::compile(resource, embed_resource::NONE); - - panic!("oh no"); } From e827c7f943551491c798d974523548b6d9a0f044 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 17:07:56 -0400 Subject: [PATCH 15/31] does this happen to work? --- crates/ark/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ark/build.rs b/crates/ark/build.rs index cf0a1a9f3..e3dac5da0 100644 --- a/crates/ark/build.rs +++ b/crates/ark/build.rs @@ -40,5 +40,5 @@ fn main() { let resource = Path::new("resources") .join("manifest") .join("ark-manifest.rc"); - embed_resource::compile(resource, embed_resource::NONE); + embed_resource::compile_for_tests(resource, embed_resource::NONE); } From 6ada120a2e2483ebe4d6d42fe957c9770d1234a8 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Wed, 25 Sep 2024 17:18:14 -0400 Subject: [PATCH 16/31] what does an integration test report? --- crates/ark/build.rs | 2 +- crates/ark/src/data_explorer/format.rs | 24 ++++++++++++------------ crates/ark/tests/data_explorer.rs | 5 +++++ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/crates/ark/build.rs b/crates/ark/build.rs index e3dac5da0..cf0a1a9f3 100644 --- a/crates/ark/build.rs +++ b/crates/ark/build.rs @@ -40,5 +40,5 @@ fn main() { let resource = Path::new("resources") .join("manifest") .join("ark-manifest.rc"); - embed_resource::compile_for_tests(resource, embed_resource::NONE); + embed_resource::compile(resource, embed_resource::NONE); } diff --git a/crates/ark/src/data_explorer/format.rs b/crates/ark/src/data_explorer/format.rs index 9261a4484..9282228c9 100644 --- a/crates/ark/src/data_explorer/format.rs +++ b/crates/ark/src/data_explorer/format.rs @@ -752,23 +752,23 @@ mod tests { ColumnValue::FormattedValue("aa".to_string()), ]); - options.max_value_length = 1000; - let text = RObject::from(r#"x <- c("ボルテックス")"#); - unsafe { r_envir_set("text", text.sexp, R_GlobalEnv) }; - let data = harp::parse_eval_global(r#"Encoding(text)"#).unwrap(); - let data = String::try_from(data).unwrap(); - let _ = harp::parse_eval_global(r#"rm(text)"#).unwrap(); - assert_eq!(data, "UTF-8".to_string()); + // options.max_value_length = 1000; + // let text = RObject::from(r#"x <- c("ボルテックス")"#); + // unsafe { r_envir_set("text", text.sexp, R_GlobalEnv) }; + // let data = harp::parse_eval_global(r#"Encoding(text)"#).unwrap(); + // let data = String::try_from(data).unwrap(); + // let _ = harp::parse_eval_global(r#"rm(text)"#).unwrap(); + // assert_eq!(data, "UTF-8".to_string()); // let data = harp::parse_eval_global("Sys.getlocale()").unwrap(); // let data = String::try_from(data).unwrap(); // assert_eq!(data, "wrong".to_string()); - let data = - harp::parse_eval_global("paste0(capture.output(sessionInfo()), collapse = ' ')") - .unwrap(); - let data = String::try_from(data).unwrap(); - assert_eq!(data, "wrong".to_string()); + // let data = + // harp::parse_eval_global("paste0(capture.output(sessionInfo()), collapse = ' ')") + // .unwrap(); + // let data = String::try_from(data).unwrap(); + // assert_eq!(data, "wrong".to_string()); // let _ = harp::parse_eval_global(r#"x <- c("ボルテックス")"#).unwrap(); // let data = harp::parse_eval_global(r#"Encoding(x)"#).unwrap(); diff --git a/crates/ark/tests/data_explorer.rs b/crates/ark/tests/data_explorer.rs index a924195aa..64127eba4 100644 --- a/crates/ark/tests/data_explorer.rs +++ b/crates/ark/tests/data_explorer.rs @@ -1808,6 +1808,11 @@ fn test_histogram() { #[test] fn test_frequency_table() { r_test(|| { + let data = harp::parse_eval_global("paste0(capture.output(sessionInfo()), collapse = ' ')") + .unwrap(); + let data = String::try_from(data).unwrap(); + assert_eq!(data, "wrong".to_string()); + let socket = open_data_explorer_from_expression("data.frame(x = rep(letters[1:10], 10:1))", None) .unwrap(); From edbae6c660e278ac5c03d10de0c323a75e0896da Mon Sep 17 00:00:00 2001 From: DavisVaughan Date: Thu, 26 Sep 2024 16:58:20 -0400 Subject: [PATCH 17/31] Use `compile_for_everything()` to embed the manifest in the test binary And also do this for the harp test binary, which starts R and tests UTF-8 related capabilities. --- Cargo.lock | 14 +++--- crates/ark/Cargo.toml | 2 +- crates/ark/build.rs | 17 ++++++- crates/ark/resources/manifest/ark-manifest.rc | 4 +- crates/ark/src/data_explorer/format.rs | 48 +++++-------------- crates/ark/src/sys/windows.rs | 1 + crates/ark/src/sys/windows/locale.rs | 33 +++++++++++++ crates/ark/tests/data_explorer.rs | 5 -- crates/harp/Cargo.toml | 3 ++ crates/harp/build.rs | 22 +++++++++ .../harp/resources/manifest/harp-manifest.rc | 13 +++++ .../harp/resources/manifest/harp.exe.manifest | 40 ++++++++++++++++ crates/harp/src/sys/windows.rs | 1 + crates/harp/src/sys/windows/locale.rs | 33 +++++++++++++ 14 files changed, 186 insertions(+), 50 deletions(-) create mode 100644 crates/ark/src/sys/windows/locale.rs create mode 100644 crates/harp/build.rs create mode 100644 crates/harp/resources/manifest/harp-manifest.rc create mode 100644 crates/harp/resources/manifest/harp.exe.manifest create mode 100644 crates/harp/src/sys/windows/locale.rs diff --git a/Cargo.lock b/Cargo.lock index 99366d76a..d3efd7f82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -830,11 +830,12 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "embed-resource" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" +checksum = "f4e24052d7be71f0efb50c201557f6fe7d237cfd5a64fd5bcd7fd8fe32dbbffa" dependencies = [ "cc", + "memchr", "rustc_version", "toml 0.8.8", "vswhom", @@ -1108,6 +1109,7 @@ dependencies = [ "anyhow", "cfg-if", "ctor", + "embed-resource", "harp-macros", "itertools", "libc", @@ -1639,9 +1641,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -3730,9 +3732,9 @@ dependencies = [ [[package]] name = "winreg" -version = "0.51.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ "cfg-if", "windows-sys 0.48.0", diff --git a/crates/ark/Cargo.toml b/crates/ark/Cargo.toml index 1a80c1b35..ee3a71a0c 100644 --- a/crates/ark/Cargo.toml +++ b/crates/ark/Cargo.toml @@ -68,7 +68,7 @@ harp = { path = "../harp", features = ["testing"]} [build-dependencies] chrono = "0.4.23" -embed-resource = "2.4.0" +embed-resource = "2.5.0" [package.metadata.generate-rpm] assets = [{ source = "target/release/ark", dest = "/usr/bin/ark", mode = "755" }] diff --git a/crates/ark/build.rs b/crates/ark/build.rs index cf0a1a9f3..b6a138da0 100644 --- a/crates/ark/build.rs +++ b/crates/ark/build.rs @@ -37,8 +37,23 @@ fn main() { // Embed an Application Manifest file on Windows. // Documented to do nothing on non-Windows. + // We also do this for harp to support its unit tests. + // + // We can't just use `compile()`, as that uses `cargo:rustc-link-arg-bins`, + // which targets the main `ark.exe` (good) but not the test binaries (bad). + // We need the application manifest to get embedded into the ark/harp test + // binaries too, so that the instance of R started by our tests also has + // UTF-8 support. + // + // We can't use `compile_for_tests()` because `cargo:rustc-link-arg-tests` + // only targets integration tests right now, not unit tests. + // https://github.com/rust-lang/cargo/issues/10937 + // + // Instead we use `compile_for_everything()` which uses the kitchen sink + // instruction of `cargo:rustc-link-arg`, and that seems to work. + // https://github.com/nabijaczleweli/rust-embed-resource/issues/69 let resource = Path::new("resources") .join("manifest") .join("ark-manifest.rc"); - embed_resource::compile(resource, embed_resource::NONE); + embed_resource::compile_for_everything(resource, embed_resource::NONE); } diff --git a/crates/ark/resources/manifest/ark-manifest.rc b/crates/ark/resources/manifest/ark-manifest.rc index 571caf3f7..26e00deb8 100644 --- a/crates/ark/resources/manifest/ark-manifest.rc +++ b/crates/ark/resources/manifest/ark-manifest.rc @@ -1,3 +1,5 @@ +// Autogenerated, do not modify! + // This is a C file that embed-resource compiles for us. // It helps embed our Windows Application Manifest file. // https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests @@ -7,5 +9,5 @@ // https://github.com/nabijaczleweli/rust-embed-resource/issues/11#issuecomment-779295722 #include -// The `1` is a `resource_id` that specifies ark as an executable file +// The `1` is a `resource_id` that specifies us as an executable file 1 RT_MANIFEST "ark.exe.manifest" diff --git a/crates/ark/src/data_explorer/format.rs b/crates/ark/src/data_explorer/format.rs index 9282228c9..04855c9f1 100644 --- a/crates/ark/src/data_explorer/format.rs +++ b/crates/ark/src/data_explorer/format.rs @@ -439,8 +439,6 @@ impl Into for FormattedValue { #[cfg(test)] mod tests { - use harp::utils::r_envir_set; - use super::*; use crate::fixtures::r_test; @@ -752,40 +750,18 @@ mod tests { ColumnValue::FormattedValue("aa".to_string()), ]); - // options.max_value_length = 1000; - // let text = RObject::from(r#"x <- c("ボルテックス")"#); - // unsafe { r_envir_set("text", text.sexp, R_GlobalEnv) }; - // let data = harp::parse_eval_global(r#"Encoding(text)"#).unwrap(); - // let data = String::try_from(data).unwrap(); - // let _ = harp::parse_eval_global(r#"rm(text)"#).unwrap(); - // assert_eq!(data, "UTF-8".to_string()); - - // let data = harp::parse_eval_global("Sys.getlocale()").unwrap(); - // let data = String::try_from(data).unwrap(); - // assert_eq!(data, "wrong".to_string()); - - // let data = - // harp::parse_eval_global("paste0(capture.output(sessionInfo()), collapse = ' ')") - // .unwrap(); - // let data = String::try_from(data).unwrap(); - // assert_eq!(data, "wrong".to_string()); - - // let _ = harp::parse_eval_global(r#"x <- c("ボルテックス")"#).unwrap(); - // let data = harp::parse_eval_global(r#"Encoding(x)"#).unwrap(); - // let data = String::try_from(data).unwrap(); - // let _ = harp::parse_eval_global(r#"rm(x)"#).unwrap(); - // assert_eq!(data, "UTF-8".to_string()); - // let formatted = format_column(data.sexp, &options); - // assert_eq!(formatted, vec![ColumnValue::FormattedValue( - // "ボルテックス".to_string() - // ),]); - - // options.max_value_length = 4; - // let data = harp::parse_eval_global(r#"c("नमस्ते")"#).unwrap(); - // let formatted = format_column(data.sexp, &options); - // assert_eq!(formatted, vec![ColumnValue::FormattedValue( - // "नमस्".to_string() - // ),]); + let data = harp::parse_eval_global(r#"c("ボルテックス")"#).unwrap(); + let formatted = format_column(data.sexp, &options); + assert_eq!(formatted, vec![ColumnValue::FormattedValue( + "ボルテ".to_string() + ),]); + + options.max_value_length = 4; + let data = harp::parse_eval_global(r#"c("नमस्ते")"#).unwrap(); + let formatted = format_column(data.sexp, &options); + assert_eq!(formatted, vec![ColumnValue::FormattedValue( + "नमस्".to_string() + ),]); }) } } diff --git a/crates/ark/src/sys/windows.rs b/crates/ark/src/sys/windows.rs index 6651ef627..19571fe85 100644 --- a/crates/ark/src/sys/windows.rs +++ b/crates/ark/src/sys/windows.rs @@ -8,6 +8,7 @@ pub mod console; pub mod control; pub mod interface; +mod locale; pub mod path; pub mod signals; mod strings; diff --git a/crates/ark/src/sys/windows/locale.rs b/crates/ark/src/sys/windows/locale.rs new file mode 100644 index 000000000..df0ecf72d --- /dev/null +++ b/crates/ark/src/sys/windows/locale.rs @@ -0,0 +1,33 @@ +/* + * locale.rs + * + * Copyright (C) 2024 Posit Software, PBC. All rights reserved. + * + */ + +#[cfg(test)] +mod tests { + use crate::test::r_test; + + #[test] + fn test_locale() { + // These tests assert that we've embedded our Application Manifest file correctly in `build.rs` + r_test(|| { + let latin1 = harp::parse_eval_base("l10n_info()$`Latin-1`").unwrap(); + let latin1 = bool::try_from(latin1).unwrap(); + assert!(!latin1); + + let utf8 = harp::parse_eval_base("l10n_info()$`UTF-8`").unwrap(); + let utf8 = bool::try_from(utf8).unwrap(); + assert!(utf8); + + let codepage = harp::parse_eval_base("l10n_info()$codepage").unwrap(); + let codepage = i32::try_from(codepage).unwrap(); + assert_eq!(codepage, 65001); + + let system_codepage = harp::parse_eval_base("l10n_info()$system.codepage").unwrap(); + let system_codepage = i32::try_from(system_codepage).unwrap(); + assert_eq!(system_codepage, 65001); + }) + } +} diff --git a/crates/ark/tests/data_explorer.rs b/crates/ark/tests/data_explorer.rs index 64127eba4..a924195aa 100644 --- a/crates/ark/tests/data_explorer.rs +++ b/crates/ark/tests/data_explorer.rs @@ -1808,11 +1808,6 @@ fn test_histogram() { #[test] fn test_frequency_table() { r_test(|| { - let data = harp::parse_eval_global("paste0(capture.output(sessionInfo()), collapse = ' ')") - .unwrap(); - let data = String::try_from(data).unwrap(); - assert_eq!(data, "wrong".to_string()); - let socket = open_data_explorer_from_expression("data.frame(x = rep(letters[1:10], 10:1))", None) .unwrap(); diff --git a/crates/harp/Cargo.toml b/crates/harp/Cargo.toml index 0a10d3d2f..3e4542d54 100644 --- a/crates/harp/Cargo.toml +++ b/crates/harp/Cargo.toml @@ -29,5 +29,8 @@ serde_json = { version = "1.0.94", features = ["preserve_order"]} rust-embed = "8.2.0" tracing-error = "0.2.0" +[build-dependencies] +embed-resource = "2.5.0" + [features] testing = [] diff --git a/crates/harp/build.rs b/crates/harp/build.rs new file mode 100644 index 000000000..b2b3f3d15 --- /dev/null +++ b/crates/harp/build.rs @@ -0,0 +1,22 @@ +// +// build.rs +// +// Copyright (C) 2024 Posit Software, PBC. All rights reserved. +// +// + +use std::path::Path; +extern crate embed_resource; + +fn main() { + // Embed an Application Manifest file on Windows. + // Documented to do nothing on non-Windows. + // We also do this for ark. + // We don't generate a main `harp.exe` binary, but `cargo test` does generate a `harp-*.exe` + // binary for unit testing, and those unit tests also start R and test UTF-8 related capabilities! + // So we need that test executable to include a manifest file too. + let resource = Path::new("resources") + .join("manifest") + .join("harp-manifest.rc"); + embed_resource::compile_for_everything(resource, embed_resource::NONE); +} diff --git a/crates/harp/resources/manifest/harp-manifest.rc b/crates/harp/resources/manifest/harp-manifest.rc new file mode 100644 index 000000000..dc8649797 --- /dev/null +++ b/crates/harp/resources/manifest/harp-manifest.rc @@ -0,0 +1,13 @@ +// Autogenerated, do not modify! + +// This is a C file that embed-resource compiles for us. +// It helps embed our Windows Application Manifest file. +// https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests +// https://learn.microsoft.com/en-us/cpp/build/reference/manifest-create-side-by-side-assembly-manifest?view=msvc-170 + +// This defines `RT_MANIFEST` to `24`. embed-resource should know how to ensure the header is available. +// https://github.com/nabijaczleweli/rust-embed-resource/issues/11#issuecomment-779295722 +#include + +// The `1` is a `resource_id` that specifies us as an executable file +1 RT_MANIFEST "harp.exe.manifest" diff --git a/crates/harp/resources/manifest/harp.exe.manifest b/crates/harp/resources/manifest/harp.exe.manifest new file mode 100644 index 000000000..e3bab77fd --- /dev/null +++ b/crates/harp/resources/manifest/harp.exe.manifest @@ -0,0 +1,40 @@ + + + + + + harp + + + + + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crates/harp/src/sys/windows.rs b/crates/harp/src/sys/windows.rs index 95932ce46..dff45856b 100644 --- a/crates/harp/src/sys/windows.rs +++ b/crates/harp/src/sys/windows.rs @@ -7,4 +7,5 @@ pub mod library; pub mod line_ending; +mod locale; pub mod polled_events; diff --git a/crates/harp/src/sys/windows/locale.rs b/crates/harp/src/sys/windows/locale.rs new file mode 100644 index 000000000..df0ecf72d --- /dev/null +++ b/crates/harp/src/sys/windows/locale.rs @@ -0,0 +1,33 @@ +/* + * locale.rs + * + * Copyright (C) 2024 Posit Software, PBC. All rights reserved. + * + */ + +#[cfg(test)] +mod tests { + use crate::test::r_test; + + #[test] + fn test_locale() { + // These tests assert that we've embedded our Application Manifest file correctly in `build.rs` + r_test(|| { + let latin1 = harp::parse_eval_base("l10n_info()$`Latin-1`").unwrap(); + let latin1 = bool::try_from(latin1).unwrap(); + assert!(!latin1); + + let utf8 = harp::parse_eval_base("l10n_info()$`UTF-8`").unwrap(); + let utf8 = bool::try_from(utf8).unwrap(); + assert!(utf8); + + let codepage = harp::parse_eval_base("l10n_info()$codepage").unwrap(); + let codepage = i32::try_from(codepage).unwrap(); + assert_eq!(codepage, 65001); + + let system_codepage = harp::parse_eval_base("l10n_info()$system.codepage").unwrap(); + let system_codepage = i32::try_from(system_codepage).unwrap(); + assert_eq!(system_codepage, 65001); + }) + } +} From a8c175eb14f90fb4670f33428c85dc9ff02c3283 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Thu, 26 Sep 2024 17:18:57 -0400 Subject: [PATCH 18/31] Try removing some extra installs --- .github/workflows/test-linux.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index f67b51b9c..4c3e11b19 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -33,7 +33,6 @@ jobs: - name: Setup Build Environment run: | sudo apt-get update - sudo apt-get install -y build-essential libsodium-dev # Unit tests "automatically" find and set `R_HOME` if it isn't set by # calling `R RHOME`. See the testing version of `start_r()` for this. From cd811421898620022b1e29335066c1a046add542 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Thu, 26 Sep 2024 17:32:16 -0400 Subject: [PATCH 19/31] Create unified `test.yml` --- .github/workflows/test-linux.yml | 10 +++------- .github/workflows/test-windows.yml | 10 +++------- .github/workflows/test.yml | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 4c3e11b19..326588671 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -1,13 +1,9 @@ -name: "Testing - Linux" +name: "Test Ark - Linux" on: - push: - branches: - - main - pull_request: + workflow_dispatch: jobs: - linux: runs-on: ubuntu-latest name: "Unit Tests on Linux (rust: ${{ matrix.config.rust }})" @@ -35,7 +31,7 @@ jobs: sudo apt-get update # Unit tests "automatically" find and set `R_HOME` if it isn't set by - # calling `R RHOME`. See the testing version of `start_r()` for this. + # calling `R RHOME`. - name: Run Unit Tests id: test run: | diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 395e5ae63..ddfe4057a 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -1,13 +1,9 @@ -name: "Testing - Windows" +name: "Test Ark - Windows" on: - push: - branches: - - main - pull_request: + workflow_dispatch: jobs: - windows: runs-on: windows-latest name: "Unit Tests on Windows (rust: ${{ matrix.config.rust }})" @@ -31,7 +27,7 @@ jobs: use-public-rspm: true # Unit tests "automatically" find and set `R_HOME` if it isn't set by - # calling `R RHOME`. See the testing version of `start_r()` for this. + # calling `R RHOME`. - name: Run Unit Tests id: test run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..93210ca2e --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,24 @@ +name: "Test Ark" +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + # TODO + # test_macos: + # name: Test macOS + # uses: ./.github/workflows/test-macos.yml + # secrets: inherit + + test_windows: + name: Test Windows + uses: ./.github/workflows/test-windows.yml + secrets: inherit + + test_linux: + name: Test Linux + uses: ./.github/workflows/test-linux.yml + secrets: inherit From e98cff9611e6e49fbe60ed4f74338d6b80a16943 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Thu, 26 Sep 2024 17:33:18 -0400 Subject: [PATCH 20/31] Make the subworkflows callable --- .github/workflows/test-linux.yml | 1 + .github/workflows/test-windows.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 326588671..5f34a419f 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -1,6 +1,7 @@ name: "Test Ark - Linux" on: + workflow_call: workflow_dispatch: jobs: diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index ddfe4057a..fba941354 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -1,6 +1,7 @@ name: "Test Ark - Windows" on: + workflow_call: workflow_dispatch: jobs: From d0a4f7bafb5683f0f70eda41e1eeb2548caca6e8 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 27 Sep 2024 09:21:51 -0400 Subject: [PATCH 21/31] Add script to auto generate the manifest files --- crates/ark/resources/manifest/ark-manifest.rc | 2 +- .../ark/resources/manifest/ark.exe.manifest | 1 + .../harp/resources/manifest/harp-manifest.rc | 2 +- .../harp/resources/manifest/harp.exe.manifest | 1 + scripts/manifest/generate.R | 42 +++++++++++++++++++ scripts/manifest/template.manifest | 41 ++++++++++++++++++ scripts/manifest/template.rc | 13 ++++++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 scripts/manifest/generate.R create mode 100644 scripts/manifest/template.manifest create mode 100644 scripts/manifest/template.rc diff --git a/crates/ark/resources/manifest/ark-manifest.rc b/crates/ark/resources/manifest/ark-manifest.rc index 26e00deb8..4df2a418e 100644 --- a/crates/ark/resources/manifest/ark-manifest.rc +++ b/crates/ark/resources/manifest/ark-manifest.rc @@ -1,4 +1,4 @@ -// Autogenerated, do not modify! +// Autogenerated, do not modify! See `template.rc`. // This is a C file that embed-resource compiles for us. // It helps embed our Windows Application Manifest file. diff --git a/crates/ark/resources/manifest/ark.exe.manifest b/crates/ark/resources/manifest/ark.exe.manifest index 5c68fb45b..8be536132 100644 --- a/crates/ark/resources/manifest/ark.exe.manifest +++ b/crates/ark/resources/manifest/ark.exe.manifest @@ -3,6 +3,7 @@ + ark diff --git a/crates/harp/resources/manifest/harp-manifest.rc b/crates/harp/resources/manifest/harp-manifest.rc index dc8649797..b5d647516 100644 --- a/crates/harp/resources/manifest/harp-manifest.rc +++ b/crates/harp/resources/manifest/harp-manifest.rc @@ -1,4 +1,4 @@ -// Autogenerated, do not modify! +// Autogenerated, do not modify! See `template.rc`. // This is a C file that embed-resource compiles for us. // It helps embed our Windows Application Manifest file. diff --git a/crates/harp/resources/manifest/harp.exe.manifest b/crates/harp/resources/manifest/harp.exe.manifest index e3bab77fd..f0055309a 100644 --- a/crates/harp/resources/manifest/harp.exe.manifest +++ b/crates/harp/resources/manifest/harp.exe.manifest @@ -3,6 +3,7 @@ + harp diff --git a/scripts/manifest/generate.R b/scripts/manifest/generate.R new file mode 100644 index 000000000..f116098eb --- /dev/null +++ b/scripts/manifest/generate.R @@ -0,0 +1,42 @@ +#' Write out templated Windows Application Manifest files +#' +#' We use two files to embed an application manifest on Windows: +#' - `{crate}-manifest.rc` +#' - `{crate}.exe.manifest` +#' +#' And we generate these two files for both `harp` and `ark`. +#' +#' They are effectively the same, we just need to swap out the crate names, +#' so we use this script to write the files in a consistent manner. +write_manifest <- function(root, crate) { + crate_exe <- glue::glue("{crate}.exe.manifest") + + dest_folder <- file.path(root, "crates", crate, "resources", "manifest") + dest_path_rc <- file.path(dest_folder, glue::glue("{crate}-manifest.rc")) + dest_path_manifest <- file.path(dest_folder, crate_exe) + + src_folder <- file.path(root, "scripts", "manifest") + src_path_rc <- file.path(src_folder, "template.rc") + src_path_manifest <- file.path(src_folder, "template.manifest") + + # Write `{crate}-manifest.rc` + data <- list(name = crate_exe) + text <- brio::read_file(src_path_rc) + text <- whisker::whisker.render(text, data = data) + brio::write_file(text, dest_path_rc) + + # Write `{crate}.exe.manifest` + data <- list(name = crate) + text <- brio::read_file(src_path_manifest) + text <- whisker::whisker.render(text, data = data) + brio::write_file(text, dest_path_manifest) + + invisible(NULL) +} + +root <- here::here() +crates <- c("ark", "harp") + +for (crate in crates) { + write_manifest(root, crate) +} diff --git a/scripts/manifest/template.manifest b/scripts/manifest/template.manifest new file mode 100644 index 000000000..647b87f88 --- /dev/null +++ b/scripts/manifest/template.manifest @@ -0,0 +1,41 @@ + + + + + + + {{name}} + + + + + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/manifest/template.rc b/scripts/manifest/template.rc new file mode 100644 index 000000000..25cc16a5c --- /dev/null +++ b/scripts/manifest/template.rc @@ -0,0 +1,13 @@ +// Autogenerated, do not modify! See `template.rc`. + +// This is a C file that embed-resource compiles for us. +// It helps embed our Windows Application Manifest file. +// https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests +// https://learn.microsoft.com/en-us/cpp/build/reference/manifest-create-side-by-side-assembly-manifest?view=msvc-170 + +// This defines `RT_MANIFEST` to `24`. embed-resource should know how to ensure the header is available. +// https://github.com/nabijaczleweli/rust-embed-resource/issues/11#issuecomment-779295722 +#include + +// The `1` is a `resource_id` that specifies us as an executable file +1 RT_MANIFEST "{{name}}" From 899e2c7a1c3cbbb169c52decb4f1e3756f4e435a Mon Sep 17 00:00:00 2001 From: DavisVaughan Date: Fri, 27 Sep 2024 12:31:39 -0400 Subject: [PATCH 22/31] Post rebase fixup --- crates/ark/src/sys/windows/locale.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ark/src/sys/windows/locale.rs b/crates/ark/src/sys/windows/locale.rs index df0ecf72d..a19405d96 100644 --- a/crates/ark/src/sys/windows/locale.rs +++ b/crates/ark/src/sys/windows/locale.rs @@ -7,7 +7,7 @@ #[cfg(test)] mod tests { - use crate::test::r_test; + use crate::fixtures::r_test; #[test] fn test_locale() { From 17c5b849cf85c5a7a760086ddfdbf655694630d4 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 27 Sep 2024 13:29:45 -0400 Subject: [PATCH 23/31] Only test on nightly on 1 OS, also test on R 4.2 --- .github/workflows/test-linux.yml | 10 +++++++--- .github/workflows/test-windows.yml | 9 +++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 5f34a419f..8172b123a 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -7,13 +7,16 @@ on: jobs: linux: runs-on: ubuntu-latest - name: "Unit Tests on Linux (rust: ${{ matrix.config.rust }})" + name: "Test Ark - Linux (Rust: ${{ matrix.config.rust }}, R ${{ matrix.config.r }})" strategy: fail-fast: false matrix: config: - - { rust: 'stable' } - - { rust: 'nightly' } + - { rust: 'stable', r: 'release' } + # Oldest supported R version + - { rust: 'stable', r: '4.2' } + # Nightly rust + - { rust: 'nightly', r: 'release' } timeout-minutes: 30 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -25,6 +28,7 @@ jobs: - uses: r-lib/actions/setup-r@v2 with: + r-version: ${{ matrix.config.r }} use-public-rspm: true - name: Setup Build Environment diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index fba941354..e0944fbac 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -7,24 +7,21 @@ on: jobs: windows: runs-on: windows-latest - name: "Unit Tests on Windows (rust: ${{ matrix.config.rust }})" + name: "Test Ark - Windows (Rust: ${{ matrix.config.rust }}, R ${{ matrix.config.r }})" strategy: fail-fast: false matrix: config: - - { rust: 'stable' } - - { rust: 'nightly' } + - { rust: 'stable', r: 'release' } timeout-minutes: 30 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@nightly - if: matrix.config.rust == 'nightly' - - uses: r-lib/actions/setup-r@v2 with: + r-version: ${{ matrix.config.r }} use-public-rspm: true # Unit tests "automatically" find and set `R_HOME` if it isn't set by From 6024d60508ce830cebad46e39bca4a41892d2835 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 27 Sep 2024 13:32:34 -0400 Subject: [PATCH 24/31] Less repetition --- .github/workflows/test-linux.yml | 2 +- .github/workflows/test-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 8172b123a..afcecc171 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -7,7 +7,7 @@ on: jobs: linux: runs-on: ubuntu-latest - name: "Test Ark - Linux (Rust: ${{ matrix.config.rust }}, R ${{ matrix.config.r }})" + name: "Variant - Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" strategy: fail-fast: false matrix: diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index e0944fbac..8419db7fe 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -7,7 +7,7 @@ on: jobs: windows: runs-on: windows-latest - name: "Test Ark - Windows (Rust: ${{ matrix.config.rust }}, R ${{ matrix.config.r }})" + name: "Variant - Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" strategy: fail-fast: false matrix: From 9bc08e2304f50a203afae4b60a6610d260006ebf Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 27 Sep 2024 13:35:58 -0400 Subject: [PATCH 25/31] Add in macOS testing --- .github/workflows/test-linux.yml | 2 -- .github/workflows/test-macos.yml | 30 ++++++++++++++++++++++++++++++ .github/workflows/test-windows.yml | 2 -- .github/workflows/test.yml | 25 ++++++++++++------------- 4 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/test-macos.yml diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index afcecc171..ecd7541eb 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -35,8 +35,6 @@ jobs: run: | sudo apt-get update - # Unit tests "automatically" find and set `R_HOME` if it isn't set by - # calling `R RHOME`. - name: Run Unit Tests id: test run: | diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml new file mode 100644 index 000000000..305485394 --- /dev/null +++ b/.github/workflows/test-macos.yml @@ -0,0 +1,30 @@ +name: "Test Ark - macOS" + +on: + workflow_call: + workflow_dispatch: + +jobs: + macos: + runs-on: macos-latest + name: "Variant - Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" + strategy: + fail-fast: false + matrix: + config: + - { rust: 'stable', r: 'release' } + timeout-minutes: 30 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + use-public-rspm: true + + - name: Run Unit Tests + id: test + run: | + cargo test --verbose diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 8419db7fe..606db6128 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -24,8 +24,6 @@ jobs: r-version: ${{ matrix.config.r }} use-public-rspm: true - # Unit tests "automatically" find and set `R_HOME` if it isn't set by - # calling `R RHOME`. - name: Run Unit Tests id: test run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 93210ca2e..4fb947530 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,18 +7,17 @@ on: workflow_dispatch: jobs: - # TODO - # test_macos: - # name: Test macOS - # uses: ./.github/workflows/test-macos.yml - # secrets: inherit + test_macos: + name: Test macOS + uses: ./.github/workflows/test-macos.yml + secrets: inherit - test_windows: - name: Test Windows - uses: ./.github/workflows/test-windows.yml - secrets: inherit + test_windows: + name: Test Windows + uses: ./.github/workflows/test-windows.yml + secrets: inherit - test_linux: - name: Test Linux - uses: ./.github/workflows/test-linux.yml - secrets: inherit + test_linux: + name: Test Linux + uses: ./.github/workflows/test-linux.yml + secrets: inherit From a6581e90cd97099557a066efdf9f83728b833966 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 27 Sep 2024 13:42:17 -0400 Subject: [PATCH 26/31] An `origin` is required on R <= 4.2 for `as.POSIXct.numeric()` --- crates/ark/src/modules/positron/r_data_explorer.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/ark/src/modules/positron/r_data_explorer.R b/crates/ark/src/modules/positron/r_data_explorer.R index d63ca6e78..982a36b43 100644 --- a/crates/ark/src/modules/positron/r_data_explorer.R +++ b/crates/ark/src/modules/positron/r_data_explorer.R @@ -425,7 +425,9 @@ profile_histogram <- function(x, method = c("fixed", "sturges", "fd", "scott"), # For dates, we convert back the breaks to the date representation. if (inherits(x, "POSIXct")) { - bin_edges <- as.POSIXct(h$breaks, tz = attr(x, "tzone")) + # Must supply an `origin` on R <= 4.2 + origin <- as.POSIXct("1970-01-01", tz = "UTC") + bin_edges <- as.POSIXct(h$breaks, tz = attr(x, "tzone"), origin = origin) } list( From fbb335468cc6cc4057f1834ad4aea24b387b21fb Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 27 Sep 2024 13:44:03 -0400 Subject: [PATCH 27/31] Looks better without this too --- .github/workflows/test-linux.yml | 2 +- .github/workflows/test-macos.yml | 2 +- .github/workflows/test-windows.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index ecd7541eb..28b720d00 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -7,7 +7,7 @@ on: jobs: linux: runs-on: ubuntu-latest - name: "Variant - Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" + name: "Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" strategy: fail-fast: false matrix: diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index 305485394..11b6e2d0e 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -7,7 +7,7 @@ on: jobs: macos: runs-on: macos-latest - name: "Variant - Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" + name: "Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" strategy: fail-fast: false matrix: diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 606db6128..d82569808 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -7,7 +7,7 @@ on: jobs: windows: runs-on: windows-latest - name: "Variant - Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" + name: "Rust: ${{ matrix.config.rust }}, R: ${{ matrix.config.r }}" strategy: fail-fast: false matrix: From 51a899f15c540b67155a1e70f0f7d05fb8381307 Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Fri, 27 Sep 2024 13:51:11 -0400 Subject: [PATCH 28/31] Allow SSH access on workflow dispatch --- .github/workflows/test-linux.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 28b720d00..49c67ec42 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -3,6 +3,12 @@ name: "Test Ark - Linux" on: workflow_call: workflow_dispatch: + inputs: + ssh: + description: 'Set up an SSH session before running `cargo test`?' + type: boolean + required: true + default: false jobs: linux: @@ -35,6 +41,11 @@ jobs: run: | sudo apt-get update + - name: Setup SSH access + uses: mxschmitt/action-tmate@v3 + if: ${{ inputs.ssh }} + timeout-minutes: 30 + - name: Run Unit Tests id: test run: | From 0b0aab9b14b77342e523a6518bfd83bfbf0f2355 Mon Sep 17 00:00:00 2001 From: DavisVaughan Date: Fri, 27 Sep 2024 14:06:55 -0400 Subject: [PATCH 29/31] Try and get some information on where `recv()` is hanging --- crates/amalthea/src/socket/socket.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/amalthea/src/socket/socket.rs b/crates/amalthea/src/socket/socket.rs index fb07ab51e..ac34e1c81 100644 --- a/crates/amalthea/src/socket/socket.rs +++ b/crates/amalthea/src/socket/socket.rs @@ -133,6 +133,12 @@ impl Socket { } } + // 10 second timeout on `recv()` operations (for testing for now) + // TODO: Expose `IS_TESTING` in its own lightweight crate? + if let Err(error) = socket.set_rcvtimeo(10000) { + return Err(Error::CreateSocketFailed(name, error)); + } + // Set the socket's identity, if supplied if let Some(identity) = identity { if let Err(err) = socket.set_identity(identity) { From 36357c43fc58a77641f4ef2a20d25bed3188a0fb Mon Sep 17 00:00:00 2001 From: DavisVaughan Date: Fri, 27 Sep 2024 14:12:04 -0400 Subject: [PATCH 30/31] Send timeout too --- crates/amalthea/src/socket/socket.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/amalthea/src/socket/socket.rs b/crates/amalthea/src/socket/socket.rs index ac34e1c81..4453af4f6 100644 --- a/crates/amalthea/src/socket/socket.rs +++ b/crates/amalthea/src/socket/socket.rs @@ -138,6 +138,9 @@ impl Socket { if let Err(error) = socket.set_rcvtimeo(10000) { return Err(Error::CreateSocketFailed(name, error)); } + if let Err(error) = socket.set_sndtimeo(10000) { + return Err(Error::CreateSocketFailed(name, error)); + } // Set the socket's identity, if supplied if let Some(identity) = identity { From 035ffcd9578a805152052b6e4f786c3a602dfeeb Mon Sep 17 00:00:00 2001 From: Davis Vaughan Date: Mon, 30 Sep 2024 10:28:18 -0400 Subject: [PATCH 31/31] Remove timeout code for the moment --- crates/amalthea/src/socket/socket.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/crates/amalthea/src/socket/socket.rs b/crates/amalthea/src/socket/socket.rs index 4453af4f6..fb07ab51e 100644 --- a/crates/amalthea/src/socket/socket.rs +++ b/crates/amalthea/src/socket/socket.rs @@ -133,15 +133,6 @@ impl Socket { } } - // 10 second timeout on `recv()` operations (for testing for now) - // TODO: Expose `IS_TESTING` in its own lightweight crate? - if let Err(error) = socket.set_rcvtimeo(10000) { - return Err(Error::CreateSocketFailed(name, error)); - } - if let Err(error) = socket.set_sndtimeo(10000) { - return Err(Error::CreateSocketFailed(name, error)); - } - // Set the socket's identity, if supplied if let Some(identity) = identity { if let Err(err) = socket.set_identity(identity) {