test_that("gsSurvCalendar basic functionality works", { # Test default parameters x <- gsSurvCalendar() expect_s3_class(x, c("gsSurv", "gsDesign")) expect_equal(x$k, 3) # Default number of analyses expect_equal(x$test.type, 4) # Default test type # Test calendar time input validation expect_error( gsSurvCalendar(calendarTime = c(24, 12, 36)), "calendarTime must be an increasing vector" ) # Test spending type options x_info <- gsSurvCalendar(spending = "information") x_cal <- gsSurvCalendar(spending = "calendar") expect_false(identical(x_info$n.I, x_cal$n.I)) # Test minimum follow-up validation expect_error( gsSurvCalendar(calendarTime = c(12, 24), minfup = 25), "Minimum follow-up greater than study duration." ) }) test_that("gsSurvCalendar matches gsSurv under specific conditions", { # Create comparable designs cal_design <- gsSurvCalendar( test.type = 4, calendarTime = c(12, 24, 36), spending = "information", minfup = 6 ) # Get event counts for timing nevents <- sapply(cal_design$T, function(x) { xx <- nEventsIA(tIA = x, x = cal_design, simple = FALSE) sum(xx$eDC) + sum(xx$eDE) }) timing <- nevents / max(nevents) # Create matching gsSurv design surv_design <- gsSurv( k = 3, test.type = 4, timing = timing, T = max(cal_design$T), minfup = 6 ) # Compare key outputs expect_equal(cal_design$n.I, surv_design$n.I, tolerance = 1e-4) expect_equal(cal_design$lower$bound, surv_design$lower$bound, tolerance = 1e-4) expect_equal(cal_design$upper$bound, surv_design$upper$bound, tolerance = 1e-4) }) test_that("gsSurvCalendar handles different spending functions", { # Test with O'Brien-Fleming spending x_of <- gsSurvCalendar( sfu = gsDesign::sfLDOF, sfl = gsDesign::sfLDOF, calendarTime = c(12, 24, 36), spending = "information" ) expect_s3_class(x_of, c("gsSurv", "gsDesign")) # Test with Pocock spending x_pocock <- gsSurvCalendar( sfu = gsDesign::sfLDPocock, sfl = gsDesign::sfLDPocock, calendarTime = c(12, 24, 36), spending = "information" ) # Do Pocock spending with calendar time x_pocock_cal <- gsSurvCalendar( sfu = gsDesign::sfLDPocock, sfl = gsDesign::sfLDPocock, calendarTime = c(12, 24, 36), spending = "calendar" ) expect_s3_class(x_pocock_cal, c("gsSurv", "gsDesign")) # Verify different spending functions produce different bounds expect_false(identical(x_of$upper$bound, x_pocock$upper$bound)) expect_false(identical(x_pocock$upper$bound, x_pocock_cal$upper$bound)) # Verify cumulative spending matches spending function for information spending expect_equal( cumsum(x_pocock$upper$spend), gsDesign::sfLDPocock( alpha = x_pocock$alpha, t = x_pocock$upper$sTime )$spend, tolerance = 1e-4 ) # Verify cumulative spending matches spending function for calendar time expect_equal( cumsum(x_pocock_cal$upper$spend), gsDesign::sfLDPocock( alpha = x_pocock_cal$alpha, t = x_pocock_cal$upper$sTime )$spend, tolerance = 1e-4 ) # Verify spending time is proportion of full T expect_equal(x_pocock_cal$upper$sTime, x_pocock_cal$T / max(x_pocock_cal$T)) }) test_that("gsSurvCalendar output structure is correct", { x <- gsSurvCalendar() # Check essential components expected_names <- c( "k", "test.type", "alpha", "beta", "astar", "delta", "n.fix", "timing", "tol", "r", "n.I", "maxn.IPlan", "nFixSurv", "nSurv", "endpoint", "delta1", "delta0", "overrun", "usTime", "lsTime", "upper", "lower", "theta", "falseposnb", "en", "hr", "hr0", "R", "minfup", "gamma", "eDC", "eDE", "eNC", "eNE", "ratio", "lambdaC", "etaC", "etaE", "variable", "T" ) expect_true(all(expected_names %in% names(x))) # Check dimensions of key components expect_equal(length(x$n.I), x$k) expect_equal(length(x$upper$bound), x$k) expect_equal(length(x$lower$bound), x$k) # Check class attributes expect_true(inherits(x$upper, "spendfn")) expect_true(inherits(x$lower, "spendfn")) })