Nothing
# test-onnx-helpers.R
#
# Unit tests for internal C helper functions via ONNX graph execution:
# - onnx_squeeze_ndims : trailing-1 collapsing for ggml compat
# - onnx_reshape_nd : dispatch to correct ggml_reshape_Nd branch
# - ne_product : element count verification in Reshape
run_onnx <- function(path, inputs, device = "cpu") {
m <- onnx_load(path, device = device)
res <- onnx_run(m, inputs)
res[[1]]
}
# ── onnx_squeeze_ndims ───────────────────────────────────────────
# Trailing 1s are collapsed so ggml sees compact tensors.
# Tested by reshaping to shapes with trailing 1s and verifying
# values pass through correctly.
test_that("onnx_squeeze_ndims: [2,3,1] trailing 1 is collapsed", {
inp <- .onnx_value_info("X", 1L, c(6L))
shape_raw <- c(.int64_bytes(2L), .int64_bytes(3L), .int64_bytes(1L))
shape_t <- .onnx_tensor("shape", c(3L), 7L, shape_raw)
shape_vi <- .onnx_value_info("shape", 7L, c(3L))
outp <- .onnx_value_info("Y", 1L, c(2L, 3L, 1L))
node_r <- .onnx_node("Reshape", c("X", "shape"), "tmp")
node_a <- .onnx_node("Relu", "tmp", "Y")
graph <- .onnx_graph("test", list(node_r, node_a),
list(inp, shape_vi), list(outp), list(shape_t))
path <- tempfile(fileext = ".onnx")
writeBin(.onnx_model(graph), path)
x <- c(-1, 2, -3, 4, -5, 6)
result <- run_onnx(path, list(X = x))
expect_equal(length(result), 6)
expect_equal(as.numeric(result), pmax(x, 0), tolerance = 1e-5)
})
test_that("onnx_squeeze_ndims: [1,1,4,1] multiple trailing 1s", {
inp <- .onnx_value_info("X", 1L, c(4L))
shape_raw <- c(.int64_bytes(1L), .int64_bytes(1L),
.int64_bytes(4L), .int64_bytes(1L))
shape_t <- .onnx_tensor("shape", c(4L), 7L, shape_raw)
shape_vi <- .onnx_value_info("shape", 7L, c(4L))
outp <- .onnx_value_info("Y", 1L, c(1L, 1L, 4L, 1L))
node_r <- .onnx_node("Reshape", c("X", "shape"), "tmp")
node_a <- .onnx_node("Relu", "tmp", "Y")
graph <- .onnx_graph("test", list(node_r, node_a),
list(inp, shape_vi), list(outp), list(shape_t))
path <- tempfile(fileext = ".onnx")
writeBin(.onnx_model(graph), path)
x <- c(-1, 2, -3, 4)
result <- run_onnx(path, list(X = x))
expect_equal(length(result), 4)
expect_equal(as.numeric(result), pmax(x, 0), tolerance = 1e-5)
})
test_that("onnx_squeeze_ndims: [1,1,1,1] all-ones shape (scalar repeat)", {
inp <- .onnx_value_info("X", 1L, c(1L))
shape_raw <- c(.int64_bytes(1L), .int64_bytes(1L),
.int64_bytes(1L), .int64_bytes(1L))
shape_t <- .onnx_tensor("shape", c(4L), 7L, shape_raw)
shape_vi <- .onnx_value_info("shape", 7L, c(4L))
outp <- .onnx_value_info("Y", 1L, c(1L, 1L, 1L, 1L))
node_r <- .onnx_node("Reshape", c("X", "shape"), "tmp")
node_a <- .onnx_node("Relu", "tmp", "Y")
graph <- .onnx_graph("test", list(node_r, node_a),
list(inp, shape_vi), list(outp), list(shape_t))
path <- tempfile(fileext = ".onnx")
writeBin(.onnx_model(graph), path)
result <- run_onnx(path, list(X = 5.0))
expect_equal(as.numeric(result), 5.0, tolerance = 1e-5)
})
# ── onnx_reshape_nd dispatch ─────────────────────────────────────
# Each test exercises a different ggml_reshape_Nd branch (1D–4D).
test_that("onnx_reshape_nd 1D: [12] → [12] identity", {
path <- .onnx_make_reshape(c(12L), c(12L))
x <- seq_len(12) * 1.0
result <- run_onnx(path, list(X = x))
expect_equal(as.numeric(result), x, tolerance = 1e-5)
})
test_that("onnx_reshape_nd 2D: [3,4] → [4,3]", {
path <- .onnx_make_reshape(c(3L, 4L), c(4L, 3L))
x <- seq_len(12) * 1.0
result <- run_onnx(path, list(X = x))
expect_equal(length(result), 12)
expect_equal(sum(result), sum(x), tolerance = 1e-5)
})
test_that("onnx_reshape_nd 3D: [2,3,4] → [24]", {
path <- .onnx_make_reshape(c(2L, 3L, 4L), c(24L))
x <- seq_len(24) * 1.0
result <- run_onnx(path, list(X = x))
expect_equal(as.numeric(result), x, tolerance = 1e-5)
})
test_that("onnx_reshape_nd 4D: [6] → [1,1,2,3]", {
path <- .onnx_make_reshape(c(6L), c(1L, 1L, 2L, 3L))
x <- c(1, 2, 3, 4, 5, 6)
result <- run_onnx(path, list(X = x))
expect_equal(as.numeric(result), x, tolerance = 1e-5)
})
test_that("onnx_reshape_nd 5D: [24] → [1,2,3,4,1] (5D branch)", {
inp <- .onnx_value_info("X", 1L, c(24L))
shape_raw <- c(.int64_bytes(1L), .int64_bytes(2L), .int64_bytes(3L),
.int64_bytes(4L), .int64_bytes(1L))
shape_t <- .onnx_tensor("shape", c(5L), 7L, shape_raw)
shape_vi <- .onnx_value_info("shape", 7L, c(5L))
outp <- .onnx_value_info("Y", 1L, c(1L, 2L, 3L, 4L, 1L))
node_r <- .onnx_node("Reshape", c("X", "shape"), "tmp")
node_a <- .onnx_node("Relu", "tmp", "Y")
graph <- .onnx_graph("test", list(node_r, node_a),
list(inp, shape_vi), list(outp), list(shape_t))
path <- tempfile(fileext = ".onnx")
writeBin(.onnx_model(graph), path)
x <- seq_len(24) * 1.0
result <- run_onnx(path, list(X = x))
expect_equal(length(result), 24)
expect_equal(sum(result), sum(x), tolerance = 1e-3)
})
# ── ne_product: element count verification ───────────────────────
# Reshape with mismatched count must be caught, not silently corrupt.
test_that("ne_product: mismatch [6] → [2,4] node is skipped (output NULL)", {
inp <- .onnx_value_info("X", 1L, c(6L))
shape_raw <- c(.int64_bytes(2L), .int64_bytes(4L)) # 8 != 6
shape_t <- .onnx_tensor("shape", c(2L), 7L, shape_raw)
shape_vi <- .onnx_value_info("shape", 7L, c(2L))
outp <- .onnx_value_info("Y", 1L, c(2L, 4L))
node <- .onnx_node("Reshape", c("X", "shape"), "Y")
graph <- .onnx_graph("test", list(node),
list(inp, shape_vi), list(outp), list(shape_t))
path <- tempfile(fileext = ".onnx")
writeBin(.onnx_model(graph), path)
# Mismatch is logged as warning; node is skipped → output tensor absent → NULL
m <- onnx_load(path, device = "cpu")
res <- onnx_run(m, list(X = seq_len(6) * 1.0))
expect_null(res[[1]])
})
test_that("ne_product: mismatch [12] → [3,5] output is NULL", {
inp <- .onnx_value_info("X", 1L, c(12L))
shape_raw <- c(.int64_bytes(3L), .int64_bytes(5L)) # 15 != 12
shape_t <- .onnx_tensor("shape", c(2L), 7L, shape_raw)
shape_vi <- .onnx_value_info("shape", 7L, c(2L))
outp <- .onnx_value_info("Y", 1L, c(3L, 5L))
node <- .onnx_node("Reshape", c("X", "shape"), "Y")
graph <- .onnx_graph("test", list(node),
list(inp, shape_vi), list(outp), list(shape_t))
path <- tempfile(fileext = ".onnx")
writeBin(.onnx_model(graph), path)
m <- onnx_load(path, device = "cpu")
res <- onnx_run(m, list(X = seq_len(12) * 1.0))
expect_null(res[[1]])
})
test_that("ne_product: -1 inference correct: [2,3,4] → [-1,4] = [6,4]", {
path <- .onnx_make_reshape(c(2L, 3L, 4L), c(-1L, 4L))
x <- seq_len(24) * 1.0
result <- run_onnx(path, list(X = x))
expect_equal(length(result), 24)
expect_equal(sum(result), sum(x), tolerance = 1e-5)
})
test_that("ne_product: -1 inference in middle: [2,3,4] → [2,-1,2]", {
path <- .onnx_make_reshape(c(2L, 3L, 4L), c(2L, -1L, 2L))
x <- seq_len(24) * 1.0
result <- run_onnx(path, list(X = x))
expect_equal(length(result), 24)
expect_equal(sum(result), sum(x), tolerance = 1e-5)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.