-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Expand file tree
/
Copy pathr_wasm_test.cjs
More file actions
165 lines (151 loc) · 5.52 KB
/
Copy pathr_wasm_test.cjs
File metadata and controls
165 lines (151 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
// Smoke-test the arrow R package under webR, then run the testthat suite.
// Called by r_wasm_test.sh. Requires env vars:
// ARROW_WASM_REPO_DIR - local CRAN-like repo with the arrow .tgz
// ARROW_R_TESTS_DIR - path to tests/testthat in the source tree
const { WebR } = require("webr");
const http = require("http");
const fs = require("fs");
const path = require("path");
const repoDir = process.env.ARROW_WASM_REPO_DIR;
if (!repoDir) {
console.error("ERROR: ARROW_WASM_REPO_DIR not set");
process.exit(1);
}
const testsDir = process.env.ARROW_R_TESTS_DIR;
if (!testsDir) {
console.error("ERROR: ARROW_R_TESTS_DIR not set");
process.exit(1);
}
function listFilesRecursive(dir) {
const results = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
results.push(...listFilesRecursive(full));
} else {
results.push(full);
}
}
return results;
}
async function main() {
// Serve the repo over HTTP (webR can't access the host filesystem directly)
const server = http.createServer((req, res) => {
const filePath = path.join(repoDir, decodeURIComponent(req.url));
if (!filePath.startsWith(path.resolve(repoDir))) {
res.writeHead(403);
res.end();
return;
}
fs.readFile(filePath, (err, data) => {
if (err) {
res.writeHead(404);
res.end();
} else {
res.writeHead(200);
res.end(data);
}
});
});
server.listen(8080);
console.log("✓ Repo server on :8080");
const webR = new WebR({ RArgs: ["--quiet"], interactive: false });
await webR.init();
console.log("✓ webR initialized");
// Upload test files to webR VFS (rwasm doesn't include tests in binaries)
const vfsTestDir = "/tmp/arrow-tests";
await webR.FS.mkdir(vfsTestDir);
const testFiles = listFilesRecursive(testsDir);
const createdDirs = new Set([vfsTestDir]);
for (const file of testFiles) {
const rel = path.relative(testsDir, file);
const vfsPath = path.posix.join(vfsTestDir, rel.split(path.sep).join("/"));
const vfsDir = path.posix.dirname(vfsPath);
if (!createdDirs.has(vfsDir)) {
await webR.evalRVoid(`dir.create("${vfsDir}", recursive=TRUE, showWarnings=FALSE)`);
createdDirs.add(vfsDir);
}
await webR.FS.writeFile(vfsPath, fs.readFileSync(file));
}
console.log(`✓ Uploaded ${testFiles.length} test files to VFS`);
// Install arrow from local repo, deps from r-wasm.org
await webR.installPackages(["arrow"], {
repos: ["http://localhost:8080", "https://repo.r-wasm.org"],
quiet: false,
mount: false,
});
console.log("✓ arrow installed");
// Install test deps parsed from DESCRIPTION
const depsList = await webR.evalRString(`
desc <- read.dcf(system.file("DESCRIPTION", package = "arrow"),
fields = c("Imports", "Suggests"))
pkgs <- unlist(strsplit(paste(na.omit(desc[1,]), collapse = ","), ",\\\\s*"))
pkgs <- trimws(sub("\\\\s*\\\\(.*\\\\)", "", pkgs))
pkgs <- pkgs[pkgs != "" & pkgs != "R"]
pkgs <- pkgs[!pkgs %in% loadedNamespaces()]
paste(pkgs, collapse = "\\n")
`);
const testDeps = depsList.split("\n").filter(Boolean);
console.log(`Installing ${testDeps.length} dependencies from DESCRIPTION...`);
await webR.installPackages(testDeps, {
repos: ["https://repo.r-wasm.org"],
quiet: false,
mount: false,
});
console.log("✓ test dependencies installed");
// Smoke test: package loads, threading disabled, basic operations work
const loadResult = await webR.evalRString(`
library(arrow)
cat("R.version$os =", R.version$os, "\\n")
stopifnot(identical(getOption("arrow.use_threads"), FALSE))
tab <- arrow::as_arrow_table(data.frame(x = 1:10, y = letters[1:10]))
stopifnot(nrow(tab) == 10L)
cat("Created table with", nrow(tab), "rows\\n")
"PASS"
`);
if (loadResult !== "PASS") {
throw new Error("Smoke test failed");
}
console.log("✓ Smoke test passed");
// Run testthat suite
console.log("Running testthat suite...");
const testResult = await webR.evalRString(`
library(testthat)
results <- testthat::test_dir(
"${vfsTestDir}",
reporter = "summary",
stop_on_failure = FALSE,
package = "arrow"
)
df <- as.data.frame(results)
cat(sprintf("Results: %d passed, %d skipped, %d failed, %d errors\\n",
sum(df$passed), sum(df$skipped), sum(df$failed), sum(df$error)))
if (sum(df$failed) > 0 || sum(df$error) > 0) "FAIL" else "PASS"
`);
if (testResult !== "PASS") {
throw new Error("testthat suite failed");
}
console.log("✓ testthat suite passed");
await webR.close();
server.close();
}
main().catch((e) => {
console.error("FAILED:", e);
process.exit(1);
});