Skip to content

Commit

Permalink
Merge pull request #686 from molgenis/refactor/tests
Browse files Browse the repository at this point in the history
refactor: restructure release test script
  • Loading branch information
timcadman authored Mar 19, 2024
2 parents 3a7279a + 2a82d86 commit fe0e6a5
Show file tree
Hide file tree
Showing 31 changed files with 1,422 additions and 1,158 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ dist
### STORAGE ###
data/user-*
data/system

# Ignore all projects but life-cycle
data/shared-*
!data/shared-lifecycle
data/testing

HELP.md
target/
Expand All @@ -36,6 +38,7 @@ target/
*.iml
*.ipr


### NetBeans ###
/nbproject/private/
/nbbuild/
Expand All @@ -55,3 +58,6 @@ build/
/application.yaml
/application.properties
.Rproj.user

# R files
.Rhistory
1 change: 1 addition & 0 deletions docker/bin/prepare.bash
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ mkdir -p "$LOG_DIR" || exit 1

cp "$PROJECT_DIR/scripts/release/release-test.R" "$BIN_DIR/" || exit 1
cp -r "$PROJECT_DIR/scripts/release/test-cases" "$BIN_DIR/" || exit 1
cp -r "$PROJECT_DIR/scripts/release/lib" "$BIN_DIR/" || exit 1
cp "$PROJECT_DIR/scripts/release/install_release_script_dependencies.R" "$BIN_DIR/" || exit 1
cp "$TARGET_DIR/armadillo-ready.bash" "$BIN_DIR/" || exit 1
cp "$TARGET_DIR/ci.env" "$BIN_DIR/.env" || exit 1
Expand Down
3 changes: 3 additions & 0 deletions scripts/release/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.env
Rplots.pdf
molgenis-service-armadillo.Rproj
3 changes: 3 additions & 0 deletions scripts/release/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ To prevent all the questions:
- copy the `dev.dist.env` to `.env`
- fill in some or all parts
- toggle the `interactive` to `n` or `y` to let the script wait for manual checks.
- Specify tests you want to skip by adding them to the SKIP_TESTS in the .env file.
Specify the name of the R script to skip without the .R extension, separated by
commas with no spaces. Eg: SKIP_TESTS = upload-resource,xenon-mediate

### CICD
- Note CICD only runs test as admin as we cannot connect to an OIDC account.
Expand Down
4 changes: 4 additions & 0 deletions scripts/release/dev.env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ OIDC_EMAIL=

# The token will invalidate probably in 1 hour so replace it or set to empty
TOKEN=

# Specify tests you don't want to run. If not specified all tests will run. Character vectors separated by commas with
# no space, e.g SKIP_TESTS = upload-resource,xenon-mediate
SKIP_TESTS =
17 changes: 10 additions & 7 deletions scripts/release/install_release_script_dependencies.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,34 @@ cat("
")
cat("Installing dependencies for release test\n")
if(!"cli" %in% installed.packages()) {
if (!"cli" %in% installed.packages()) {
install.packages("cli", repos = "http://cran.us.r-project.org")
}
library(cli)
cli_alert_info("Installing packages")

packages <- c("diffobj", "getPass", "arrow", "jsonlite", "future",
packages <- c(
"diffobj", "getPass", "arrow", "jsonlite", "future",
"RCurl",
"devtools",
"DSI",
"resourcer",
"MolgenisArmadillo",
"DSMolgenisArmadillo"
"DSMolgenisArmadillo",
"purrr",
"stringr"
)

install_requirements_from_cran <- function(packages) {
n_requirements <- length(packages)
cli_progress_bar("Installing packages", total = n_requirements)
for (i in 1:n_requirements) {
pkg <- packages[i]
if (pkg %in% installed.packages()){
if (pkg %in% installed.packages()) {
cli_alert_info(sprintf("Package [%s] already installed, skipping.", pkg))
} else{
} else {
cli_alert_info(paste0("Installing ", pkg))
install.packages(pkg, repos = "http://cran.us.r-project.org", quiet=TRUE)
install.packages(pkg, repos = "http://cran.us.r-project.org", quiet = TRUE)
}
cli_progress_update()
}
Expand All @@ -59,5 +62,5 @@ install_github("datashield/dsMediationClient", ref = "0.0.3")
install_github("https://github.com/transbioZI/dsMTLClient", ref = "0.9.9")
install_github("neelsoumya/dsSurvivalClient") # There is no version for this package

#check if all packages are installed
# check if all packages are installed
cli_alert_success("All packages are installed")
204 changes: 204 additions & 0 deletions scripts/release/lib/common-functions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
add_slash_if_not_added <- function(path) {
if (!endsWith(path, "/")) {
return(paste0(path, "/"))
} else {
return(path)
}
}

remove_slash_if_added <- function(path) {
if (endsWith(path, "/")) {
return(gsub("/$", "", path))
} else {
return(path)
}
}

exit_test <- function(msg) {
cli_alert_danger(msg)
cond <- structure(list(message = msg), class = c("exit", "condition"))
signalCondition(cond)
stop(cond)
}

check_cohort_exists <- function(cohort) {
if (cohort %in% armadillo.list_projects()) {
cli_alert_success(paste0(cohort, " exists"))
} else {
exit_test(paste0(cohort, " doesn't exist!"))
}
}

wait_for_input <- function(interactive) {
if (interactive) {
cat("\nPress any key to continue")
continue <- readLines("stdin", n = 1)
} else {
cat("\n\n")
}
}

create_basic_header <- function(pwd) {
encoded <- base64enc::base64encode(
charToRaw(
paste0("admin:", pwd)
)
)
return(paste0("Basic ", encoded))
}

# # add/edit user using armadillo api
set_user <- function(user, admin_pwd, isAdmin, required_projects, url) {
args <- list(email = user, admin = isAdmin, projects = required_projects)
response <- put_to_api("access/users", admin_pwd, "basic", args, url)
if (response$status_code != 204) {
cli_alert_warning("Altering OIDC user failed, please do this manually")
update_auto <- ""
}
}

# # armadillo api put request
put_to_api <- function(endpoint, key, auth_type, body_args, url) {
auth_header <- get_auth_header(auth_type, key)
body <- jsonlite::toJSON(body_args, auto_unbox = TRUE)
response <- PUT(paste0(url, endpoint),
body = body, encode = "json",
config = c(httr::content_type_json(), httr::add_headers(auth_header))
)
return(response)
}

do_skip_test <- function(test_name, skip_tests) {
if (any(skip_tests %in% test_name)) {
cli_alert_info(sprintf("Test '%s' skipped", test_name))
return(TRUE)
}
return(FALSE)
}

read_parquet_with_message <- function(file_path, dest) {
cli_alert_info(file_path)
out <- arrow::read_parquet(paste0(dest, paste0(file_path, ".parquet")))
cli_alert_success(paste0(file_path, " read"))
return(out)
}

run_spinner <- function(spinner) {
lapply(1:1000, function(x) {
spinner$spin()
spin_till_done(spinner)
})
}

# # compare values in two lists
compare_list_values <- function(list1, list2) {
vals_to_print <- cli_ul()
equal <- TRUE
for (i in 1:length(list1)) {
val1 <- list1[i]
val2 <- list2[i]
if (almost_equal(val1, val2) == TRUE) {
cli_li(sprintf("%s ~= %s", val1, val2))
} else {
equal <- FALSE
cli_li(sprintf("%s != %s", val1, val2))
}
}
cli_end(vals_to_print)
if (equal) {
cli_alert_success("Values equal")
} else {
cli_alert_danger("Values not equal")
}
}

# theres a bit of noise added in DataSHIELD answers, causing calculations to not always be exactly the same, but close
# here we check if they're equal enough
almost_equal <- function(val1, val2) {
return(all.equal(val1, val2, tolerance = .Machine$double.eps^0.03))
}

generate_random_project_name <- function(skip_tests) {
test_name <- "generate-project"
if (do_skip_test(test_name, skip_tests)) {
return()
}

current_projects <- armadillo.list_projects()
random_project <- stri_rand_strings(1, 10, "[a-z0-9]")
if (!random_project %in% current_projects) {
cli_alert_success(sprintf("Project %s created", random_project))
cli_alert_success(sprintf("%s passed!", test_name))
return(random_project)
} else {
generate_random_project_name(current_projects)
}
}

# # armadillo api put request
put_to_api <- function(endpoint, key, auth_type, body_args, url) {
auth_header <- get_auth_header(auth_type, key)
body <- jsonlite::toJSON(body_args, auto_unbox = TRUE)
response <- PUT(paste0(url, endpoint),
body = body, encode = "json",
config = c(httr::content_type_json(), httr::add_headers(auth_header))
)
return(response)
}

get_from_api <- function(endpoint, armadillo_url) {
cli_alert_info(sprintf("Retrieving [%s%s]", armadillo_url, endpoint))
response <- GET(paste0(armadillo_url, endpoint))
cat(paste0("get_from_api", " for ", endpoint, " results ", response$status_code, "\n"))
return(content(response))
}

get_auth_type <- function(ADMIN_MODE) {
if (ADMIN_MODE) {
auth_type <- "basic"
} else {
auth_type <- "bearer"
}
}

# get request to armadillo api with an authheader
get_from_api_with_header <- function(endpoint, key, auth_type, url, user) {
auth_header <- get_auth_header(auth_type, key)
response <- GET(paste0(url, endpoint), config = c(httr::add_headers(auth_header)))
if (response$status_code == 403) {
msg <- sprintf("Permission denied. Is user [%s] admin?", user)
exit_test(msg)
} else if (response$status_code != 200) {
cli_alert_danger(sprintf("Cannot retrieve data from endpoint [%s]", endpoint))
exit_test(content(response)$message)
}
return(content(response))
}


# make authentication header for api calls, basic or bearer based on type
get_auth_header <- function(type, key) {
header_content <- ""
if (tolower(type) == "bearer") {
header_content <- create_bearer_header(key)
} else if (tolower(type) == "basic") {
header_content <- create_basic_header(key)
} else {
exit_test(sprintf("Type [%s] invalid, choose from 'basic' and 'bearer'"))
}
return(c("Authorization" = header_content))
}

create_bearer_header <- function(token) {
return(paste0("Bearer ", token))
}


print_list <- function(list) {
vals_to_print <- cli_ul()
for (i in 1:length(list)) {
val <- list[i]
cli_li(val)
}
cli_end(vals_to_print)
}
22 changes: 22 additions & 0 deletions scripts/release/lib/release-test-info.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
show_test_info <- function(version, url, user, admin_pwd, dest, profile, ADMIN_MODE, skip_tests) {
test_name <- "show_test_info"
if (do_skip_test(test_name, skip_tests)) {
return()
}

if (admin_pwd != "") {
admin_pwd_msg <- TRUE
}

test_message <- cat(sprintf("
,.-----__ Testing version: %s
,:::://///,:::-. Test server: %s
/:''/////// ``:::`;/|/ OIDC User: %s
/' |||||| :://'`\\ Admin password set: %s
.' , |||||| `/( e \\ Directory for test files: %s
-===~__-'\\__X_`````\\_____/~`-._ `. Profile: %s
~~ ~~ `~-' Admin-only mode: %s
", version, url, user, admin_pwd_msg, dest, profile, ADMIN_MODE))

return(test_message)
}
Loading

0 comments on commit fe0e6a5

Please sign in to comment.