- July 1, ‘24:
1) Created test cases for testing a relational operator mutant of rbindlist.c
: (6 hours)
library(data.table)
iVal <- 1:10
test_rbindlist <- function()
{
inputList <- list(
data.table(A = integer(0)),
data.table(A = integer(0), B = 1:3),
data.table(A = integer(0), B = integer(0)),
data.table(A = 1, B = fifelse(iVal %% 2 == 0, 2, NA_real_)
)
usenamesArg <- FALSE
fillArg <- FALSE
idcolArg <- NULL
result <- rbindlist(inputList, usenamesArg, fillArg, idcolArg)
print("Test result:")
print(result)
stopifnot(!is.null(result))
}
test_rbindlist()
Changing to nrow > 0
doesn’t affect this since having zero columns itself invalidates the use of rbindlist and returns nil.
2) Continuing work on the blog posts (GHA, data.table.threads
, mutation testing results). (2 hours)
- July 2, ‘24:
1) Tested the fifelse.c
mutant. (7 hours)
Created my own version at first:
library(data.table)
fifelseR <- function(test, yes, no, na)
{
.Call("CfifelseR", test, yes, no, na)
}
# Mock fifelse function to simulate the altered conditional:
m_fifelse <- function(test, yes, no, na)
{
if(!is.logical(test))
stop("'test' must be logical")
len0 <- length(test)
len3 <- length(na)
if(len3 != 1 && len3 < len0)
stop(sprintf("Length of 'na' is %d but must be 1 or length of 'test' (%d)", len3, len0))
fifelseR(test, yes, no, na) # Calling the fifelseR function.
}
testfifelse <- function()
{
test <- c(TRUE, FALSE, TRUE)
yes <- c(1, 2, 3)
no <- c(4, 5, 6)
na_values <- as.numeric(c(NA, NA, NA, NA))
tryCatch({
m_fifelse(test, yes, no, na_values)
cat("Original condition passed.\n")
na_values[1] <- 1
m_fifelse(test, yes, no, na_values)
cat("Test passed.\n")
}, error = function(e)
{
cat("Error:", e$message, "\n")
cat("Test failed.\n")
})
}
testfifelse()
Error: Length of 'na' is 4 but must be 1 or length of 'test' (3)
Test failed.
This correctly fails for the mutant whereas having the original operator in the condition (!=
) does not induce test failure, but not for the actual function: (handled somewhere else?)
library(data.table)
# Create a test case where len3 (length of 'na') equals len0 (length of 'test')
testfifelse <- function()
{
result <- tryCatch({
fifelse(c(TRUE, FALSE, TRUE), 1:3, 4:6, as.numeric(c(NA, NA, NA)))
message("Original condition passed.")
}, error = function(e)
{
message("Original condition failed: ", e$message)
})
result <- tryCatch({
fifelse(c(TRUE, FALSE, TRUE), 1:3, 4:6, NA)
message("Altered condition passed.")
}, error = function(e)
{
message("Altered condition failed: ", e$message)
})
}
testfifelse()
Original condition passed.
Altered condition passed.
- July 3, ‘24:
1) Tested the first forder
mutant (commenting line 167 of the original code) but no test case I made broke the function (also, a fair amount of tests already exists, e.g.: grep -r "forder" inst/tests/tests.Rraw
), and the change is also a slightly tricky one to construct test cases around. (8 hours)
- July 4, ‘24:
1) Tested the subset.c
mutants. Found test cases which break for both with and without the changes. (8 hours)
library(data.table)
dt <- data.table(a = 1:5)
index <- seq_len(max(dt$a))
expectedResult <- dt[seq(1, 4)]
result <- tryCatch({
dt[index]
}, error = function(e) {
NULL
})
if(!identical(result, expectedResult))
stop("Test failed.")
else
message("Test passed.")
The test case above for e.g. fails because the current implementation of the indexing behavior is not correctly handling the situation where the index vector contains the maximum value present in the a
column of dt
.
dt <- data.table(a = 1:5)
index <- c(-1, NA_integer_)
tryCatch({
result <- dt[index]
stop("Failed.")
}, error = function(e) {
message("Passed.")
})
- July 5, ‘24:
1) Helped with issue 6224. (9 hours)