#' expect_equal_workbooks() ------------------------------------------ #' Quick internal expectation function. Easier to ignore fields to be set expect_equal_workbooks <- function(object, expected, ..., ignore_fields = NULL) { # object <- as.list(object) # expected <- as.list(expected) requireNamespace("waldo") assert_workbook(object) assert_workbook(expected) fields <- c(names(wbWorkbook$public_fields), names(wbWorkbook$private_fields)) bad <- setdiff(ignore_fields, fields) if (length(bad)) { stop("Invalid fields: ", toString(bad)) } for (i in ignore_fields) { object[[i]] <- NULL expected[[i]] <- NULL } bad <- waldo::compare( x = object, y = expected, x_arg = "object", y_arg = "expected", ... ) if (length(bad)) { testthat::fail(bad) return(invisible()) } testthat::succeed() return(invisible()) } # expect_wrapper helper -------------------- #' Expect wrapper #' #' Internal tool: see tests/testthat/test-workbook-wrappers.R #' #' @description Testing expectations for [wbWorkbook] wrappers. These test that #' the method and wrappers have the same params, same default values, and #' return the same value. #' #' Requires the `waldo` package, used within `testthat`. #' #' @param method The name of the [wbWorkbook] method #' @param fun The name of the wrapper (probably in R/class-workbook-wrappers) #' @param wb A `wbWorkbook` object #' @param params A named list of params. Set to `NULL` to not execute functions #' @param ignore Names of params to ignore #' @param ignore_attr Passed to `waldo::compare()` for the result of the #' executed functions #' @param ignore_fields Ignore immediate fields by removing them from the #' objects for comparison #' @param ignore_wb for pseudo wbWorkbook wrappers such as wb_load() we have #' to ignore wb #' @returns Nothing, called for its side-effects expect_wrapper <- function( method, fun = paste0("wb_", method), wb = wb_workbook(), params = list(), ignore = NULL, ignore_attr = "waldo_opts", ignore_fields = NULL, ignore_wb = FALSE ) { stopifnot( requireNamespace("waldo", quietly = TRUE), is.character(method), length(method) == 1L, is.character(fun), length(fun) == 1L, is.list(params) || is.null(params) ) method_fun <- get(method, wbWorkbook$public_methods) fun_fun <- match.fun(fun) # these come as pairlist -- we don't really care about that method_forms <- as.list(formals(method_fun)) fun_forms <- as.list(formals(fun_fun)) method_args <- names(method_forms) fun_args <- names(fun_forms) # remove wb and other ignores ignore <- c("wb", ignore) # remove ignores from fun m <- match(ignore, fun_args, 0L) if (!identical(m, 0L)) { # remove wb from both the args and formals fun_args <- fun_args[-m] fun_forms <- fun_forms[-m] } # remove ignores from method m <- match(ignore, method_args, 0L) if (!identical(m, 0L)) { # remove wb from both the args and formals method_args <- method_args[-m] method_forms <- method_forms[-m] } method0 <- paste0("wbWorkbook$", method) # adjustments for when wrappers don't have any args if (!length(method_args)) { method_args <- character() } if (!length(method_forms)) { method_forms <- structure(list(), names = character()) } # expectation that the names are the same (possibly redundant but quicker to) bad <- waldo::compare( x = method_args, y = setdiff(fun_args, "wb"), x_arg = method0, y_arg = fun ) if (length(bad)) { testthat::fail(bad) return(invisible()) } # expectation that the default values are the same bad <- waldo::compare( x = method_forms, y = fun_forms, x_arg = method0, y_arg = fun ) if (length(bad)) { testthat::fail(bad) return(invisible()) } if (!is.null(params)) { # create now so that it's the same every time wb_fun <- wb$clone(deep = TRUE) wb_method <- wb$clone(deep = TRUE) # be careful and report when we failed to run these # the style names are generated at random: use matching seeds for both calls options("openxlsx2_seed" = NULL) if (ignore_wb) { res_fun <- try(do.call(fun, c(params)), silent = TRUE) } else { res_fun <- try(do.call(fun, c(wb = wb_fun, params)), silent = TRUE) } options("openxlsx2_seed" = NULL) res_method <- try(do.call(wb_method[[method]], params), silent = TRUE) msg <- NULL if (inherits(res_fun, "try-error")) { temp <- file() writeLines(attr(res_fun, "condition")$message, temp) bad <- paste0("# > ", readLines(temp)) close(temp) expr <- paste0("\n", deparse1(do.call(call, c(fun, c(wb = wb_fun, params))))) msg <- c(msg, expr, bad) } if (inherits(res_method, "try-error")) { temp <- file() writeLines(attr(res_method, "condition")$message, temp) bad <- paste0("# > ", readLines(temp)) close(temp) expr <- paste0("\n", deparse1(do.call(call, c(method0, params)))) # slight fix because we get those "`" which I don't want to see expr <- sub(paste0("`", method0, "`"), method0, expr, fixed = TRUE) msg <- c(msg, expr, bad) } if (!is.null(msg)) { # browser() bad <- c("Failed to get results", msg) testthat::fail(bad) return(invisible()) } for (i in ignore_fields) { # remove the fields we don't want to check res_method[[i]] <- NULL res_fun[[i]] <- NULL } # expectation that the results are the same bad <- waldo::compare( x = res_method, y = res_fun, x_arg = method0, y_arg = fun, ignore_attr = ignore_attr, ignore_formula_env = TRUE ) if (length(bad)) { testthat::fail(bad) return(invisible()) } } testthat::succeed() return(invisible()) } # `expect_pseudo_wrapper()` ------- #' A trimmed down pseudo wrapper to check internal wrapped functions. #' @rdname expect_wrapper expect_pseudo_wrapper <- function( method, fun = paste0("wb_", method) ) { method_fun <- get(method, wbWorkbook$public_methods) fun_fun <- match.fun(fun) method_forms <- as.list(formals(method_fun)) fun_forms <- as.list(formals(fun_fun)) method_args <- names(method_forms) fun_args <- names(fun_forms) ignore <- "file" # remove ignores from fun m <- match(ignore, fun_args, 0L) if (!identical(m, 0L)) { # remove wb from both the args and formals fun_args <- fun_args[-m] fun_forms <- fun_forms[-m] } # remove ignores from method m <- match(ignore, method_args, 0L) if (!identical(m, 0L)) { # remove wb from both the args and formals method_args <- method_args[-m] method_forms <- method_forms[-m] } # expectation that the names are the same (possibly redundant but quicker to) bad <- waldo::compare( x = method_args, y = setdiff(fun_args, "wb") ) if (length(bad)) { testthat::fail(bad) return(invisible()) } # expectation that the default values are the same bad <- waldo::compare( x = method_forms, y = fun_forms ) if (length(bad)) { testthat::fail(bad) return(invisible()) } testthat::succeed() return(invisible()) } # Miscellaneous helpers for testthat ----------- expected_shared_strings <- function() { structure(c( "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "bool", "Date", "value", "word", "N-Z-P-S-Y", "C-G-D-X-H", "B-K-A-O-W", "H-P-G-O-K", "F-P-C-L-T", "A-N-Q-P-V", "Y-E-B-K-O", "V-S-N-T-R", "F-K-Z-U-S", "O-E-Z-T-G", "Q-X-F-L-N", "E-D-Y-Z-N", "W-F-L-C-I", "P-S-W-Y-E", "P-H-N-Q-Z", "S-O-L-W-J", "J-E-F-Q-K", "D-N-O-P-Z", "H-Z-K-S-U", "B-P-A-Y-R", "Z-I-X-J-V", "Y-S-I-M-X", "V-A-C-R-O", "O-V-S-C-Q", "A-K-S-V-W", "B-G-U-S-J", "Z-E-J-V-T", "P-F-C-N-T", "L-T-Z-D-V", "K-Q-Y-N-O", "U-S-Z-O-E", "Y-F-Z-C-P", "P-Y-M-I-K", "D-Y-A-L-T", "W-I-F-A-B", "I-H-S-W-K", "U-D-J-F-K", "B-K-G-J-V", "Y-J-E-N-B", "X-L-V-S-U", "A-I-B-S-P", "U-L-D-O-M", "M-D-V-R-X", "O-Q-K-S-B", "O-R-X-C-W", "O-F-M-A-X", "J-K-V-E-X", "W-B-S-O-A", "R-N-D-G-S", "W-J-K-M-R", "K-I-H-F-M", "U-F-X-P-A", "M-R-C-H-L", "H-A-E-X-J", "C-B-K-L-S", "V-A-I-S-L", "B-L-N-J-G", "J-X-A-D-O", "I-S-W-P-U", "D-R-M-G-C", "M-V-U-D-W", "U-S-A-Z-B", "T-E-N-F-P", "K-E-S-Z-Y", "D-J-O-T-A", "F-U-Y-T-R", "Q-U-N-P-J", "D-C-V-A-X", "S-B-F-E-V", "U-R-P-H-A", "R-C-Z-J-B", "L-B-M-F-I", "D-Y-B-S-Q", "X-Y-D-W-P", "Z-L-I-V-R", "Z-W-T-M-B", "Z-U-S-E-G", "V-I-M-C-O", "E-K-D-R-Z", "Z-F-H-Y-D", "O-I-X-M-A", "F-K-U-G-T", "I-P-X-J-M", "F-N-Z-E-C", "F-A-M-X-E", "R-V-C-O-P", "X-Y-C-V-H", "K-G-T-Y-I", "N-M-E-D-F", "M-K-N-U-W", "L-K-J-A-B", "S-M-T-D-A", "W-D-G-F-U", "X-R-Z-F-E", "H-L-N-G-P", "Z-X-W-M-R", "E-F-G-J-V", "X-I-M-Z-V", "T-A-O-L-Q", "F-T-X-N-B", "O-G-D-P-A", "B-K-Z-V-M", "M-J-O-S-X", "O-D-M-S-G", "W-O-V-A-D", "I-D-W-T-H", "E-C-I-A-L", "P-I-W-U-T", "Y-P-U-L-C", "Q-N-A-B-E", "C-F-X-Y-H", "Q-P-G-I-J", "A-Q-J-W-F", "G-N-R-U-D", "G-L-I-F-V", "Y-R-P-K-X", "V-W-B-G-S", "E-Q-D-N-F", "E-R-U-D-O", "O-E-G-X-L", "D-Q-G-A-K", "U-Z-N-C-V", "O-K-T-W-X", "L-W-G-K-Q", "I-F-O-X-Q", "J-B-V-W-T", "U-H-I-P-Q", "R-W-M-S-U", "F-U-M-W-H", "F-A-Q-U-K", "Q-R-D-K-I", "L-P-K-V-S", "G-I-B-U-Q", "Z-W-L-G-E", "Q-C-I-B-A", "J-N-Y-W-D", "T-Y-G-W-S", "L-M-A-G-K", "O-D-S-T-K", "O-G-L-T-Z", "N-Q-E-B-F", "B-F-W-A-X", "U-G-Q-B-M", "B-O-V-U-A", "R-K-X-H-A", "B-P-Q-T-R", "I-P-Z-L-V", "C-T-L-W-D", "L-Q-D-M-U", "N-P-H-A-G", "F-O-P-G-M", "N-M-Z-W-L", "G-V-K-Z-T", "F-J-T-C-U", "J-P-R-A-C", "Z-X-V-C-W", "B-Z-K-I-Q", "E-N-L-I-Y", "C-D-P-R-B", "I-W-X-P-V", "T-M-P-I-O", "W-Y-D-J-K", "A-O-C-L-B", "S-R-O-Y-C", "A-O-Y-N-W", "P-C-O-D-Y", "E-S-A-L-Y", "E-O-Q-W-C", "U-O-A-X-Q", "W-E-N-Y-D", "A-W-J-Z-X", "P-L-R-U-K", "V-J-E-K-Z", "V-A-M-G-D", "N-C-F-M-G", "H-W-N-K-R", "G-T-A-F-O", "K-F-V-G-S", "N-V-H-G-I", "F-Y-T-S-G", "A-H-O-C-V", "Q-W-J-S-C", "W-G-I-X-E", "D-B-V-A-N", "P-N-L-Y-Q", "O-I-R-Q-U", "D-R-W-E-O", "W-X-U-V-P", "X-Y-D-A-W", "M-J-B-S-G", "K-R-G-N-Y", "O-B-K-L-M", "G-N-Y-X-D", "K-F-A-B-T", "S-Z-R-L-A", "K-Y-W-X-A", "O-Q-X-I-D", "I-L-R-M-X", "S-D-V-U-N", "B-W-F-A-T", "A-W-X-R-J", "D-H-G-X-L", "E-C-V-U-T", "D-W-P-Z-F", "V-O-M-P-R", "P-L-B-X-N", "Z-U-F-D-V", "M-K-Z-S-Y", "X-P-N-T-D", "U-Q-D-T-S", "N-I-X-S-O", "S-C-K-F-D", "N-V-I-R-D", "Z-X-Y-B-P", "U-W-R-D-V", "G-V-I-N-K", "D-Y-N-T-J", "P-K-F-U-W", "U-I-P-D-Q", "R-T-Q-N-Z", "Z-R-D-V-O", "Z-S-F-T-D", "X-K-Z-B-W", "U-F-Z-S-Y", "X-I-T-Z-K", "A-X-H-N-Z", "R-U-Q-W-J", "C-H-P-V-Y", "R-O-A-T-E", "L-F-B-X-A", "Z-X-E-C-G", "R-B-C-Q-W", "A-O-Z-U-B", "R-W-P-S-H", "R-Y-B-A-W", "K-X-U-I-M", "O-X-F-P-A", "U-Y-P-D-M", "A-D-K-R-M", "R-U-D-T-M", "H-Q-Y-K-J", "T-B-H-N-U", "P-I-V-X-W", "S-H-X-C-U", "I-O-Y-G-W", "A-U-Z-J-R", "Q-U-H-M-A", "B-W-M-I-C", "P-X-Z-Y-N", "Y-J-W-N-B", "V-Y-U-S-B", "K-W-S-Q-M", "I-K-X-H-S", "F-L-M-Q-T", "S-Z-O-K-L", "O-P-N-G-E", "P-H-R-Q-T", "M-L-A-D-T", "D-S-X-V-H", "F-C-O-A-B", "P-I-N-O-H", "H-X-Y-I-C", "S-I-R-P-Q", "P-M-F-H-Y", "S-R-O-T-Q", "X-H-O-B-R", "W-P-A-Q-V", "E-L-Q-G-Y", "I-S-T-W-C", "B-M-R-G-Y", "S-J-A-K-Q", "E-P-B-G-J", "R-Y-E-L-D", "A-R-C-N-S", "Y-H-B-M-I", "T-Q-C-K-N", "L-T-Z-V-C", "Q-L-N-J-K", "T-E-J-M-Y", "E-M-F-R-C", "M-A-Y-D-I", "G-M-Y-F-Q", "A-X-B-E-N", "F-Y-E-H-L", "S-Z-R-M-O", "U-V-W-S-I", "D-S-E-L-K", "B-C-X-V-F", "Q-V-L-F-H", "H-Z-I-J-P", "W-U-O-M-D", "A-Y-T-O-X", "Y-C-Z-V-D", "E-L-O-X-Y", "D-U-K-X-A", "S-W-K-N-E", "D-F-T-E-Y", "J-T-B-C-L", "E-T-Z-V-F", "Q-D-U-P-E", "M-Q-X-T-J", "A-M-I-K-P", "J-T-B-E-R", "L-X-J-O-F", "X-B-V-W-P", "Y-N-H-G-Z", "M-F-K-S-P", "K-B-V-Z-L", "T-L-Y-G-A", "N-U-X-C-D", "W-B-O-X-Z", "U-Y-J-F-A", "T-V-J-I-S", "T-L-W-X-Z", "V-K-X-C-N", "G-C-I-S-Z", "C-T-K-S-Z", "F-I-D-N-E", "E-C-M-Y-J", "N-C-Y-S-I", "B-N-I-L-D", "Y-F-T-M-V", "R-A-E-O-M", "M-G-P-W-X", "H-B-C-D-R", "A-J-N-C-H", "R-O-F-D-N", "H-E-R-T-K", "M-U-S-V-A", "L-V-F-A-H", "E-Q-N-Y-C", "T-N-L-X-S", "C-F-X-A-N", "M-X-Y-C-Z", "A-N-F-B-K", "J-Q-R-Z-D", "Q-P-Y-G-N", "D-Y-O-R-J", "K-R-Y-N-O", "A-H-K-J-B", "O-G-J-A-S", "T-N-K-X-S", "V-P-X-Y-F", "R-P-V-G-T", "O-B-F-E-D", "Z-P-I-T-F", "T-S-D-X-G", "Y-J-P-Z-U", "H-W-Y-K-J", "H-Z-C-F-Q", "D-I-B-N-X", "K-B-U-H-E", "H-Y-U-Q-A", "N-Q-G-T-I", "J-B-V-E-G", "M-F-O-E-H", "B-P-K-M-I", "T-Z-B-Q-Y", "X-Y-T-P-O", "E-K-I-W-C", "C-M-R-S-Y", "F-Y-M-W-L", "A-S-E-U-J", "I-P-W-N-G", "V-G-R-E-T", "H-O-W-G-Y", "O-H-B-C-P", "C-Y-D-Q-X", "X-Y-I-Z-U", "R-I-Q-Y-P", "E-M-L-D-Y", "B-G-P-Y-T", "Z-H-X-D-V", "S-B-R-J-F", "O-T-X-P-W", "Y-C-T-M-E", "J-A-D-O-P", "B-W-Q-D-I", "Y-T-X-K-Q", "F-D-P-X-J", "Z-G-Y-O-N", "J-N-Z-Q-P", "W-C-E-I-U", "L-R-K-F-H", "X-I-G-B-O", "M-C-Q-Y-Z", "S-T-W-J-E", "G-O-N-Y-Q", "O-Q-R-Z-B", "X-G-E-C-I", "P-B-D-F-Q", "Q-H-D-I-V", "H-I-J-D-Q", "C-B-S-I-G", "M-A-F-D-B", "G-Z-R-U-K", "N-U-L-Q-R", "C-A-K-M-T", "F-S-R-B-K", "O-D-X-S-W", "H-J-N-P-C", "N-G-Y-L-J", "D-X-K-O-E", "F-E-H-D-L", "E-M-D-P-Z", "Q-K-I-J-V", "D-O-N-M-X", "C-P-N-E-K", "L-H-T-U-P", "M-T-Z-P-H", "B-T-L-Z-G", "Z-V-R-C-I", "J-M-R-D-G", "I-V-L-Q-T", "O-V-X-A-M", "V-L-N-A-T", "M-B-R-U-O", "O-B-Q-F-X", "H-O-E-K-G", "S-H-G-B-D", "N-Z-C-L-D", "M-F-J-H-K", "A-O-D-W-B", "I-X-G-K-W", "B-S-O-K-Q", "X-T-Z-I-D", "N-D-G-B-L", "Z-O-U-I-X", "W-B-A-R-H", "S-G-Q-J-F", "M-B-J-F-A", "M-B-X-A-P", "F-M-S-Y-V", "T-K-B-G-C", "H-V-C-G-X", "V-A-S-I-T", "Z-X-G-U-S", "U-J-Y-M-H", "D-Y-H-X-S", "T-Q-X-I-E", "S-V-K-M-T", "S-Z-P-O-Y", "V-Y-Q-L-F", "A-E-R-V-G", "E-C-M-G-O", "T-B-U-M-V", "M-R-V-A-E", "C-A-R-W-N", "Y-U-D-Z-X", "Y-G-Z-C-Q", "T-X-R-A-D", "S-A-U-R-K", "E-A-D-R-V", "P-R-T-W-F", "A-Z-Y-O-N", "O-P-W-A-I", "H-V-U-R-F", "W-D-G-P-I", "M-Z-Q-C-I", "Y-S-H-W-I", "F-J-C-N-S", "H-C-Z-Y-K", "W-J-K-Z-I", "Q-T-G-C-X", "S-Q-T-O-Y", "Z-G-T-W-X", "X-M-J-R-W", "S-Y-N-F-H", "C-F-V-G-A", "W-R-J-I-B", "I-V-B-A-M", "R-C-D-L-U", "S-T-B-A-N", "F-W-J-M-A", "J-I-R-E-H", "Q-D-O-E-R", "R-B-M-O-J", "B-X-G-V-U", "R-J-L-Y-M", "R-F-A-X-J", "N-I-J-V-Q", "J-O-D-Q-Z", "K-I-F-D-H", "N-H-Q-Z-M", "I-K-R-Z-X", "O-D-U-T-I", "K-G-S-L-Y", "X-D-O-K-A", "C-X-I-P-J", "X-A-Y-V-T", "I-V-T-J-O", "X-D-M-H-U", "M-L-R-Y-J", "N-L-I-R-B", "A-J-Z-O-Q", "G-Y-I-S-E", "N-F-X-Z-T", "U-G-C-F-K", "R-N-W-S-M", "A-O-T-N-U", "W-O-P-G-V", "D-W-E-H-O", "B-D-S-E-Z", "C-L-V-M-I", "Y-N-C-W-B", "C-Q-L-P-W", "X-H-L-B-M", "H-V-D-K-Q", "O-S-C-U-H", "V-I-J-K-A", "D-M-B-I-F", "O-H-N-J-V", "R-L-Q-J-Y", "Q-P-B-S-X", "J-K-V-H-F", "A-T-L-Q-B", "E-D-S-B-G", "K-T-X-J-Q", "W-L-U-B-H", "T-Y-Z-G-V", "G-S-C-X-P", "D-C-M-Z-Y", "V-G-F-D-E", "Q-F-X-O-U", "E-V-L-F-G", "M-T-V-U-Y", "Z-X-S-U-E", "J-I-F-E-R", "C-V-J-R-W", "W-R-V-U-K", "M-A-S-U-Q", "J-K-O-F-I", "I-Y-G-U-Z", "B-Y-V-D-R", "M-G-Q-N-J", "A-F-N-K-M", "R-B-D-Q-P", "H-T-N-U-L", "J-W-E-A-B", "N-M-K-R-O", "H-Q-A-N-E", "U-B-Y-L-Q", "J-E-N-T-Q", "D-N-L-R-E", "K-S-O-L-Z", "Z-D-Y-A-N", "D-Q-B-X-Z", "J-E-F-O-Q", "U-E-Q-T-R", "U-H-F-N-L", "C-T-I-V-X", "V-L-Q-O-K", "G-Q-D-P-V", "D-T-V-G-S", "I-G-H-Z-L", "A-E-I-Y-B", "S-V-N-B-R", "M-P-J-Y-N", "D-T-W-Q-Z", "U-V-F-A-S", "M-B-T-Y-Q", "F-I-C-D-X", "G-X-O-K-J", "J-M-I-E-D", "C-B-S-F-A", "A-Y-O-Z-P", "R-T-H-L-S", "P-X-B-S-O", "B-I-C-P-T", "F-K-H-Z-N", "R-D-Y-T-P", "S-U-P-G-R", "M-K-R-Q-V", "Z-E-O-U-T", "M-W-Y-X-C", "Q-J-U-T-B", "L-H-S-J-U", "P-M-X-R-N", "S-Y-T-G-W", "W-P-N-V-O", "E-U-I-L-M", "V-S-K-J-R", "P-E-T-C-X", "E-V-C-S-Y", "M-S-F-T-Q", "L-D-P-K-T", "D-Z-U-Q-P", "D-H-L-W-N", "V-U-Q-I-A", "L-D-G-H-V", "G-I-U-Q-E", "G-E-D-R-H", "N-T-L-K-H", "J-U-K-F-V", "G-J-Y-K-W", "E-A-I-G-Q", "S-U-H-R-T", "L-S-W-H-C", "P-V-I-Y-O", "E-L-K-X-N", "Y-B-S-T-N", "N-U-V-E-Z", "B-V-K-M-O", "L-V-H-A-K", "M-U-T-J-K", "V-J-T-F-R", "T-Y-E-U-W", "C-D-B-A-L", "K-E-U-S-A", "D-H-R-X-Z", "M-B-Z-G-C", "P-E-T-S-Y", "M-G-O-J-F", "C-Y-E-P-X", "R-V-D-C-N", "S-Y-A-K-Z", "K-S-G-T-D", "D-F-G-U-K", "F-B-P-T-M", "P-G-O-D-W", "U-L-I-R-J", "F-Q-N-X-J", "D-Q-F-V-B", "R-P-E-Z-H", "A-H-X-M-L", "I-H-F-G-W", "V-C-M-H-Y", "V-H-L-Y-F", "H-I-L-P-V", "L-Q-W-K-A", "D-W-J-R-L", "W-E-V-J-L", "F-Z-X-U-H", "K-U-Q-I-R", "S-D-N-E-V", "G-T-E-L-Y", "S-P-E-B-D", "U-N-L-S-O", "Z-G-W-I-X", "M-C-X-S-E", "P-C-S-X-Y", "B-Z-K-R-H", "D-J-W-Y-U", "J-O-Q-F-P", "I-A-V-G-Y", "U-B-V-G-N", "W-H-Q-M-E", "J-R-O-D-F", "W-M-C-O-P", "R-I-F-M-Q", "Q-L-D-W-X", "M-A-Q-P-F", "O-J-T-L-A", "X-S-I-P-G", "G-W-D-Y-F", "T-B-M-N-J", "Q-W-N-Z-C", "M-F-C-O-H", "Z-N-Q-X-P", "Q-G-A-Y-C", "R-F-G-P-E", "X-J-F-R-C", "J-S-Q-E-L", "O-K-P-F-D", "R-J-W-G-T", "Y-P-J-N-D", "N-S-F-Y-T", "M-L-N-H-U", "V-A-H-G-Q", "H-L-W-K-P", "U-P-G-V-O", "V-N-P-I-Y", "A-O-E-F-L", "W-F-Q-J-G", "B-A-L-V-Q", "Y-J-F-V-S", "O-F-E-J-A", "X-O-F-M-B", "B-M-L-H-W", "Z-X-F-T-B", "W-X-E-M-A", "F-J-V-W-L", "P-C-U-R-O", "S-K-F-D-V", "K-F-Z-Q-C", "J-S-R-M-Q", "E-H-L-Q-N", "W-F-M-E-X", "P-R-E-N-A", "D-F-G-N-Y", "I-S-O-V-T", "R-I-C-N-L", "I-T-C-Y-P", "R-W-I-K-X", "P-B-J-X-G", "D-W-F-N-E", "M-G-C-B-K", "E-T-H-F-W", "A-E-L-F-Z", "Z-V-W-S-R", "O-T-L-D-Q", "S-E-M-Z-O", "N-R-Y-A-U", "Y-D-M-A-R", "S-M-P-N-K", "C-T-B-L-Z", "X-A-L-I-V", "B-V-M-G-S", "N-R-K-Q-D", "F-O-L-X-Y", "Y-T-F-A-S", "X-G-O-U-A", "Z-F-I-B-T", "V-H-B-N-W", "V-K-B-W-S", "V-C-T-L-G", "X-N-L-Y-Q", "N-D-L-I-Z", "L-K-G-N-E", "D-L-M-K-Z", "E-I-P-Z-U", "H-X-B-C-D", "B-H-D-C-V", "F-O-L-D-R", "B-Z-J-Y-V", "E-C-R-B-S", "E-X-V-B-S", "P-K-I-W-G", "A-I-F-V-O", "D-F-R-I-E", "X-L-I-N-O", "P-Y-Q-C-S", "C-P-A-X-L", "W-O-U-A-X", "H-M-R-E-B", "K-Y-P-G-A", "O-E-V-D-C", "Z-A-K-M-W", "S-F-M-Z-E", "X-U-I-C-J", "C-V-T-B-N", "Z-Q-Y-V-G", "T-W-G-Q-D", "K-Y-L-R-F", "W-O-S-E-A", "V-T-Q-F-G", "G-V-J-M-U", "P-R-A-N-C", "I-R-A-F-T", "X-Z-U-W-N", "A-G-R-D-Y", "J-U-T-A-Q", "K-Y-T-H-U", "P-Q-L-Z-G", "N-K-Y-X-W", "A-T-M-R-Z", "M-B-P-C-L", "M-Q-K-N-R", "I-W-H-G-R", "I-F-D-Q-A", "V-G-F-C-X", "H-Q-F-D-T", "N-R-T-Q-G", "X-V-P-B-G", "V-H-B-N-X", "G-Q-T-J-Y", "P-F-A-N-H", "C-D-I-W-K", "T-R-J-B-P", "E-P-X-L-S", "O-K-B-L-M", "Z-T-B-R-V", "V-N-Y-Z-U", "E-W-V-F-O", "D-S-A-Z-J", "R-O-W-A-Y", "V-L-K-J-Q", "Q-T-J-S-Z", "M-G-L-Y-D", "G-U-W-I-C", "G-O-D-T-I", "R-L-Z-P-V", "W-G-M-T-I", "S-F-H-Z-J", "Z-L-O-V-N", "G-D-A-U-H", "Y-K-V-R-E", "Y-O-L-R-I", "X-V-Z-I-B", "N-Z-S-D-O", "N-X-Z-J-M", "S-X-A-H-C", "V-T-R-F-H", "K-E-Q-B-J", "V-R-J-U-G", "Q-K-B-P-Z", "Y-I-S-X-K", "U-O-R-Q-J", "Q-T-X-F-D", "P-O-F-B-J", "C-M-K-L-F", "N-W-Y-A-V", "E-H-I-G-U", "L-J-X-A-C", "Q-K-U-D-B", "A-S-R-D-T", "S-Z-E-Y-U", "A-K-R-S-G", "S-F-R-J-Q", "A-Y-J-F-U", "L-I-J-R-H", "K-C-V-Q-F", "H-U-A-T-D", "E-W-L-I-C", "Y-P-R-F-V", "L-M-P-Z-U", "T-Q-U-P-V", "Q-W-T-M-K", "P-D-G-Y-K", "F-I-K-C-P", "I-T-Y-K-L", "H-T-K-I-R", "H-K-B-M-F", "J-P-D-Z-Q", "D-M-K-C-V", "E-K-Y-F-R", "P-L-H-A-J", "R-C-Z-V-T", "I-W-G-A-T", "Y-N-X-K-R", "M-N-E-C-Q", "J-B-W-R-X", "R-M-D-T-F", "R-V-L-Y-G", "M-V-E-Z-Q", "S-H-Q-X-G", "H-P-Y-Q-G", "F-N-K-T-W", "I-B-Z-P-F", "G-P-N-S-F", "B-Y-S-N-A", "P-I-Z-A-S", "X-I-K-B-Y", "B-Q-F-W-M", "Y-E-J-P-M", "V-E-T-G-O", "M-N-L-K-I", "N-D-W-B-V", "F-P-S-M-X", "K-H-Q-M-F", "Z-B-O-I-L", "L-F-D-S-E", "W-Y-P-B-A", "L-P-S-V-U", "D-G-L-J-P", "K-U-F-Y-E", "J-G-R-M-N", "J-U-P-H-O", "O-U-N-M-W", "X-V-J-K-E", "C-W-G-L-K", "D-H-A-O-K", "H-G-C-X-P", "B-C-I-J-D", "N-L-T-D-S", "X-D-C-A-T", "Z-D-U-N-E", "P-W-A-I-L", "N-U-G-H-C", "F-Q-E-V-T", "X-O-M-S-U", "Z-V-S-Q-R", "K-Z-U-D-L", "A-O-Z-C-T", "S-K-U-T-Q", "V-Q-I-B-Z", "A-K-Z-N-Y", "T-G-V-Y-O", "G-K-R-A-J", "Y-J-F-T-U", "E-P-K-G-F", "U-P-X-L-V", "H-C-S-M-I", "K-D-X-W-N", "F-E-P-V-R", "C-P-V-W-L", "I-S-M-E-B", "D-E-L-C-O", "A-D-V-U-W", "D-I-N-M-Z", "O-Z-K-S-N", "F-J-W-L-S", "H-C-V-W-I", "B-A-L-V-Y", "N-K-Z-W-X", "Z-C-X-K-A", "S-X-H-G-Y", "L-G-M-V-Q", "Z-L-G-Y-Q", "J-W-E-A-D", "G-S-A-M-U", "F-M-D-K-O", "B-O-G-R-K", "V-S-U-Q-B", "R-X-O-N-F", "Y-N-M-H-I", "T-J-W-Q-L", "R-W-P-B-H", "D-A-I-P-E", "D-P-Q-T-N", "Y-K-Q-U-X", "A-Y-M-C-R", "M-O-I-L-B", "Y-O-K-J-F", "O-C-J-X-H", "W-J-X-L-Z", "F-P-H-A-L", "M-T-F-U-P", "W-H-F-C-X", "R-C-D-Z-L", "Y-B-A-I-L", "S-I-Y-W-P", "K-D-X-G-Z", "O-W-Q-M-G", "M-T-V-L-G", "F-Z-Y-J-L", "V-L-A-S-N", "I-P-A-S-N", "G-T-Q-D-F", "G-R-L-W-V", "I-R-Z-V-P", "M-L-B-A-I", "D-K-Z-F-M", "M-O-G-X-V", "Y-V-D-Z-W", "M-S-O-G-T", "Z-F-M-U-X", "V-N-Z-P-I", "N-D-F-U-J", "G-O-U-E-S", "Z-C-G-W-B", "O-T-E-N-V", "W-P-H-C-V", "X-R-D-P-G", "Y-C-E-F-T", "V-O-G-K-I", "S-I-W-M-L", "M-H-C-O-A", "Q-C-N-Z-D", "A-N-L-S-T", "X-W-I-L-K", "A-Y-V-S-K", "D-W-F-L-K", "U-Z-I-R-Q", "V-W-B-A-T", "I-U-R-E-W", "N-W-U-Q-O", "F-H-L-N-O", "D-I-T-J-H", "W-K-Q-D-T", "A-O-R-I-U", "M-E-V-A-F", "U-J-M-X-S", "O-E-R-K-H", "A-V-Z-T-D", "C-Z-B-D-L", "D-J-T-Q-G", "A-O-C-I-Z", "J-L-A-Y-C", "P-O-H-E-V", "A-M-Z-I-R", "W-C-R-H-V", "Z-G-I-V-N", "K-M-W-T-Q", "O-I-F-D-N", "X-D-A-V-T", "T-S-M-B-D", "F-C-D-U-Q", "B-H-M-Q-G", "M-K-I-W-B", "R-M-Q-W-P", "N-Z-L-F-G", "I-P-J-B-W", "O-Y-W-U-V", "C-V-Z-B-O", "O-Q-S-F-X", "B-G-F-M-W", "N-X-R-P-S", "L-T-A-H-R", "G-O-E-L-X", "R-I-U-X-Y", "Q-O-Z-F-V", "O-P-J-C-M", "D-W-G-S-L", "T-K-W-L-O", "E-I-O-K-D", "K-E-A-I-S", "M-I-W-F-K", "S-W-G-T-N", "P-L-J-D-A", "O-M-T-J-P", "C-R-Z-L-G", "F-S-D-V-K", "N-J-H-V-I", "D-I-A-F-J", "U-R-T-V-X", "J-N-T-R-S", "K-V-Z-T-Q", "J-L-C-R-M", "Z-A-R-L-E", "Y-L-W-I-S", "B-W-E-N-U", "B-S-W-J-F", "D-G-I-P-S", "D-Q-M-E-R", "K-T-R-A-D", "P-Q-L-E-U", "U-D-W-A-O", "Q-R-P-D-Y", "C-X-V-S-I", "F-E-U-I-K", "H-Z-T-L-P", "P-I-U-B-O", "S-Q-G-W-K", "K-V-S-U-L", "F-N-Q-O-P", "M-Q-F-C-L", "V-X-G-C-A", "N-S-E-C-V", "R-K-J-A-X", "D-L-H-W-S", "Z-C-Y-L-G", "M-D-W-F-U", "R-A-U-S-F", "Y-W-H-V-Q", "B-K-G-J-W", "B-V-H-E-C", "D-J-X-S-H", "W-C-H-Z-Q", "X-B-A-I-U", "D-A-J-C-F", "B-P-U-S-W", "A-D-R-Z-K", "S-H-P-A-Z", "J-O-U-P-S", "W-C-H-P-T", "C-U-Z-O-W", "P-E-H-M-S", "B-W-L-Y-N", "N-S-F-R-Y", "W-R-K-A-N", "G-X-V-D-E", "I-G-D-P-T", "W-N-J-R-L", "P-Q-H-A-V", "U-Q-R-P-W", "I-H-Q-X-U", "W-K-R-M-N", "U-H-Q-B-Y", "X-P-D-V-W", "E-K-F-R-C", "T-E-B-N-L", "I-S-K-Q-H", "Y-Z-V-Q-L", "W-L-U-P-I", "Y-P-F-H-O", "M-C-Y-T-I", "Q-A-V-Z-O", "I-H-U-K-F", "Q-Z-C-W-Y", "U-M-Q-C-R", "U-H-S-M-W", "R-C-M-Y-G", "R-C-J-A-V", "X-B-Z-C-Y", "P-C-O-J-I", "E-C-O-W-R", "E-T-Y-X-F", "Q-M-C-K-S", "H-I-O-J-K", "R-P-N-J-V", "H-Y-P-N-V", "R-J-I-L-S", "N-K-T-Z-O", "H-B-K-A-P", "P-G-J-A-B", "L-S-O-I-Y", "L-U-R-Z-D", "F-I-K-Q-B", "Q-K-X-B-M", "A-C-L-B-I", "J-E-O-D-K", "Y-W-V-G-D", "S-N-T-H-Q", "K-M-D-R-H", "B-U-N-A-T", "A-J-F-O-C", "J-L-V-R-D", "X-A-Q-J-R", "I-V-E-W-Z", "Q-G-K-P-X", "O-H-K-J-D", "N-K-I-J-B", "Y-R-N-G-C", "K-L-E-B-S", "O-P-T-D-G", "O-R-E-J-V", "X-V-B-Z-U", "Y-H-I-O-C", "B-O-Y-M-P", "J-Z-R-Q-P", "A-E-K-M-D", "D-X-L-F-U", "J-X-U-A-Z", "Y-R-G-X-Q", "Y-R-P-W-C", "K-Q-C-Y-L", "K-H-L-V-U", "P-A-N-I-C", "M-D-Y-F-A", "H-V-D-F-U", "Z-D-P-U-J", "O-E-I-Z-Q", "L-Q-A-O-I", "L-V-C-K-N", "E-Z-R-Q-K", "N-T-V-U-D", "U-B-O-H-Z", "F-X-D-H-U", "T-W-R-O-G", "G-A-O-Z-L", "Z-C-B-G-P", "O-I-B-S-N", "Z-R-I-O-Y", "K-B-L-C-Z", "Z-B-T-F-D", "B-H-P-J-C", "A-T-L-N-M", "O-P-W-M-S", "Q-I-L-G-J", "O-D-Q-J-M", "P-B-F-Z-V", "Q-H-J-I-C", "K-V-W-Z-D", "Y-A-R-Z-Q", "M-U-H-Q-N", "O-D-K-J-Z", "I-C-Z-J-H", "E-K-R-G-M", "D-B-G-Y-K", "U-Q-B-C-L", "Y-Q-M-W-L", "A-Z-J-B-S", "C-W-K-O-X", "G-E-V-B-R", "L-N-Q-T-H", "H-E-X-A-J", "U-O-Z-S-B", "P-G-W-K-D", "J-W-L-C-A", "L-C-E-V-Z", "T-K-Y-Q-P", "Z-J-Q-U-V", "V-C-P-K-X", "U-X-A-H-E", "I-J-E-Z-W", "O-M-W-F-S", "N-K-Y-P-M", "C-G-K-L-R", "M-T-V-A-E", "D-V-H-Q-F", "M-N-P-W-L", "G-E-F-T-M", "G-X-D-Q-O", "X-G-W-E-Z", "U-C-B-P-Z", "F-K-Z-W-H", "P-C-D-F-L", "N-V-G-R-T", "I-N-B-J-T", "B-T-A-M-L", "Q-D-N-Y-I", "B-I-K-X-A", "C-U-F-S-K", "W-X-G-P-L", "H-A-P-L-C", "W-T-K-P-F", "G-B-U-T-K", "U-S-Q-Y-Z", "G-C-E-Z-W", "Z-Y-Q-B-M", "D-Y-N-C-E", "E-J-Q-K-I", "P-R-O-B-V", "D-E-A-S-U", "I-A-M-E-L", "M-K-U-F-Y", "L-Q-H-S-O", "Z-F-V-T-P", "V-N-M-R-J", "Q-E-P-K-O", "O-H-J-U-K", "U-Z-Q-O-F", "R-X-K-O-C", "L-R-K-C-G", "V-F-B-S-K", "L-Z-O-H-E", "D-S-Y-V-K", "R-J-V-A-C", "P-L-B-Q-Z", "U-Q-Z-X-Y", "E-P-L-F-T", "Z-F-C-G-B", "W-V-C-A-J", "O-N-C-Y-H", "B-Y-C-D-Z", "E-X-G-H-Z", "Y-H-X-J-I", "O-K-P-J-D", "G-E-K-T-B", "G-A-K-Y-P", "T-V-X-P-H", "W-Y-D-K-V", "Z-W-B-P-Q", "A-J-F-U-P", "V-A-X-E-Z", "F-T-J-E-I", "V-M-L-Z-U", "H-I-B-L-Q", "C-D-V-K-M", "G-Z-F-J-R", "C-T-N-U-H", "W-Y-U-X-M", "T-F-I-W-V", "X-O-P-Y-W", "L-Z-P-B-K", "A-E-T-Q-K", "K-P-C-T-Z", "C-A-H-G-E", "B-W-G-D-V", "A-S-D-B-I", "T-D-G-C-P", "J-B-F-T-K", "V-R-L-U-F", "O-P-Q-X-M", "K-M-T-E-D", "R-B-H-X-G", "L-C-O-Y-B", "R-Z-U-E-I", "K-I-W-O-G", "Z-X-W-F-K", "Y-C-B-S-V", "L-M-R-N-Z", "B-Q-M-Z-K", "P-S-Z-O-T", "Y-A-Z-N-R", "L-O-A-P-J", "O-Z-Y-M-P", "C-P-S-J-Q", "Y-F-Q-A-R", "U-Z-K-B-X", "Q-R-T-H-X", "N-U-E-Q-A", "X-Z-R-J-C", "U-X-E-A-Z", "Y-M-O-A-V", "N-K-D-W-M", "V-Q-E-F-S", "L-U-A-Z-D", "X-S-R-P-E", "I-B-O-Z-L", "J-G-K-H-Z", "T-P-O-Z-S", "L-I-R-G-N", "Y-C-O-Z-A", "H-B-D-Q-R", "C-L-J-E-T", "K-Z-N-U-X", "P-F-S-Z-H", "S-N-D-R-T", "V-R-S-T-G", "N-S-F-U-Y", "D-P-L-C-A", "B-X-V-M-S", "B-M-Z-E-Q", "K-Y-S-P-B", "K-T-V-F-G", "U-Z-B-W-E", "J-X-O-C-Y", "X-C-Q-P-D", "X-L-Y-J-Z", "Y-F-O-N-H", "M-J-B-Z-X", "G-X-R-A-D", "E-I-L-O-A", "B-R-C-I-K", "K-W-F-N-P", "C-Y-R-A-H", "J-H-D-N-C", "P-Y-C-I-D", "P-D-C-U-E", "H-A-I-E-P", "B-N-E-H-S", "C-Y-P-E-F", "K-F-X-B-S", "M-Q-D-I-Z", "V-S-P-K-O", "L-W-M-T-I", "K-N-B-V-D", "A-Z-N-X-G", "U-T-D-A-Y", "Q-Z-D-F-E", "J-Q-I-Y-C", "G-L-E-O-R", "V-J-Z-K-F", "O-W-F-X-H", "H-R-P-X-L", "B-F-X-G-P", "I-C-A-M-R", "P-N-W-Z-L", "R-G-O-H-D", "G-M-B-W-K", "G-D-E-H-P", "Z-K-I-P-N", "K-V-C-E-W", "O-K-N-T-R", "K-B-N-X-M", "E-V-A-X-P", "Q-J-I-Y-C", "I-T-U-J-D", "W-U-T-O-Q", "O-E-H-J-A", "D-K-P-A-I", "D-J-A-F-X", "T-X-D-V-A", "B-W-T-H-V", "H-G-Q-E-U", "B-U-F-Z-Y", "O-S-R-T-D", "F-W-S-I-G", "Z-O-X-C-S", "H-V-K-N-E", "Z-M-L-E-O", "Q-V-T-M-P", "T-N-D-C-S", "L-F-Q-R-Y", "U-F-S-I-O", "S-R-M-B-K", "D-P-W-U-A", "Y-W-A-T-E", "I-W-A-F-J", "V-J-G-A-Q", "Z-S-C-Y-L", "T-C-N-O-S", "J-R-Y-X-Q", "A-F-P-N-J", "R-Y-N-H-M", "S-W-Q-B-V", "N-Q-U-G-K", "T-A-Y-R-Z", "I-L-O-U-V", "W-B-L-F-Q", "N-T-E-W-G", "L-S-I-W-X", "P-A-Z-J-U", "Z-N-F-X-G", "P-B-O-E-N", "D-U-T-C-K", "G-Y-I-K-S", "F-H-W-X-P", "O-B-T-E-Z", "N-K-T-S-X", "E-S-T-N-V", "E-A-J-Q-F", "P-Q-D-X-B", "R-F-J-E-Q", "X-Z-S-M-V", "E-Z-Q-D-X", "M-O-T-U-D", "O-I-X-Z-H", "H-T-V-I-M", "U-E-A-D-W", "Z-D-F-A-X", "E-D-V-P-N", "K-J-R-M-H", "V-A-K-U-D", "S-B-L-A-N", "Q-C-Z-D-P", "U-Z-A-W-C", "V-D-M-G-B", "Z-H-A-I-X", "W-F-H-R-X", "G-E-V-F-K", "H-A-V-L-E", "K-P-E-X-Y", "T-O-Y-R-P", "H-T-F-U-K", "R-V-N-C-X", "K-H-Z-R-A", "Q-P-J-G-N", "T-F-L-K-E", "E-T-O-D-G", "J-K-E-S-N", "K-Q-D-C-B", "Q-R-A-F-D", "J-W-A-Q-I", "N-T-F-G-D", "E-R-I-D-N", "M-G-P-Q-V", "D-P-R-G-N", "N-C-F-T-A", "D-F-Q-X-O", "U-D-K-Q-X", "N-G-M-Q-A", "I-X-F-D-V", "R-T-C-K-I", "S-G-E-R-O", "R-B-J-G-Z", "J-X-G-K-R", "U-K-O-L-C", "X-Q-U-S-B", "B-A-M-V-N", "N-A-V-G-U", "I-Y-U-Z-C", "Y-R-I-M-V", "Y-I-R-P-N", "E-C-Q-A-P", "P-Z-B-O-A", "D-A-R-F-Y", "Q-E-T-L-N", "Z-D-F-Q-C", "X-T-Q-W-D", "D-P-Y-U-J", "S-J-Q-X-V", "E-O-P-W-N", "W-Q-B-O-Y", "Y-Z-W-Q-F", "H-Q-C-X-O", "S-B-W-V-L", "G-R-Y-V-J", "W-F-G-K-S", "F-N-P-D-S", "L-C-Q-T-Z", "V-S-Y-O-B", "L-F-X-U-Q", "G-D-R-M-E", "P-Q-R-Y-G", "N-E-H-L-P", "Z-R-F-M-U", "I-X-C-F-O", "L-E-X-K-O", "G-V-Y-X-F", "O-P-V-A-Z", "P-K-S-L-Y", "Q-R-K-M-D", "A-N-B-J-R", "C-S-G-R-M", "H-C-E-O-D", "E-I-N-F-O", "F-S-P-O-B", "T-S-A-X-B", "R-K-Y-L-M", "F-G-O-C-T", "C-F-H-Y-Z", "M-P-Z-A-V", "N-U-X-B-T", "Q-A-V-N-P", "D-R-V-C-K", "U-P-X-M-F", "S-P-I-T-Z", "O-Z-C-U-Y", "B-G-X-A-D", "Y-U-L-A-W", "O-J-Q-W-G", "V-B-I-F-D", "V-J-Q-K-A", "H-X-W-S-A", "E-D-F-T-I", "H-Q-V-R-L", "M-U-Z-K-Q", "V-Y-U-Q-X", "H-M-I-U-O", "N-Q-P-U-R", "Y-F-I-V-D", "F-A-L-W-M", "G-Q-M-L-B", "X-B-L-P-W", "I-A-R-Q-F", "U-E-J-T-V", "O-B-Q-U-S", "B-P-U-S-M", "N-Z-D-O-V", "A-X-S-T-V", "O-Y-C-F-K", "D-S-I-M-Y", "B-Y-N-G-I", "G-P-U-M-F", "V-B-G-N-W", "C-K-I-S-Y", "U-B-I-R-V", "L-R-M-C-Z", "T-Z-D-U-M", "R-M-F-T-O", "S-V-D-F-Y", "M-F-R-C-J", "G-P-O-X-W", "M-R-X-H-Z", "N-D-J-R-Y", "B-J-W-U-L", "T-E-U-D-J", "M-V-J-R-B", "G-X-Z-U-Y", "L-C-P-M-D", "H-Z-W-E-T", "O-H-Y-C-K", "M-B-Q-N-E", "B-D-E-U-V", "V-P-F-Y-R", "U-M-C-J-L", "P-X-L-Z-A", "D-E-F-X-H", "P-I-Z-C-V", "V-N-O-B-G", "M-T-U-D-P", "I-A-E-O-Q", "V-R-S-L-A", "S-I-Q-N-T", "A-W-T-O-U", "O-T-V-A-Q", "D-R-O-Z-F", "Z-M-F-Q-I", "B-H-E-L-M", "Z-S-D-L-G", "E-B-N-A-Q", "K-Z-O-C-D", "Y-J-M-C-Z", "K-O-F-A-G", "J-U-L-Y-G", "A-F-C-V-D", "S-B-H-T-U", "J-F-V-T-Q", "H-L-Z-K-M", "F-Q-O-K-S", "P-S-U-V-A", "Y-L-E-D-F", "Z-L-U-K-V", "J-N-M-P-F", "G-M-F-Y-Z", "W-P-N-D-U", "J-V-Q-H-P", "Q-B-H-O-R", "U-R-J-K-W", "J-Q-S-O-F", "S-J-N-T-O", "A-S-B-Q-W", "W-X-Q-H-I", "K-R-V-S-X", "Q-S-O-R-W", "R-Q-N-G-Z", "Z-P-A-S-R", "F-N-X-K-D", "S-I-X-A-W", "K-E-J-H-G", "D-N-Z-W-U", "X-Y-T-J-O", "X-I-J-Z-S", "R-V-L-W-C", "X-T-A-M-I", "A-W-B-K-M", "E-C-Q-T-X", "A-B-V-W-X", "K-O-B-W-Q", "V-Y-F-P-C", "H-O-E-X-D", "I-Y-A-H-Q", "J-U-N-D-F", "O-V-N-P-Y", "X-R-O-C-J", "W-I-D-R-M", "Q-C-O-H-N", "L-Z-Y-W-T", "L-H-J-U-I", "X-M-E-R-U", "R-J-K-Z-E", "Q-A-I-P-R", "A-D-L-Q-M", "F-E-M-B-Z", "S-J-N-H-P", "I-Y-C-L-F", "W-Y-O-N-I", "S-E-N-B-H", "K-Z-E-U-V", "D-N-Y-Z-O", "Q-S-B-J-P", "J-N-V-T-B", "U-H-Q-L-S", "U-C-N-Q-L", "A-L-R-Q-F", "J-Y-K-P-L", "W-S-O-M-U", "L-P-S-U-T", "U-V-P-F-M", "C-J-W-Q-N", "A-V-C-P-L", "P-V-N-Y-E", "A-S-M-K-G", "T-U-I-W-H", "E-K-G-P-M", "Z-F-O-H-E", "C-G-I-X-R", "R-F-D-O-X", "C-R-F-M-Q", "H-F-M-N-W", "M-Y-F-I-X", "A-B-U-X-S", "C-F-G-R-D", "M-A-G-L-C", "W-L-Y-F-U", "U-M-C-R-H", "A-C-P-Y-K", "A-E-V-C-P", "M-C-A-J-B", "M-O-Z-G-A", "T-R-E-Y-M", "F-K-E-S-C", "F-Q-B-J-T", "R-Y-D-V-B", "J-M-C-R-W", "L-S-E-Z-R", "J-A-E-P-N", "Y-S-K-B-O", "S-Y-N-G-C", "B-Q-I-W-H", "W-T-U-J-Y", "O-J-W-G-C", "Q-B-G-I-F", "W-E-B-T-N", "M-A-U-R-G", "Q-R-O-X-P", "H-T-Y-N-P", "L-Q-A-G-X", "U-S-D-R-C", "I-J-F-R-Q", "K-T-G-C-E", "M-K-P-C-T", "W-Z-L-N-K", "B-O-G-U-P", "C-F-V-D-P", "G-A-P-R-X", "E-I-Y-K-F", "W-H-G-P-S", "G-J-W-M-B", "R-Y-B-F-L", "T-F-Y-Q-I", "R-L-O-C-F", "I-X-S-G-O", "F-R-M-A-X", "H-B-L-Z-A", "A-L-M-N-C", "F-D-Q-X-L", "Y-K-S-Q-D", "I-Z-B-O-D", "R-M-A-S-C", "J-S-U-H-T", "Q-B-A-P-Z", "I-D-X-Q-O", "F-H-S-W-Z", "P-V-K-R-G", "L-B-A-H-I", "I-P-T-O-Q", "N-F-K-Y-V", "T-U-M-A-G", "S-N-X-W-F", "I-V-Y-O-C", "M-T-Z-G-O", "R-V-B-J-I", "O-X-N-R-V", "W-N-M-F-J", "I-L-R-D-B", "E-G-F-V-Z", "A-P-S-L-Y", "U-A-X-G-O", "Y-D-B-O-M", "T-Q-K-M-D", "L-K-D-X-G", "V-Z-J-A-C", "T-N-I-W-H", "Z-C-S-R-E", "X-P-C-S-J", "O-A-F-C-R", "P-Z-X-W-E", "N-L-Q-W-Z", "M-J-W-D-T", "R-S-Q-G-O", "Z-C-Q-Y-S", "S-J-Y-R-V", "B-H-M-G-A", "Y-K-D-O-N", "Y-F-G-W-J", "I-G-T-C-V", "U-D-T-B-F", "N-Q-X-R-V", "F-O-N-L-V", "R-C-X-F-I", "C-G-H-U-X", "T-I-J-W-G", "U-B-G-O-Y", "G-C-H-Q-V", "S-U-D-A-H", "F-B-S-I-H", "X-R-S-O-B", "M-H-C-E-K", "Y-J-A-T-N", "Z-B-I-D-X", "R-I-U-E-B", "C-S-O-V-X", "S-Y-G-E-M", "N-O-D-H-Z", "U-D-V-T-S", "U-I-H-Q-M", "L-E-S-U-Y", "L-Q-Y-W-P", "J-K-U-C-V", "A-Z-R-S-N", "Z-F-A-Y-L", "C-L-G-R-I", "A-N-Q-C-Z", "A-X-P-R-Z", "W-N-I-M-X", "O-I-L-B-N", "P-U-Q-S-Y", "N-M-W-L-D", "D-V-X-C-R", "P-G-J-I-X", "Y-G-C-T-H", "R-S-V-N-X", "Y-H-O-Q-D", "Q-N-Y-Z-H", "D-Q-J-B-H", "N-X-O-Z-T", "R-Q-B-X-J", "V-S-U-E-K", "H-X-U-C-K", "W-X-E-I-P", "Z-H-J-N-L", "A-R-N-V-H", "R-W-L-O-N", "Q-Z-K-E-G", "M-X-L-W-F", "Z-R-L-K-J", "S-E-G-Y-N", "R-H-K-V-L", "A-V-Q-R-I", "Z-L-J-B-O", "W-S-R-C-V", "S-L-Q-M-R", "T-P-Y-A-K", "W-R-H-U-O", "Z-B-Q-P-J", "I-H-Q-Y-U", "W-K-U-I-S", "V-Y-N-M-W", "O-C-P-J-V", "M-S-Z-W-G", "T-M-E-X-F", "E-W-A-P-N", "Z-S-N-B-K", "G-D-X-R-V", "O-D-J-X-I", "F-V-G-U-L", "R-U-I-Z-M", "G-E-O-L-I", "K-T-B-F-X", "I-M-R-C-T", "B-Q-M-F-C", "E-J-F-W-B", "W-P-N-H-G", "E-F-G-O-J", "P-C-O-S-H", "C-L-A-N-W", "J-N-B-F-K", "S-X-A-E-Z", "G-B-F-T-P", "K-C-G-D-E", "T-I-O-G-U", "B-R-W-Q-Z", "L-C-R-G-N", "F-A-B-V-G", "R-E-Q-W-L", "L-Z-J-H-S", "E-R-L-D-N", "N-D-A-O-F", "V-O-A-C-L", "A-J-S-M-W", "K-B-V-T-O", "J-D-P-K-L", "J-Y-T-D-X", "Z-A-E-K-B", "L-D-R-Z-Q", "O-X-L-B-G", "B-P-V-O-K", "Y-J-D-T-E", "C-F-R-N-W", "U-Y-M-Q-E", "Y-O-V-X-H", "Z-K-D-V-Q", "A-Q-B-P-S", "W-S-O-Z-B", "W-D-U-F-S", "A-H-P-R-E", "W-N-V-J-K", "D-F-U-Y-S", "O-A-G-P-V", "V-J-R-E-P", "I-P-R-E-U", "F-T-C-O-G", "K-F-U-M-H", "V-N-F-X-U", "E-R-C-H-B", "D-U-C-V-X", "Q-Z-U-C-A", "B-G-I-O-T", "L-C-S-Z-M", "S-Y-A-W-P", "K-M-D-G-N", "O-I-D-R-Q", "D-P-J-Q-C", "T-N-I-B-L", "I-G-M-D-A", "O-D-C-L-Y", "B-D-Q-H-F", "H-M-W-P-X", "Z-Q-U-T-L", "K-F-I-O-R", "U-W-L-M-V", "M-A-N-D-Y", "M-E-X-I-K", "Y-S-F-L-V", "Q-Y-O-L-E", "T-K-G-A-O", "I-S-J-V-Q", "J-K-P-B-G", "D-P-F-I-T", "I-Q-B-J-M", "E-Q-H-V-W", "J-D-C-E-Q", "Q-U-V-D-J", "G-D-S-Z-T", "U-M-X-Z-C", "Q-R-Z-G-W", "R-C-L-Q-J", "E-I-O-V-W", "S-E-R-D-Q", "V-J-E-D-T", "K-A-D-N-T", "P-C-R-Z-X", "P-B-I-T-E", "H-W-Q-L-C", "C-J-K-E-G", "R-Y-D-P-Q", "R-X-U-L-K", "R-T-Q-G-Y", "X-H-J-T-D", "U-E-F-I-A", "L-K-O-C-M", "K-Y-H-M-J", "T-M-K-L-Y", "B-D-U-L-P", "D-G-N-F-H", "H-K-O-J-B", "L-A-C-X-D", "L-D-P-Q-J", "A-F-T-U-R", "M-W-H-Q-V", "T-F-J-S-G", "C-T-W-E-N", "K-U-F-A-D", "S-U-Q-T-P", "K-V-Y-B-T", "E-V-Y-O-S", "D-J-E-I-C", "Y-P-M-X-O", "Q-X-W-K-S", "G-W-O-B-C", "A-V-G-B-D", "I-L-V-D-K", "R-V-G-B-W", "Z-S-O-M-G", "B-A-C-X-W", "S-P-X-G-Q", "A-I-S-C-B", "Q-N-S-J-P", "E-T-W-J-B", "R-X-Y-T-E", "X-G-Z-V-S", "C-M-B-A-N", "N-L-W-B-I", "R-H-E-F-X", "E-U-I-Z-C", "N-F-E-Z-V", "T-S-O-J-F", "R-U-B-S-K", "R-A-S-K-G", "O-F-K-R-V", "N-X-J-A-M", "E-A-Z-T-X", "H-G-S-J-M", "H-E-A-J-U", "N-Z-M-Q-O", "B-M-R-E-S", "X-Y-Z-E-U", "W-I-H-R-J", "N-W-M-Y-Q", "I-N-O-T-P", "C-N-T-H-W", "O-C-M-H-L", "V-U-X-N-Q", "M-B-W-A-N", "H-Q-Z-B-L", "H-E-C-O-Y", "A-D-W-F-Y", "C-G-L-M-O", "A-D-U-O-C", "U-O-V-R-H", "Z-B-Y-G-L", "L-X-C-E-P", "L-P-K-M-R", "A-F-T-M-B", "E-Z-B-K-U", "D-F-E-A-Y", "J-A-R-M-O", "T-N-I-U-X", "F-Q-B-D-J", "N-J-M-R-Z", "Z-G-C-A-K", "U-G-V-X-H", "D-I-R-Z-W", "E-O-M-R-T", "L-G-S-F-M", "A-J-C-K-N", "Z-N-D-L-H", "X-Y-S-U-V", "B-Q-I-L-Y", "J-C-D-Z-E", "S-U-K-T-G", "P-W-T-X-U", "D-I-H-B-A", "Y-W-L-U-E", "F-O-A-S-V", "B-H-R-Z-J", "B-V-C-Y-L", "Z-C-J-F-H", "Z-Y-V-A-T", "R-F-D-E-Y", "J-O-L-A-M", "L-B-Z-F-P", "X-P-S-D-R", "O-E-B-R-S", "J-P-B-Q-X", "Q-E-Z-I-U", "Q-N-G-U-P", "W-O-L-I-T", "D-O-B-K-Z", "Z-E-A-V-J", "K-D-E-W-A", "Y-B-M-C-Z", "B-N-Y-J-O", "L-U-F-E-J", "B-V-X-O-F", "V-X-S-A-P", "L-B-Y-D-E", "E-U-D-V-T", "J-P-T-D-A", "Q-C-R-X-V", "I-D-L-A-O", "R-G-Q-V-K", "H-S-W-R-F", "C-E-F-Y-O", "S-P-B-Q-M", "B-J-Z-F-Q", "U-E-C-P-Z", "D-H-O-E-B", "G-J-L-R-S", "L-C-V-T-S", "R-V-W-K-I", "A-M-X-W-P", "W-B-K-A-C", "P-O-I-L-S", "A-K-T-B-Y", "K-B-X-R-T", "S-P-T-Q-W", "D-Z-U-W-B", "L-S-E-H-Q", "G-F-W-U-N", "J-T-E-Z-F", "V-X-N-T-B", "T-K-D-N-R", "L-K-Q-I-T", "N-E-X-D-Q", "Y-B-S-X-A", "S-D-W-J-Q", "U-H-J-W-I", "X-Z-A-J-B", "E-S-D-O-H", "G-O-Y-N-Q", "U-F-I-B-A", "M-H-W-C-O", "F-Z-C-B-M", "S-C-A-O-V", "G-R-H-Q-U", "V-N-J-Q-P", "V-P-Y-M-U", "R-J-O-Q-V", "G-C-U-E-I", "C-A-T-L-R", "O-N-S-G-H", "P-Z-K-U-V", "R-Z-H-D-N", "G-E-X-C-L", "Q-K-E-P-S", "N-K-I-H-A", "A-N-T-R-M", "T-R-G-E-F", "I-B-T-S-D", "G-R-J-L-W", "I-P-Y-K-L", "S-J-M-F-W", "U-H-D-P-T", "A-D-H-M-B", "S-T-Z-P-U", "N-I-G-R-S", "U-V-M-Q-S", "E-F-S-J-R", "F-H-O-S-Z", "O-G-R-E-Z", "B-M-A-N-T", "Z-H-D-L-Q", "Q-R-N-J-K", "C-X-H-Y-L", "I-X-W-G-E", "T-B-M-Q-S", "A-H-Z-V-B", "R-Z-M-X-G", "M-U-K-H-E", "G-B-L-A-W", "R-X-T-S-F", "D-W-Q-M-S", "P-B-F-Q-K", "R-H-I-J-V", "I-F-J-V-C", "U-T-K-R-F", "P-T-L-U-R", "I-L-P-N-F", "D-H-K-X-J", "A-Q-B-M-S", "B-V-L-Q-F", "C-H-K-V-A", "T-Y-C-P-U", "B-U-P-Q-H", "M-H-Q-E-I", "E-Z-S-U-K", "H-W-Q-R-M", "C-I-B-J-K", "E-I-O-S-H", "Y-I-E-X-L", "S-Q-O-L-N", "J-H-L-T-G", "H-M-Q-J-I", "V-I-Z-J-Q", "B-G-R-J-P", "Z-I-W-B-O", "R-V-B-G-N", "B-I-N-J-R", "F-T-W-M-L", "F-S-K-I-J", "S-N-V-G-Z", "X-I-G-L-H", "K-B-X-V-A", "F-M-A-H-N", "Y-Z-I-W-A", "P-M-R-C-Z", "N-U-B-R-A", "wordZ2", "Var1", "Var2", "Var3", "Var4", "a", "b", "c", "e", "f", "h", "i", "Var5", "Var6", "Var7", "col 1", "col 2", "g", "x" ), uniqueCount = "2114") } #' provides testfile path for testthat #' @param x a file assumed in testfiles folder testfile_path <- function(x, replace = FALSE) { test_path <- testthat::test_path("testfiles") if (!dir.exists(test_path)) { dir.create(test_path) } fl <- testthat::test_path("testfiles", x) if (Sys.getenv("openxlsx2_testthat_fullrun") == "") { if (isTRUE(as.logical(Sys.getenv("CI", "false")))) # on_ci() return(testthat::skip("Skip on CI")) if (!interactive() && !isTRUE(as.logical(Sys.getenv("NOT_CRAN", "false")))) # on_cran() return(testthat::skip("Skip on CRAN")) } # try to download if (!file.exists(fl) || replace) { out <- paste0(test_path, "/", x) url <- paste0("https://github.com/JanMarvin/openxlsx-data/raw/main/", x) try({ download.file(url, destfile = out, quiet = TRUE, mode = "wb") }) } if (!file.exists(fl)) { return(testthat::skip("Testfile does not exist")) } fl } testsetup <- function() { if (is.null(getOption("openxlsx2.datetimeCreated"))) { testthat::test_that("testsetup", { options("openxlsx2.datetimeCreated" = as.POSIXct("2023-07-20 23:32:14", tz = "UTC")) wb <- wb_workbook() exp <- "2023-07-20T23:32:14Z" got <- wb$get_properties()[["datetime_created"]] testthat::expect_equal(exp, got) }) } } dns_lookup <- function(host = "captive.apple.com") { con <- try( socketConnection(host, port = 80, open = "r+", timeout = 2), silent = TRUE ) on.exit(close(con)) if (inherits(con, "try-error")) return(FALSE) TRUE } # testthat::skip_if_offline requires curl, but fails if curl is not available skip_online_checks <- function() { testthat::skip_on_cran() testthat::skip_if_not(dns_lookup()) }