diff --git a/.Rbuildignore b/.Rbuildignore index a82962f..6bcb713 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -5,7 +5,8 @@ ^LICENSE\.md$ ^docker-compose.yml$ ^input_dir/ -^output_dir/ +^analysis_output_dir/ +^pacta-data/ ^portfolios/ ^run-pacta.sh$ ^workflow.pacta.Rproj$ diff --git a/.lintr b/.lintr new file mode 100644 index 0000000..f81a71a --- /dev/null +++ b/.lintr @@ -0,0 +1,6 @@ +linters: all_linters() +exclusions: list( + "tests/testthat.R", + "inst/extdata/scripts/run_pacta.R" + ) + diff --git a/DESCRIPTION b/DESCRIPTION index 83781d9..902efa1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: workflow.pacta Title: Run PACTA -Version: 0.0.0.9005 +Version: 0.0.0.9006 Authors@R: c(person(given = "CJ", family = "Yetman", @@ -40,4 +40,8 @@ Remotes: RMI-PACTA/pacta.portfolio.audit, RMI-PACTA/pacta.portfolio.import, RMI-PACTA/pacta.portfolio.utils, - RMI-PACTA/pacta.workflow.utils + RMI-PACTA/pacta.workflow.utils@develop +Suggests: + testthat (>= 3.0.0), + withr +Config/testthat/edition: 3 diff --git a/R/calc_weights_and_outputs.R b/R/calc_weights_and_outputs.R index a3b6305..93a5b40 100644 --- a/R/calc_weights_and_outputs.R +++ b/R/calc_weights_and_outputs.R @@ -10,6 +10,13 @@ calc_weights_and_outputs <- function( start_year, time_horizon ) { + log_debug("Checking IO for calc_weights_and_outputs.") + calc_weights_prechecks( + total_portfolio = total_portfolio, + portfolio_type = portfolio_type, + output_dir = output_dir, + data_dir = data_dir + ) log_info("Starting {portfolio_type} calculations.") @@ -178,3 +185,44 @@ calc_weights_and_outputs <- function( } } + +calc_weights_prechecks <- function( + total_portfolio, + portfolio_type, + output_dir, + data_dir +) { + if (is.null(total_portfolio)) { + log_warn("Portfolio is NULL.") + } else if (nrow(total_portfolio) == 0L) { + log_error("Portfolio has no rows.") + stop("Portfolio has no rows.") + } + if (portfolio_type == "Equity") { + input_files <- c( + # merge_abcd_from_db + file.path(data_dir, "equity_abcd_scenario.rds"), + # get_abcd_raw + file.path(data_dir, "masterdata_ownership_datastore.rds") + ) + } else if (portfolio_type == "Bonds") { + input_files <- c( + # merge_abcd_from_db + file.path(data_dir, "bonds_abcd_scenario.rds"), + # get_abcd_raw + file.path(data_dir, "masterdata_debt_datastore.rds") + ) + } else { + stop("Invalid portfolio type.") + } + pacta.workflow.utils::check_io( + input_files = input_files, + output_dir = output_dir + ) + return( + list( + input_files = input_files, + output_dir = output_dir + ) + ) +} diff --git a/R/run_analysis.R b/R/run_analysis.R index 24ffa14..c30e369 100644 --- a/R/run_analysis.R +++ b/R/run_analysis.R @@ -20,16 +20,12 @@ run_analysis <- function( # quit if there's no relevant PACTA assets -------------------------------- total_portfolio_path <- file.path(output_dir, "total_portfolio.rds") - if (file.exists(total_portfolio_path)) { - total_portfolio <- readRDS(total_portfolio_path) - log_trace( - "Checking for PACTA relevant data in file: \"{total_portfolio_path}\"." - ) - pacta.portfolio.utils::quit_if_no_pacta_relevant_data(total_portfolio) - } else { - log_warn("file \"{total_portfolio_path}\" does not exist.") - warning("File \"total_portfolio.rds\" file does not exist.") - } + analysis_prechecks( + total_portfolio_path = total_portfolio_path, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + total_portfolio <- readRDS(total_portfolio_path) calc_weights_and_outputs( @@ -60,3 +56,35 @@ run_analysis <- function( log_info("Finished PACTA calculations.") } + +analysis_prechecks <- function( + total_portfolio_path, + pacta_data_dir, + output_dir +) { + pacta.workflow.utils::check_io( + input_files = total_portfolio_path, + output_dir = output_dir + ) + if (is.null(total_portfolio_path)) { + total_portfolio <- NULL + } else { + total_portfolio <- readRDS(total_portfolio_path) + log_trace( + "Checking for PACTA relevant data in file: \"{total_portfolio_path}\"." + ) + pacta.portfolio.utils::quit_if_no_pacta_relevant_data(total_portfolio) + } + calc_weights_prechecks( + total_portfolio = total_portfolio, + portfolio_type = "Equity", + output_dir = output_dir, + data_dir = pacta_data_dir + ) + calc_weights_prechecks( + total_portfolio = total_portfolio, + portfolio_type = "Bonds", + output_dir = output_dir, + data_dir = pacta_data_dir + ) +} diff --git a/R/run_audit.R b/R/run_audit.R index 7e4eac6..df908f7 100644 --- a/R/run_audit.R +++ b/R/run_audit.R @@ -4,6 +4,13 @@ run_audit <- function( portfolio_files, output_dir ) { + # Prechecks ---------------------------------------------------------------- + audit_io_files <- audit_prechecks( + pacta_data_dir = pacta_data_dir, + portfolio_dir = portfolio_dir, + portfolio_files = portfolio_files, + output_dir = output_dir + ) log_info("Starting portfolio audit") @@ -139,4 +146,35 @@ run_audit <- function( saveRDS(emissions_totals, file.path(output_dir, "emissions.rds")) log_info("Portfolio audit finished.") + return(audit_io_files) +} + +audit_prechecks <- function( + pacta_data_dir, + portfolio_dir, + portfolio_files, + output_dir +) { + input_files <- c( + file.path(pacta_data_dir, "currencies.rds"), + file.path(pacta_data_dir, "fund_data.rds"), + file.path(pacta_data_dir, "total_fund_list.rds"), + file.path(pacta_data_dir, "isin_to_fund_table.rds"), + file.path(pacta_data_dir, "financial_data.rds"), + file.path(pacta_data_dir, "abcd_flags_equity.rds"), + file.path(pacta_data_dir, "abcd_flags_bonds.rds"), + file.path(pacta_data_dir, "iss_entity_emission_intensities.rds"), + file.path(pacta_data_dir, "iss_average_sector_emission_intensities.rds"), + file.path(portfolio_dir, portfolio_files) + ) + pacta.workflow.utils::check_io( + input_files = input_files, + output_dir = output_dir + ) + return( + list( + input_files = input_files, + output_dir = output_dir + ) + ) } diff --git a/R/run_pacta.R b/R/run_pacta.R index 56c17d9..ba1f80c 100644 --- a/R/run_pacta.R +++ b/R/run_pacta.R @@ -47,7 +47,7 @@ run_pacta <- function( stop("Invalid raw input parameters.") } - params <- pacta.workflow.utils:::parse_params( + params <- pacta.workflow.utils:::parse_params( #nolint json = raw_params, inheritence_search_paths = system.file( "extdata", "parameters", @@ -59,6 +59,18 @@ run_pacta <- function( ) ) + audit_prechecks( + portfolio_files = params[["portfolio"]][["files"]], + pacta_data_dir = pacta_data_dir, + portfolio_dir = portfolio_dir, + output_dir = output_dir + ) + analysis_prechecks( + total_portfolio_path = NULL, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + run_audit( portfolio_files = params[["portfolio"]][["files"]], pacta_data_dir = pacta_data_dir, diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..ad7799e --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,12 @@ +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html + +library(testthat) +library(workflow.pacta) + +test_check("workflow.pacta") diff --git a/tests/testthat/test-analysis_prechecks.R b/tests/testthat/test-analysis_prechecks.R new file mode 100644 index 0000000..a1f8f9d --- /dev/null +++ b/tests/testthat/test-analysis_prechecks.R @@ -0,0 +1,226 @@ +## save current settings so that we can reset later +threshold <- logger::log_threshold() +appender <- logger::log_appender() +layout <- logger::log_layout() +on.exit({ + ## reset logger settings + logger::log_threshold(threshold) + logger::log_layout(layout) + logger::log_appender(appender) +}) + +logger::log_appender(logger::appender_stdout) +logger::log_threshold(logger::FATAL) +logger::log_layout(logger::layout_simple) + +test_that("audit_prechecks works when all files are present", { + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + output_dir <- withr::local_tempdir() + portfolio <- data.frame( + asset_type = "Equity", + has_asset_level_data = TRUE, + stringsAsFactors = FALSE + ) + total_portfolio_path <- file.path(output_dir, "total_portfolio.rds") + saveRDS( + object = portfolio, + file = total_portfolio_path + ) + + expect_no_error( + analysis_prechecks( + total_portfolio_path = total_portfolio_path, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + ) +}) + +test_that("audit_prechecks fails when total_portfolio.rds missing", { + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + output_dir <- withr::local_tempdir() + portfolio <- data.frame( + asset_type = "Equity", + has_asset_level_data = TRUE, + stringsAsFactors = FALSE + ) + total_portfolio_path <- file.path(output_dir, "total_portfolio.rds") + + expect_error( + # suppressWarnings is used to avoid printing the warning from check_io + suppressWarnings( + analysis_prechecks( + total_portfolio_path = total_portfolio_path, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + ), + regexp = "^IO checks failed.$" + ) +}) +test_that("analysis_prechecks passes when port missing, but path is NULL", { + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + output_dir <- withr::local_tempdir() + portfolio <- data.frame( + asset_type = "Equity", + has_asset_level_data = TRUE, + stringsAsFactors = FALSE + ) + total_portfolio_path <- file.path(output_dir, "total_portfolio.rds") + + results <- analysis_prechecks( + total_portfolio_path = NULL, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + expect_identical( + object = results, + expected = list( + input_files = c( + file.path(pacta_data_dir, "bonds_abcd_scenario.rds"), + file.path(pacta_data_dir, "masterdata_debt_datastore.rds") + ), + output_dir = output_dir + ) + ) + +}) + +test_that("audit_prechecks fails when output_dir not writable", { + skip_on_os("windows") + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + output_dir <- withr::local_tempdir() + portfolio <- data.frame( + asset_type = "Equity", + has_asset_level_data = TRUE, + stringsAsFactors = FALSE + ) + total_portfolio_path <- file.path(output_dir, "total_portfolio.rds") + Sys.chmod(output_dir, mode = "000") + + expect_error( + # suppressWarnings is used to avoid printing the warning from check_io + suppressWarnings( + analysis_prechecks( + total_portfolio_path = total_portfolio_path, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + ), + regexp = "^IO checks failed.$" + ) +}) + +test_that("audit_prechecks fails when data files missing", { + skip_on_os("windows") + pacta_data_dir <- withr::local_tempdir() + + output_dir <- withr::local_tempdir() + portfolio <- data.frame( + asset_type = "Equity", + has_asset_level_data = TRUE, + stringsAsFactors = FALSE + ) + total_portfolio_path <- file.path(output_dir, "total_portfolio.rds") + + expect_error( + # suppressWarnings is used to avoid printing the warning from check_io + suppressWarnings( + analysis_prechecks( + total_portfolio_path = total_portfolio_path, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + ), + regexp = "^IO checks failed.$" + ) +}) + +test_that("audit_prechecks fails when no pacta-relevant data", { + skip_on_os("windows") + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + output_dir <- withr::local_tempdir() + portfolio <- data.frame( + asset_type = "Equity", + has_asset_level_data = FALSE, + stringsAsFactors = FALSE + ) + total_portfolio_path <- file.path(output_dir, "total_portfolio.rds") + + expect_error( + # suppressWarnings is used to avoid printing the warning from check_io + suppressWarnings( + analysis_prechecks( + total_portfolio_path = total_portfolio_path, + pacta_data_dir = pacta_data_dir, + output_dir = output_dir + ) + ), + regexp = "^IO checks failed.$" + ) +}) diff --git a/tests/testthat/test-audit_prechecks.R b/tests/testthat/test-audit_prechecks.R new file mode 100644 index 0000000..500b43e --- /dev/null +++ b/tests/testthat/test-audit_prechecks.R @@ -0,0 +1,200 @@ +## save current settings so that we can reset later +threshold <- logger::log_threshold() +appender <- logger::log_appender() +layout <- logger::log_layout() +on.exit({ + ## reset logger settings + logger::log_threshold(threshold) + logger::log_layout(layout) + logger::log_appender(appender) +}) + +logger::log_appender(logger::appender_stdout) +logger::log_threshold(logger::FATAL) +logger::log_layout(logger::layout_simple) + +test_that("audit_prechecks works when all files are present", { + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "currencies.rds", + "fund_data.rds", + "total_fund_list.rds", + "isin_to_fund_table.rds", + "financial_data.rds", + "abcd_flags_equity.rds", + "abcd_flags_bonds.rds", + "iss_entity_emission_intensities.rds", + "iss_average_sector_emission_intensities.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + portfolio_dir <- withr::local_tempdir() + portfolio_files <- "portfolio1.csv" + write.csv( + data.frame(a = 1L, b = 2L), + file.path(portfolio_dir, portfolio_files) + ) + + output_dir <- withr::local_tempdir() + + results <- audit_prechecks( + pacta_data_dir = pacta_data_dir, + portfolio_dir = portfolio_dir, + portfolio_files = portfolio_files, + output_dir = output_dir + ) + expect_identical( + object = results, + expected = list( + input_files = c( + file.path(pacta_data_dir, "currencies.rds"), + file.path(pacta_data_dir, "fund_data.rds"), + file.path(pacta_data_dir, "total_fund_list.rds"), + file.path(pacta_data_dir, "isin_to_fund_table.rds"), + file.path(pacta_data_dir, "financial_data.rds"), + file.path(pacta_data_dir, "abcd_flags_equity.rds"), + file.path(pacta_data_dir, "abcd_flags_bonds.rds"), + file.path(pacta_data_dir, "iss_entity_emission_intensities.rds"), + file.path( + pacta_data_dir, "iss_average_sector_emission_intensities.rds" + ), + file.path(portfolio_dir, portfolio_files) + ), + output_dir = output_dir + ) + ) +}) + +test_that("audit_prechecks fails when output_dir not writable", { + skip_on_os("windows") + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "currencies.rds", + "fund_data.rds", + "total_fund_list.rds", + "isin_to_fund_table.rds", + "financial_data.rds", + "abcd_flags_equity.rds", + "abcd_flags_bonds.rds", + "iss_entity_emission_intensities.rds", + "iss_average_sector_emission_intensities.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + portfolio_dir <- withr::local_tempdir() + portfolio_files <- "portfolio1.csv" + write.csv( + data.frame(a = 1L, b = 2L), + file.path(portfolio_dir, portfolio_files) + ) + + output_dir <- withr::local_tempdir() + Sys.chmod(output_dir, mode = "000") + + expect_error( + audit_prechecks( + pacta_data_dir = pacta_data_dir, + portfolio_dir = portfolio_dir, + portfolio_files = portfolio_files, + output_dir = output_dir + ), + regexp = "^IO checks failed.$" + ) +}) + +test_that("audit_prechecks fails when missing pacta-data files", { + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "currencies.rds", + "fund_data.rds", + "total_fund_list.rds", + "isin_to_fund_table.rds", + "financial_data.rds", + "abcd_flags_equity.rds", + "abcd_flags_bonds.rds", + "iss_entity_emission_intensities.rds", + "iss_average_sector_emission_intensities.rds" + ) + filenames <- sample(x = filenames, size = 8L, replace = FALSE) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + portfolio_dir <- withr::local_tempdir() + portfolio_files <- "portfolio1.csv" + write.csv( + data.frame(a = 1L, b = 2L), + file.path(portfolio_dir, portfolio_files) + ) + + output_dir <- withr::local_tempdir() + + expect_error( + # supress warnings form pacta.workflow.utils + suppressWarnings( + audit_prechecks( + pacta_data_dir = pacta_data_dir, + portfolio_dir = portfolio_dir, + portfolio_files = portfolio_files, + output_dir = output_dir + ) + ), + regexp = "^IO checks failed.$" + ) +}) + +test_that("audit_prechecks fails when missing portfolio files", { + pacta_data_dir <- withr::local_tempdir() + filenames <- c( + "currencies.rds", + "fund_data.rds", + "total_fund_list.rds", + "isin_to_fund_table.rds", + "financial_data.rds", + "abcd_flags_equity.rds", + "abcd_flags_bonds.rds", + "iss_entity_emission_intensities.rds", + "iss_average_sector_emission_intensities.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(pacta_data_dir, filename) + ) + } + + portfolio_dir <- withr::local_tempdir() + portfolio_files <- c("portfolio1.csv", "portfolio2.csv") + write.csv( + data.frame(a = 1L, b = 2L), + file.path(portfolio_dir, portfolio_files[[1L]]) + ) + + output_dir <- withr::local_tempdir() + + expect_error( + # supress warnings form pacta.workflow.utils + suppressWarnings( + audit_prechecks( + pacta_data_dir = pacta_data_dir, + portfolio_dir = portfolio_dir, + portfolio_files = portfolio_files, + output_dir = output_dir + ) + ), + regexp = "^IO checks failed.$" + ) +}) diff --git a/tests/testthat/test-calc_weights_prechecks.R b/tests/testthat/test-calc_weights_prechecks.R new file mode 100644 index 0000000..1e3ba9e --- /dev/null +++ b/tests/testthat/test-calc_weights_prechecks.R @@ -0,0 +1,230 @@ +## save current settings so that we can reset later +threshold <- logger::log_threshold() +appender <- logger::log_appender() +layout <- logger::log_layout() +on.exit({ + ## reset logger settings + logger::log_threshold(threshold) + logger::log_layout(layout) + logger::log_appender(appender) +}) + +logger::log_appender(logger::appender_stdout) +logger::log_threshold(logger::FATAL) +logger::log_layout(logger::layout_simple) + +test_that("audit_prechecks works when all files are present", { + data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(data_dir, filename) + ) + } + + portfolio <- data.frame(a = 1L, b = 2L) + + output_dir <- withr::local_tempdir() + + results_eq <- calc_weights_prechecks( + total_portfolio = portfolio, + portfolio_type = "Equity", + output_dir = output_dir, + data_dir = data_dir + ) + expect_identical( + object = results_eq, + expected = list( + input_files = c( + file.path(data_dir, "equity_abcd_scenario.rds"), + file.path(data_dir, "masterdata_ownership_datastore.rds") + ), + output_dir = output_dir + ) + ) + results_cb <- calc_weights_prechecks( + total_portfolio = portfolio, + portfolio_type = "Bonds", + output_dir = output_dir, + data_dir = data_dir + ) + expect_identical( + object = results_cb, + expected = list( + input_files = c( + file.path(data_dir, "bonds_abcd_scenario.rds"), + file.path(data_dir, "masterdata_debt_datastore.rds") + ), + output_dir = output_dir + ) + ) +}) + +test_that("audit_prechecks works for EQ when EQ files are present", { + data_dir <- withr::local_tempdir() + filenames <- c( + "equity_abcd_scenario.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(data_dir, filename) + ) + } + + portfolio <- data.frame(a = 1L, b = 2L) + + output_dir <- withr::local_tempdir() + + results_eq <- calc_weights_prechecks( + total_portfolio = portfolio, + portfolio_type = "Equity", + output_dir = output_dir, + data_dir = data_dir + ) + expect_identical( + object = results_eq, + expected = list( + input_files = c( + file.path(data_dir, "equity_abcd_scenario.rds"), + file.path(data_dir, "masterdata_ownership_datastore.rds") + ), + output_dir = output_dir + ) + ) +}) + +test_that("audit_prechecks works for CB when CB files are present", { + data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "masterdata_debt_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(data_dir, filename) + ) + } + + portfolio <- data.frame(a = 1L, b = 2L) + + output_dir <- withr::local_tempdir() + + results_cb <- calc_weights_prechecks( + total_portfolio = portfolio, + portfolio_type = "Bonds", + output_dir = output_dir, + data_dir = data_dir + ) + expect_identical( + object = results_cb, + expected = list( + input_files = c( + file.path(data_dir, "bonds_abcd_scenario.rds"), + file.path(data_dir, "masterdata_debt_datastore.rds") + ), + output_dir = output_dir + ) + ) +}) + +test_that("audit_prechecks throws error when output_dir not writable", { + skip_on_os("windows") + data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(data_dir, filename) + ) + } + + portfolio <- data.frame(a = 1L, b = 2L) + + output_dir <- withr::local_tempdir() + Sys.chmod(output_dir, mode = "000") + + for (type in c("Equity", "Bonds")) { + expect_error( + calc_weights_prechecks( + total_portfolio = portfolio, + portfolio_type = type, + output_dir = output_dir, + data_dir = data_dir + ), + regexp = "^IO checks failed.$" + ) + } +}) + +test_that("audit_prechecks throws error when data files missing", { + skip_on_os("windows") + data_dir <- withr::local_tempdir() + + portfolio <- data.frame(a = 1L, b = 2L) + + output_dir <- withr::local_tempdir() + + for (type in c("Equity", "Bonds")) { + expect_error( + # suppressWarnings to avoid warning about missing files + suppressWarnings( + calc_weights_prechecks( + total_portfolio = portfolio, + portfolio_type = type, + output_dir = output_dir, + data_dir = data_dir + ) + ), + regexp = "^IO checks failed.$" + ) + } +}) + +test_that("audit_prechecks errors on empty portfolio", { + data_dir <- withr::local_tempdir() + filenames <- c( + "bonds_abcd_scenario.rds", + "equity_abcd_scenario.rds", + "masterdata_debt_datastore.rds", + "masterdata_ownership_datastore.rds" + ) + for (filename in filenames) { + saveRDS( + 1L, + file.path(data_dir, filename) + ) + } + + portfolio <- data.frame() + + output_dir <- withr::local_tempdir() + + for (type in c("Equity", "Bonds")) { + expect_error( + # suppressWarnings to avoid warning about missing files + suppressWarnings( + calc_weights_prechecks( + total_portfolio = portfolio, + portfolio_type = type, + output_dir = output_dir, + data_dir = data_dir + ) + ), + regexp = "^Portfolio has no rows.$" + ) + } +})