tests/tinytests/test-partial-read.r

local({
  #test_that("validate_start_count handles missing count correctly", {
  file <- tempfile(fileext = ".h5")
  v <- 1:10
  h5_write(v, file, "v")
  h5_write(1L, file, "v", attr = "my_attr")
  
  # 1. Start is provided, count is NULL (Valid exact index)
  expect_silent(h5_read(file, "v", start = 1))
  
  # 2. Count is provided, start is NULL (Invalid)
  expect_error(h5_read(file, "v", count = 1), "must be provided if `count` is specified")
  
  # 3. Attribute check
  expect_error(h5_read(file, "v", attr = "my_attr", start = 1), 
               "cannot be used on attributes")
  
  # 4. Numeric checks
  expect_error(h5_read(file, "v", start = "a"), "must be numeric")
  expect_error(h5_read(file, "v", start = 1, count = "a"), "must be numeric")
  
  # 5. Positivity checks
  expect_error(h5_read(file, "v", start = 0), "must be positive")
  expect_error(h5_read(file, "v", start = c(1, -1)), "must be positive")
  expect_error(h5_read(file, "v", start = 1, count = 0), "must be positive")
  
  # 6. Bounds checks
  expect_error(h5_read(file, "v", start = 11), "out of bounds")
  expect_error(h5_read(file, "v", start = 10, count = 2), "out of bounds")
  
  # 7. Other errors
  expect_error(h5_read(file, "v", start = numeric(0)), "cannot be an empty vector")
  expect_error(h5_read(file, "v", start = 1, count = 1:2), "must be a single numeric value")
  expect_error(h5_read(file, "v", start = 1, count = numeric(0)), "must be a single numeric value")
  expect_error(h5_read(file, "v", start = 1:2), "more dimensions than the dataset")
  
  unlink(file)
})

local({
  #test_that("partial reading works for 1D atomic vectors (with naming logic)", {
  file <- tempfile(fileext = ".h5")
  
  # Scalar
  h5_write(I(42), file, "scl")
  
  res0 <- h5_read(file, "scl", start = 1)
  expect_equal(res0, 42)
  
  res0 <- h5_read(file, "scl", start = 1, count = 1)
  expect_equal(res0, 42)
  
  # Setup Named Vector
  v_int <- c(a=1L, b=2L, c=3L, d=4L, e=5L)
  h5_write(v_int, file, "int")
  
  # 1. Range Indexing (count > 1)
  res1 <- h5_read(file, "int", start = 2, count = 3)
  expect_equal(res1, c(b=2L, c=3L, d=4L))
  
  # 2. Range Indexing of 1 (count = 1) -> retains name
  res2 <- h5_read(file, "int", start = 3, count = 1)
  expect_equal(res2, c(c=3L))
  
  # 3. Exact Point Indexing (count = NULL) -> strips name
  res3 <- h5_read(file, "int", start = 3)
  expect_equal(res3, 3L)
  expect_null(names(res3))
  
  unlink(file)
})

local({
  #test_that("partial reading works for matrices (with dimension dropping)", {
  file <- tempfile(fileext = ".h5")
  
  # 5x4 matrix
  m <- matrix(1:20, nrow = 5, ncol = 4, 
              dimnames = list(paste0("r", 1:5), paste0("c", 1:4)))
  h5_write(m, file, "m")
  
  # 1. Range Indexing (rows)
  res1 <- h5_read(file, "m", start = 3, count = 2)
  expect_equal(dim(res1), c(2, 4))
  expect_equal(rownames(res1), c("r3", "r4"))
  expect_equal(colnames(res1), c("c1", "c2", "c3", "c4"))
  
  # 2. Exact Indexing (row) -> drops matrix to vector, inherits column names
  res2 <- h5_read(file, "m", start = 3)
  expect_null(dim(res2))
  expect_equal(names(res2), c("c1", "c2", "c3", "c4"))
  expect_equal(res2, m[3, ])
  
  # 3. Range Indexing of 1 (row) -> preserves 1xN matrix, inherits row name
  res3 <- h5_read(file, "m", start = 3, count = 1)
  expect_equal(dim(res3), c(1, 4))
  expect_equal(rownames(res3), "r3")
  expect_equal(colnames(res3), c("c1", "c2", "c3", "c4"))
  
  # 4. Multi-value Exact+Range (row exactly, cols range) -> drops row, named vector
  res4 <- h5_read(file, "m", start = c(3, 2), count = 2)
  expect_null(dim(res4))
  expect_equal(names(res4), c("c2", "c3"))
  expect_equal(res4, m[3, 2:3])
  
  # 5. Multi-value Exact (row exactly, col exactly) -> fully unnamed scalar
  res5 <- h5_read(file, "m", start = c(3, 2))
  expect_null(dim(res5))
  expect_null(names(res5))
  expect_equal(res5, m[3, 2][[1]])
  
  unlink(file)
})

local({
  #test_that("partial reading works for data.frames (no dropping allowed)", {
  file <- tempfile(fileext = ".h5")
  
  df <- data.frame(
    id = 1:5,
    val = c(1.1, 2.2, 3.3, 4.4, 5.5),
    name = c("a", "b", "c", "d", "e"),
    row.names = c("r1", "r2", "r3", "r4", "r5"),
    stringsAsFactors = FALSE
  )
  h5_write(df, file, "df")
  
  # 1. Range Indexing
  res1 <- h5_read(file, "df", start = 2, count = 3)
  expect_inherits(res1, "data.frame")
  expect_equal(nrow(res1), 3)
  expect_equal(rownames(res1), c("r2", "r3", "r4"))
  
  # 2. Exact Indexing (count = NULL) -> Data Frames should never drop!
  res2 <- h5_read(file, "df", start = 2)
  expect_inherits(res2, "data.frame")
  expect_equal(nrow(res2), 1)
  expect_equal(rownames(res2), "r2")
  expect_equal(res2$val, 2.2)
  
  unlink(file)
})

local({
  #test_that("partial reading works for named N-dimensional arrays", {
  file <- tempfile(fileext = ".h5")
  
  # Create a 2x3x4x5 array (Rows=2, Cols=3, 3rd=4, 4th=5)
  arr4 <- array(
    data     = 1:120,
    dim      = c(2, 3, 4, 5), 
    dimnames = list(LETTERS[1:2], LETTERS[3:5], LETTERS[6:9], LETTERS[10:14]) )
  h5_write(arr4, file, "arr4")
  
  # 1. Target 4th=2, 3rd=3, Row=1. Read 2 rows (count=2).
  # Exact point indices: 4th, 3rd. (Dropped)
  # Range target: Rows. (Preserved)
  # Untargeted: Cols. (Preserved)
  # Result: 2x3 matrix
  res1 <- h5_read(file, "arr4", start = c(2, 3, 1), count = 2)
  expect_equal(dim(res1), c(2, 3))
  expect_equal(res1, arr4[1:2,, 3, 2, drop=TRUE])
  
  # 2. Exact index deep down: Target 4th=2, 3rd=3, Row=2, Col=1. (count=NULL)
  # Drops all dimensions -> scalar
  res2 <- h5_read(file, "arr4", start = c(2, 3, 2, 1))
  expect_null(dim(res2))
  expect_equal(res2, arr4[2, 1, 3, 2])
  
  # 3. Same target as above, but Range index (count=1).
  # Drops 4th, 3rd, Rows. Preserves Cols.
  # Result: 1D vector of length 1
  res3 <- h5_read(file, "arr4", start = c(2, 3, 2, 1), count = 1)
  expect_equal(length(res3), 1)
  expect_equal(names(res3), 'C')
  expect_equal(unname(res3), arr4[2, 1, 3, 2])
  
  unlink(file)
})

local({
  #test_that("partial reading works for unnamed N-dimensional arrays", {
  file <- tempfile(fileext = ".h5")
  
  # Create a 2x3x4x5 array (Rows=2, Cols=3, 3rd=4, 4th=5)
  arr4 <- array(data = 1:120, dim = c(2, 3, 4, 5))
  h5_write(arr4, file, "arr4")
  
  # 1. Target 4th=2, 3rd=3, Row=1. Read 2 rows (count=2).
  # Exact point indices: 4th, 3rd. (Dropped)
  # Range target: Rows. (Preserved)
  # Untargeted: Cols. (Preserved)
  # Result: 2x3 matrix
  res1 <- h5_read(file, "arr4", start = c(2, 3, 1), count = 2)
  expect_equal(dim(res1), c(2, 3))
  expect_equal(res1, arr4[1:2,, 3, 2, drop=TRUE])
  
  # 2. Exact index deep down: Target 4th=2, 3rd=3, Row=2, Col=1. (count=NULL)
  # Drops all dimensions -> scalar
  res2 <- h5_read(file, "arr4", start = c(2, 3, 2, 1))
  expect_null(dim(res2))
  expect_equal(res2, arr4[2, 1, 3, 2])
  
  # 3. Same target as above, but Range index (count=1).
  # Drops 4th, 3rd, Rows. Preserves Cols.
  # Result: 1D vector of length 1
  res3 <- h5_read(file, "arr4", start = c(2, 3, 2, 1), count = 1)
  expect_equal(length(res3), 1)
  expect_equal(names(res3), NULL)
  expect_equal(res3, arr4[2, 1, 3, 2])
  
  unlink(file)
})

Try the h5lite package in your browser

Any scripts or data that you put into this service are public.

h5lite documentation built on May 19, 2026, 1:07 a.m.