diff --git a/R/branch_metrics.R b/R/branch_metrics.R index b9a319d4..e3fca007 100644 --- a/R/branch_metrics.R +++ b/R/branch_metrics.R @@ -56,7 +56,7 @@ time_branch <- function(test_path, branch = "master", num_commits = 5) { # Git operations target <- git2r::repository("./") - origin_state <- git2r::head(target) + origin_state <- git2r::repository_head(target) git2r::checkout(target, branch) on.exit(expr = git2r::checkout(origin_state)) @@ -194,7 +194,7 @@ compare_branchm <- function(test_path, branch1, branch2 = "master") { stopifnot(length(branch2) == 1) target <- git2r::repository("./") - original_state <- git2r::head(target) + original_state <- git2r::repository_head(target) same_commit <- .common_commit(branch1 = branch1, branch2 = branch2) # same_commit # --------------------------------------------- @@ -239,7 +239,7 @@ compare_branchm <- function(test_path, branch1, branch2 = "master") { target1 <- git2r::repository(file.path("./")) # If branch1 is specified, check out to it and obtain commit list if (!is.null(branch1)) { - original_state1 <- git2r::head(target1) + original_state1 <- git2r::repository_head(target1) git2r::checkout(object = target1, branch = branch1) } commitlist1 <- git2r::commits(target1) @@ -256,7 +256,7 @@ compare_branchm <- function(test_path, branch1, branch2 = "master") { target2 <- git2r::repository(file.path("./")) # If branch2 is specified, check out to it and obtain commit list if (!is.null(branch2)) { - original_state2 <- git2r::head(target2) + original_state2 <- git2r::repository_head(target2) git2r::checkout(object = target2, branch = branch2) } commitlist2 <- git2r::commits(target2) diff --git a/R/git_help.R b/R/git_help.R index 2db5ab95..35e9bcb6 100644 --- a/R/git_help.R +++ b/R/git_help.R @@ -6,7 +6,7 @@ #' @param commit_val git commit object, as returned by git2r::commits() #' #' @seealso \code{\link[git2r]{commits}} - + # The get_sha function, given a git commit object returns a character vector which is the # SHA1 value for the given commit. @@ -15,7 +15,7 @@ get_sha <- function(commit_val) { print(commit_val) stopifnot(git2r::is_commit(commit_val)) - attr(commit_val, which = "sha") + commit_val$sha } ## ----------------------------------------------------------------------------------------- @@ -33,7 +33,7 @@ get_datetime <- function(commit_val) { print(commit_val) stopifnot(git2r::is_commit(commit_val)) - methods::as((commit_val@committer@when), "POSIXct") + as.POSIXct(git2r::when(commit_val$author$when)) } ## ----------------------------------------------------------------------------------------- @@ -55,7 +55,7 @@ get_msg <- function(commit_val) { print(commit_val) stopifnot(git2r::is_commit(commit_val)) - base::substr(commit_val@summary, start = 1, stop = 15) + base::substr(commit_val$summary, start = 1, stop = 15) } ## ----------------------------------------------------------------------------------------- @@ -71,7 +71,8 @@ get_msg <- function(commit_val) { get_branch <- function(dir_path = "./") { repo <- git2r::repository(dir_path) - git2r::head(repo)@name + git2r::repository_head(repo)$name } ## ----------------------------------------------------------------------------------------- + diff --git a/R/plot_metrics.R b/R/plot_metrics.R index 3d52d71d..37d63c43 100644 --- a/R/plot_metrics.R +++ b/R/plot_metrics.R @@ -61,317 +61,15 @@ utils::globalVariables(c("metric_val", "test_name")) #' Function assumes the current directory to be the root directory of the #' repository/package being tested. #' - plot_metrics <- function(test_path, metric, num_commits = 5, save_data = FALSE, save_plots = FALSE, interactive = FALSE) { - stopifnot(is.character(test_path)) - stopifnot(length(test_path) == 1) - stopifnot(is.character(metric)) - stopifnot(length(metric) == 1) - stopifnot(is.numeric(num_commits)) - stopifnot(length(num_commits) == 1) - stopifnot(is.logical(save_data)) - stopifnot(length(save_data) == 1) - stopifnot(is.logical(save_plots)) - stopifnot(length(save_plots) == 1) - floor(num_commits) - - if (metric == "time") { - if (interactive) { - temp_out <- capture.output(.plot_interactive_time(test_path, num_commits, save_data, save_plots)) - } else { - temp_out <- capture.output(.plot_time(test_path, num_commits, save_data, save_plots)) - } - } - else if (metric == "memory") { - if (interactive) { - temp_out <- capture.output(.plot_interactive_mem(test_path, num_commits, save_data, save_plots)) - } else { - temp_out <- capture.output(.plot_mem(test_path, num_commits, save_data, save_plots)) - } - } - else if (metric == "memtime") { - if (interactive) { - temp_out <- capture.output(.plot_interactive_time(test_path, num_commits, save_data, save_plots)) - temp_out <- capture.output(.plot_interactive_mem(test_path, num_commits, save_data, save_plots)) - } else { - temp_out <- capture.output(.plot_time(test_path, num_commits, save_data, save_plots)) - temp_out <- capture.output(.plot_mem(test_path, num_commits, save_data, save_plots)) - } - } - else if (metric == "testMetrics") { - if (interactive) { - cat("Interactive mode not available for this metric!\nPrinting static plots instead.") - } - temp_out <- capture.output(.plot_testMetrics(test_path, num_commits, save_data, save_plots)) - } - else { - temp_out <- NULL - print("Input a valid metric parameter!") - } - remove(temp_out) -} - -## ----------------------------------------------------------------------------------------- - -.plot_testMetrics <- function(test_path, num_commits, save_data, save_plots) { - suppressMessages(mem_data <- mem_compare(test_path, num_commits)) - suppressMessages(time_data <- time_compare(test_path, num_commits)) - - # Store the metrics data if save_data is TRUE - if (save_data){ - - # Store the metric data - .save_data(time_data, pattern = "*.[rR]$", replacement = "_time.RData", - replace_string = basename(test_path)) - .save_data(mem_data, pattern = "*.[rR]$", replacement = "_mem.RData", - replace_string = basename(test_path)) - } - - metric_data <- rbind(time_data, mem_data) - t_names <- levels(metric_data$test_name) - - for (num in seq(t_names)) { - test_frame <- metric_data[metric_data$test_name == t_names[num],] - - tryCatch(expr = {test_plot <- - ggplot2::ggplot(data = test_frame, mapping = ggplot2::aes(message, metric_val)) + - ggplot2::geom_point(color = "blue") + - ggplot2::facet_grid(facets = metric_name ~ ., scales = "free") + - ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + - ggplot2::scale_x_discrete(limits = rev(levels(test_frame$message))) + - # In the above 5 lines of code, the first line creates the basic qplot. The - # fourth and fifth lines display the x-axis labels at 90 degrees to the - # horizontal and correct the order of message labels on the x -axis, - # respectively. - ggplot2::xlab("Commit message") + - ggplot2::ylab("Metric value") + - ggplot2::ggtitle(label = paste0("Variation in metrics for ", t_names[num])) - - - if (save_plots == TRUE) { - .save_plots(test_plot = test_plot, test_name = t_names[num], metric = "testMetrics") - print(test_plot) - } - else { - print(test_plot) - } - }, - error = function(e) { - print("Encountered an error!") - }) - } -} - -## ----------------------------------------------------------------------------------------- - -.plot_interactive_time <- function(test_path, num_commits, save_data, save_plots) { - - # Obtain the metrics data - suppressMessages(time_data <- time_compare(test_path, num_commits)) - - # Store the metrics data if save_data is TRUE - if (save_data){ - - # Store the metric data - .save_data(time_data, pattern = "*.[rR]$", replacement = "_time.RData", - replace_string = basename(test_path)) - } - - # Add links to the github page for each commit to data - remoteUrl <- git2r::remote_url(repo = git2r::repository(path = "./")) - remoteUrl <- (paste0(remoteUrl, "/commit/")) - time_data$remoteUrl <- paste0(remoteUrl, time_data$sha) - - levels(time_data$test_name) <- paste0(substr(levels(time_data$test_name), start = 0, stop = 4), - "...", - substr(levels(time_data$test_name), - start = nchar(levels(time_data$test_name)) - 4, - stop = nchar(levels(time_data$test_name)))) - - test_plot <- ggplot2::ggplot() + - ggplot2::geom_point(mapping = ggplot2::aes(x = message, y = metric_val, - href = remoteUrl), - color = "blue", - data = time_data) + - ggplot2::theme(axis.text.x = ggplot2::element_blank()) + - ggplot2::facet_grid(facets = test_name~., scales = "free") + - ggplot2::scale_x_discrete(limits = rev(levels(time_data$message))) + - ggplot2::xlab("Commit message") + - ggplot2::ylab("Runtime value") + - ggplot2::ggtitle(label = paste0("Variation in runtime for ", basename(test_path))) - - if (length(levels(time_data$test_name)) > 6) { - test_plot <- test_plot + - animint::theme_animint(height = 700) - } - else if (length(levels(time_data$test_name)) > 3) { - test_plot <- test_plot + - animint::theme_animint(height = 650) - } - - viz.list <- list(timeplot = test_plot) - - print("Loaded animint") - animint::animint2dir(plot.list = viz.list, out.dir = paste0(basename(getwd()), "_", "time_animint")) - unlink(x = paste0(basename(getwd()), "_", "time_animint"), recursive = T, force = T) -} - -## ----------------------------------------------------------------------------------------- - - -.plot_time <- function(test_path, num_commits, save_data, save_plots) { + .input_check(save_data, save_plots, interactive, num_commits, test_path, metric) - # Obtain the metrics data - suppressMessages(time_data <- time_compare(test_path, num_commits)) - - # Store the metrics data if save_data is TRUE - if (save_data){ - - # Store the metric data - .save_data(time_data, pattern = "*.[rR]$", replacement = "_time.RData", - replace_string = basename(test_path)) - } - - curr_name <- gsub(pattern = " ", replacement = "_", x = basename(test_path)) - curr_name <- gsub(pattern = ".[rR]$", replacement = "", x = curr_name) - - # Plot the metric data - tryCatch(expr = {test_plot <- - ggplot2::ggplot() + - ggplot2::geom_point(mapping = ggplot2::aes(message, metric_val), - data = time_data, color = "blue") + - ggplot2::facet_grid(facets = test_name ~ ., scales = "free") + - ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + - ggplot2::scale_x_discrete(limits = rev(levels(time_data$message))) + - # In the above 5 lines of code, the first line creates the basic qplot. The - # fourth and fifth lines display the x-axis labels at 90 degrees to the - # horizontal and correct the order of message labels on the x -axis, - # respectively. - ggplot2::xlab("Commit message") + - ggplot2::ylab("Time (in seconds)") + - ggplot2::ggtitle(label = paste0("Variation in time metrics for ", curr_name)) - - if (save_plots == TRUE) { - .save_plots(test_plot = test_plot, test_name = curr_name, metric = "time", - width = 1600, height = 1200) - print(test_plot) - } - else { - print(test_plot) - } - }, - error = function(e){ - print("Encountered an error!") - }) - -} - -## ----------------------------------------------------------------------------------------- - -.plot_interactive_mem <- function(test_path, num_commits, save_data, save_plots) { - - # Obtain the metrics data - suppressMessages(mem_data <- mem_compare(test_path, num_commits)) - - # Store the metrics data if save_data is TRUE - if (save_data){ - - # Store the metric data - .save_data(mem_data, pattern = "*.[rR]$", replacement = "_mem.RData", - replace_string = basename(test_path)) - } - - # Add links to the github page for each commit to data - remoteUrl <- git2r::remote_url(repo = git2r::repository(path = "./")) - remoteUrl <- (paste0(remoteUrl, "/commit/")) - mem_data$remoteUrl <- paste0(remoteUrl, mem_data$sha) - - levels(mem_data$test_name) <- paste0(substr(levels(mem_data$test_name), start = 0, stop = 4), - "...", - substr(levels(mem_data$test_name), - start = nchar(levels(mem_data$test_name)) - 4, - stop = nchar(levels(mem_data$test_name)))) - - test_plot <- ggplot2::ggplot() + - ggplot2::geom_point(mapping = ggplot2::aes(x = message, y = metric_val, - href = remoteUrl), - color = "blue", - data = mem_data) + - ggplot2::theme(axis.text.x = ggplot2::element_blank()) + - ggplot2::facet_grid(facets = test_name~metric_name, scales = "free") + - ggplot2::scale_x_discrete(limits = rev(levels(mem_data$message))) + - ggplot2::xlab("Commit message") + - ggplot2::ylab("Memory usage (in mb)") + - ggplot2::ggtitle(label = paste0("Variation in memory usage for ", basename(test_path))) - - if (length(levels(mem_data$test_name)) > 6) { - test_plot <- test_plot + - animint::theme_animint(height = 700) - } - else if (length(levels(mem_data$test_name)) > 3) { - test_plot <- test_plot + - animint::theme_animint(height = 650) - } - - viz.list <- list(memplot = test_plot) - - print("Loaded animint") - animint::animint2dir(plot.list = viz.list, out.dir = paste0(basename(getwd()), "_", "mem_animint")) - unlink(x = paste0(basename(getwd()), "_", "mem_animint"), recursive = T, force = T) -} - -## ----------------------------------------------------------------------------------------- - -.plot_mem <- function(test_path, num_commits, save_data, save_plots) { - - # Obtain the metrics data - suppressMessages(mem_data <- mem_compare(test_path, num_commits)) - - # Store the metrics data if save_data is TRUE - if (save_data){ - - # Store the metric data - .save_data(mem_data, pattern = "*.[rR]$", replacement = "_mem.RData", - replace_string = basename(test_path)) - } - - curr_name <- gsub(pattern = " ", replacement = "_", x = basename(test_path)) - curr_name <- gsub(pattern = ".[rR]$", replacement = "", x = curr_name) - - tryCatch(expr = {test_plot <- - ggplot2::ggplot(data = mem_data, mapping = ggplot2::aes(message, metric_val)) + - ggplot2::geom_point(color = "blue") + - ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90), - strip.text.x = ggplot2::element_text(size = 10, face = "bold")) + - ggplot2::scale_x_discrete(limits = rev(levels(mem_data$message))) + - ggplot2::facet_grid(test_name ~ metric_name, scales = "free") + - # In the above 5 lines of code, the first line creates the basic qplot. The - # third and fourth lines display the x-axis labels at 90 degrees to the - # horizontal and correct the order of message labels on the x -axis, - # respectively. The fourth line creates a facet grid so as to seperate - # the plots for the max memory and leak memory metrics. - ggplot2::ylab(label = "Memory (in Mb)") + - ggplot2::xlab(label = "Commit messages") + - ggplot2::ggtitle(label = paste0("Variation in memory metrics for ", curr_name)) - - if (save_plots == TRUE) { - .save_plots(test_plot = test_plot, test_name = curr_name, metric = "memory") - print(test_plot) - } - else { - print(test_plot) - } - }, - error = function(e) { - print("Encountered an error!") - }) + floor(num_commits) + .metrics(metric, interactive, test_path, num_commits, save_data, save_plots) } -## ----------------------------------------------------------------------------------------- -## ----------------------------------------------------------------------------------------- - #' Plot the specified metrics of all test files in a specified directory on a #' webpage. #' @@ -412,15 +110,11 @@ plot_metrics <- function(test_path, metric, num_commits = 5, save_data = FALSE, #' Function assumes the current directory to be the root directory of the #' repository being tested. #' - +#' plot_webpage <- function(test_directory = "tests/testthat", metric = "testMetrics", output_name = "RperformTest.html"){ - stopifnot(is.character(test_directory)) - stopifnot(is.character(output_name)) - stopifnot(is.character(metric)) - stopifnot(length(test_directory) == 1) - stopifnot(length(output_name) == 1) - stopifnot(length(metric) == 1) + .input_check(save_data = FALSE, save_plots = FALSE, interactive = FALSE, + num_commits = 0, test_directory, metric, output_name) out_file <- paste0(output_name, ".Rmd") @@ -436,9 +130,6 @@ plot_webpage <- function(test_directory = "tests/testthat", metric = "testMetric rmarkdown::render(input = out_file, output_format = "html_document", output_file = output_name) } -## ----------------------------------------------------------------------------------------- -## ----------------------------------------------------------------------------------------- - #' Plot metrics across versions for all files in a given directory. #' #' Given a directory path, plot the memory and time usage statistics of all files @@ -497,15 +188,9 @@ plot_webpage <- function(test_directory = "tests/testthat", metric = "testMetric plot_directory <- function(test_directory, metric = "testMetrics", num_commits = 5, save_data = FALSE, save_plots = TRUE) { - stopifnot(is.character(test_directory)) - stopifnot(is.character(metric)) - stopifnot(is.numeric(num_commits)) - stopifnot(is.logical(save_data)) - stopifnot(is.logical(save_plots)) - stopifnot(length(test_directory) == 1) - stopifnot(length(metric) == 1) - stopifnot(length(save_data) == 1) - stopifnot(length(save_plots) == 1) + + .input_check(save_data, save_plots, interactive = FALSE, num_commits, test_directory, metric) + floor(num_commits) file_names <- list.files(test_directory) @@ -604,41 +289,159 @@ plot_directory <- function(test_directory, metric = "testMetrics", num_commits = plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", save_data = FALSE, save_plots = TRUE) { - stopifnot(is.character(test_path)) - stopifnot(length(test_path) == 1) - stopifnot(is.character(branch1)) - stopifnot(length(branch1) == 1) - stopifnot(is.character(branch2)) - stopifnot(length(branch2) == 1) - stopifnot(is.character(metric)) - stopifnot(length(metric) == 1) - stopifnot(is.logical(save_data)) - stopifnot(length(save_data) == 1) - stopifnot(is.logical(save_plots)) - stopifnot(length(save_plots) == 1) + .input_check(save_data, save_plots, interactive = FALSE, num_commits = 0, test_path, metric, + branch1, branch2) - if (metric == "time") { - temp_out <- capture.output(.plot_btime(test_path, branch1, branch2, save_data, save_plots)) + .metrics_branch(metric, test_path, branch1, branch2, save_data, save_plots) +} + +.plot_testMetrics <- function(test_path, num_commits, save_data, save_plots) { + suppressMessages(mem_data <- mem_compare(test_path, num_commits)) + suppressMessages(time_data <- time_compare(test_path, num_commits)) + + # Store the metrics data if save_data is TRUE + if (save_data){ + + # Store the metric data + .save_data(time_data, pattern = "*.[rR]$", replacement = "_time.RData", + replace_string = basename(test_path)) + .save_data(mem_data, pattern = "*.[rR]$", replacement = "_mem.RData", + replace_string = basename(test_path)) } - else if (metric == "memory") { - temp_out <- capture.output(.plot_bmem(test_path, branch1, branch2, save_data, save_plots)) + + metric_data <- rbind(time_data, mem_data) + t_names <- levels(metric_data$test_name) + + for (num in seq(t_names)) { + test_frame <- metric_data[metric_data$test_name == t_names[num],] + + tryCatch(expr = {test_plot <- + ggplot2::ggplot(data = test_frame, mapping = ggplot2::aes(message, metric_val)) + + ggplot2::geom_point(color = "blue") + + ggplot2::facet_grid(facets = metric_name ~ ., scales = "free") + + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + + ggplot2::scale_x_discrete(limits = rev(levels(test_frame$message))) + + # In the above 5 lines of code, the first line creates the basic qplot. The + # fourth and fifth lines display the x-axis labels at 90 degrees to the + # horizontal and correct the order of message labels on the x -axis, + # respectively. + ggplot2::xlab("Commit message") + + ggplot2::ylab("Metric value") + + ggplot2::ggtitle(label = paste0("Variation in metrics for ", t_names[num])) + + + if (save_plots == TRUE) { + .save_plots(test_plot = test_plot, test_name = t_names[num], metric = "testMetrics") + print(test_plot) + } + else { + print(test_plot) + } + }, + error = function(e) { + print("Encountered an error!") + }) } - else if (metric == "memtime") { - temp_out <- capture.output(.plot_btime(test_path, branch1, branch2, save_data, save_plots)) - temp_out <- capture.output(.plot_bmem(test_path, branch1, branch2, save_data, save_plots)) +} + +.plot_interactive_time <- function(test_path, num_commits, save_data, save_plots) { + + # Obtain the metrics data + suppressMessages(time_data <- time_compare(test_path, num_commits)) + + # Store the metrics data if save_data is TRUE + if (save_data){ + + # Store the metric data + .save_data(time_data, pattern = "*.[rR]$", replacement = "_time.RData", + replace_string = basename(test_path)) } - else if (metric == "testMetrics") { - temp_out <- capture.output(.plot_btestMetrics(test_path, branch1, branch2, save_data, save_plots)) + + # Add links to the github page for each commit to data + remoteUrl <- git2r::remote_url(repo = git2r::repository(path = "./")) + remoteUrl <- (paste0(remoteUrl, "/commit/")) + time_data$remoteUrl <- paste0(remoteUrl, time_data$sha) + + levels(time_data$test_name) <- paste0(substr(levels(time_data$test_name), start = 0, stop = 4), + "...", + substr(levels(time_data$test_name), + start = nchar(levels(time_data$test_name)) - 4, + stop = nchar(levels(time_data$test_name)))) + + test_plot <- ggplot2::ggplot() + + ggplot2::geom_point(mapping = ggplot2::aes(x = message, y = metric_val, + href = remoteUrl), + color = "blue", + data = time_data) + + ggplot2::theme(axis.text.x = ggplot2::element_blank()) + + ggplot2::facet_grid(facets = test_name~., scales = "free") + + ggplot2::scale_x_discrete(limits = rev(levels(time_data$message))) + + ggplot2::xlab("Commit message") + + ggplot2::ylab("Runtime value") + + ggplot2::ggtitle(label = paste0("Variation in runtime for ", basename(test_path))) + + if (length(levels(time_data$test_name)) > 6) { + test_plot <- test_plot + + animint::theme_animint(height = 700) + } + else if (length(levels(time_data$test_name)) > 3) { + test_plot <- test_plot + + animint::theme_animint(height = 650) + } + + viz.list <- list(timeplot = test_plot) + + print("Loaded animint") + animint::animint2dir(plot.list = viz.list, out.dir = paste0(basename(getwd()), "_", "time_animint")) + unlink(x = paste0(basename(getwd()), "_", "time_animint"), recursive = T, force = T) +} + +.plot_time <- function(test_path, num_commits, save_data, save_plots) { + + # Obtain the metrics data + suppressMessages(time_data <- time_compare(test_path, num_commits)) + + # Store the metrics data if save_data is TRUE + if (save_data){ + # Store the metric data + .save_data(time_data, pattern = "*.[rR]$", replacement = "_time.csv", + replace_string = basename(test_path)) + } + + curr_name <- gsub(pattern = " ", replacement = "_", x = basename(test_path)) + curr_name <- gsub(pattern = ".[rR]$", replacement = "", x = curr_name) + + # Plot the metric data + tryCatch(expr = {test_plot <- + ggplot2::ggplot() + + ggplot2::geom_point(mapping = ggplot2::aes(message, metric_val), + data = time_data, color = "blue") + + ggplot2::facet_grid(facets = test_name ~ ., scales = "free") + + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + + ggplot2::scale_x_discrete(limits = rev(levels(time_data$message))) + + # In the above 5 lines of code, the first line creates the basic qplot. The + # fourth and fifth lines display the x-axis labels at 90 degrees to the + # horizontal and correct the order of message labels on the x -axis, + # respectively. + ggplot2::xlab("Commit message") + + ggplot2::ylab("Time (in seconds)") + + ggplot2::ggtitle(label = paste0("Variation in time metrics for ", curr_name)) + + if (save_plots == TRUE) { + .save_plots(test_plot = test_plot, test_name = curr_name, metric = "time", + width = 1600, height = 1200) + print(test_plot) } else { - temp_out <- NULL - print("Enter valid metric!") + print(test_plot) } - remove(temp_out) + }, + error = function(e){ + print("Encountered an error!") + }) + } -## ----------------------------------------------------------------------------------------- - .plot_btestMetrics <- function(test_path, branch1, branch2, save_data, save_plots) { suppressMessages(time_data <- compare_brancht(test_path = test_path, @@ -667,39 +470,39 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", extremes_frame <- .find_midvals(data = test_frame) tryCatch(expr = {test_plot <- - ggplot2::ggplot(data = test_frame, mapping = ggplot2::aes(message, metric_val)) + - ggplot2::geom_point(color = "blue") + - ggplot2::facet_grid(facets = metric_name ~ ., scales = "free") + - ggplot2::geom_text(data = extremes_frame, - mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.3, - y = mid_val, - label = branch2, angle = 90)) + - ggplot2::geom_text(data = extremes_frame, - mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.7, - y = mid_val, - label = branch1, angle = -90)) + - ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + - ggplot2::geom_vline(mapping = ggplot2::aes(xintercept = same_commit$cnum_b2 + 0.5)) + - ggplot2::scale_x_discrete(limits = rev(levels(test_frame$message))) + - # In the above 6 lines of code, the first line creates - # the basic qplot. The fourth and sixth lines display the - # x-axis labels at 90 degrees to the horizontal and - # correct the order of message labels on the x -axis, - # respectively. The fifth line plots a vertical seperator between - # the commit from branch2 and the commits from branch1. - ggplot2::xlab("Commit message") + - ggplot2::ylab("Metric value") + - ggplot2::ggtitle(label = paste0("Variation in metrics for ", t_names[num])) - - curr_name <- paste0(branch1, "_", branch2, "_", t_names[num]) - - if (save_plots == TRUE) { - .save_plots(test_plot = test_plot, test_name = t_names[num], - metric = "testMetrics") - print(test_plot) - } else { - print(test_plot) - } + ggplot2::ggplot(data = test_frame, mapping = ggplot2::aes(message, metric_val)) + + ggplot2::geom_point(color = "blue") + + ggplot2::facet_grid(facets = metric_name ~ ., scales = "free") + + ggplot2::geom_text(data = extremes_frame, + mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.3, + y = mid_val, + label = branch2, angle = 90)) + + ggplot2::geom_text(data = extremes_frame, + mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.7, + y = mid_val, + label = branch1, angle = -90)) + + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + + ggplot2::geom_vline(mapping = ggplot2::aes(xintercept = same_commit$cnum_b2 + 0.5)) + + ggplot2::scale_x_discrete(limits = rev(levels(test_frame$message))) + + # In the above 6 lines of code, the first line creates + # the basic qplot. The fourth and sixth lines display the + # x-axis labels at 90 degrees to the horizontal and + # correct the order of message labels on the x -axis, + # respectively. The fifth line plots a vertical seperator between + # the commit from branch2 and the commits from branch1. + ggplot2::xlab("Commit message") + + ggplot2::ylab("Metric value") + + ggplot2::ggtitle(label = paste0("Variation in metrics for ", t_names[num])) + + curr_name <- paste0(branch1, "_", branch2, "_", t_names[num]) + + if (save_plots == TRUE) { + .save_plots(test_plot = test_plot, test_name = t_names[num], + metric = "testMetrics") + print(test_plot) + } else { + print(test_plot) + } }, error = function(e){ print("Encountered an error!") @@ -708,9 +511,6 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", } -## ----------------------------------------------------------------------------------------- - - .plot_btime <- function(test_path, branch1, branch2, save_data, save_plots) { suppressMessages(time_data <- compare_brancht(test_path = test_path, @@ -743,39 +543,39 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", # Plot the branches' metric data tryCatch(expr = {test_plot <- - ggplot2::ggplot(data = time_data, mapping = ggplot2::aes(message, metric_val)) + - ggplot2::geom_point(color = "blue") + - ggplot2::facet_grid(test_name ~ ., scales = "free") + - ggplot2::geom_text(data = extremes_frame, - mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.3, - y = mid_val, - label = branch2, angle = 90)) + - ggplot2::geom_text(data = extremes_frame, - mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.7, - y = mid_val, - label = branch1, angle = -90)) + - ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + - ggplot2::geom_vline(mapping = ggplot2::aes(xintercept = same_commit$cnum_b2 + 0.5)) + - ggplot2::scale_x_discrete(limits = rev(levels(time_data$message))) + - # In the above 8 lines of code, the first line creates - # the basic plot. The sixth and eigth lines display the - # x-axis labels at 90 degrees to the horizontal and - # correct the order of message labels on the x -axis, - # respectively. The seventh line plots a vertical seperator between - # the commit from branch2 and the commits from branch1. - ggplot2::xlab(label = "Commit messages") + - ggplot2::ylab(label = "Time (in seconds)") + - ggplot2::ggtitle(label = paste0("Variation in time metrics across branches ", - branch2, " and ", branch1)) - - if (save_plots == TRUE) { - .save_plots(test_plot = test_plot, test_name = curr_name, metric = "time", - width = 1600, height = 900) - print(test_plot) - } - else { - print(test_plot) - } + ggplot2::ggplot(data = time_data, mapping = ggplot2::aes(message, metric_val)) + + ggplot2::geom_point(color = "blue") + + ggplot2::facet_grid(test_name ~ ., scales = "free") + + ggplot2::geom_text(data = extremes_frame, + mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.3, + y = mid_val, + label = branch2, angle = 90)) + + ggplot2::geom_text(data = extremes_frame, + mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.7, + y = mid_val, + label = branch1, angle = -90)) + + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90)) + + ggplot2::geom_vline(mapping = ggplot2::aes(xintercept = same_commit$cnum_b2 + 0.5)) + + ggplot2::scale_x_discrete(limits = rev(levels(time_data$message))) + + # In the above 8 lines of code, the first line creates + # the basic plot. The sixth and eigth lines display the + # x-axis labels at 90 degrees to the horizontal and + # correct the order of message labels on the x -axis, + # respectively. The seventh line plots a vertical seperator between + # the commit from branch2 and the commits from branch1. + ggplot2::xlab(label = "Commit messages") + + ggplot2::ylab(label = "Time (in seconds)") + + ggplot2::ggtitle(label = paste0("Variation in time metrics across branches ", + branch2, " and ", branch1)) + + if (save_plots == TRUE) { + .save_plots(test_plot = test_plot, test_name = curr_name, metric = "time", + width = 1600, height = 900) + print(test_plot) + } + else { + print(test_plot) + } }, error = function(e){ print("Encountered an error!") @@ -783,8 +583,6 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", } -## ----------------------------------------------------------------------------------------- - .plot_bmem <- function(test_path, branch1, branch2, save_data, save_plots) { suppressMessages(mem_data <- compare_branchm(test_path = test_path, @@ -817,39 +615,39 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", # Plot the branches' metric data tryCatch(expr = {test_plot <- - ggplot2::ggplot(data = mem_data, mapping = ggplot2::aes(message, metric_val)) + - ggplot2::geom_point(color = "blue") + - ggplot2::facet_grid(test_name ~ metric_name, scales = "free") + - ggplot2::geom_text(data = extremes_frame, - mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.3, - y = mid_val, - label = branch2, angle = 90)) + - ggplot2::geom_text(data = extremes_frame, - mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.7, - y = mid_val, - label = branch1, angle = -90)) + - ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90), - strip.text.x = ggplot2::element_text(size = 10, face = "bold")) + - ggplot2::geom_vline(mapping = ggplot2::aes(xintercept = same_commit$cnum_b2 + 0.5)) + - ggplot2::scale_x_discrete(limits = rev(levels(mem_data$message))) + - # In the above 8 lines of code, the first line creates - # the basic plot. The sixth and eigth lines display the - # x-axis labels at 90 degrees to the horizontal and - # correct the order of message labels on the x -axis, - # respectively. The seventh line plots a vertical seperator between - # the commit from branch2 and the commits from branch1. - ggplot2::xlab(label = "Commit messages") + - ggplot2::ylab(label = "Memory (in Mb") + - ggplot2::ggtitle(label = paste0("Variation in memory metrics across branches ", - branch2, " and ", branch1)) - - if (save_plots == TRUE) { - .save_plots(test_plot = test_plot, test_name = curr_name, metric = "memory") - print(test_plot) - } - else { - print(test_plot) - } + ggplot2::ggplot(data = mem_data, mapping = ggplot2::aes(message, metric_val)) + + ggplot2::geom_point(color = "blue") + + ggplot2::facet_grid(test_name ~ metric_name, scales = "free") + + ggplot2::geom_text(data = extremes_frame, + mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.3, + y = mid_val, + label = branch2, angle = 90)) + + ggplot2::geom_text(data = extremes_frame, + mapping = ggplot2::aes(x = same_commit$cnum_b2 + 0.7, + y = mid_val, + label = branch1, angle = -90)) + + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = -90), + strip.text.x = ggplot2::element_text(size = 10, face = "bold")) + + ggplot2::geom_vline(mapping = ggplot2::aes(xintercept = same_commit$cnum_b2 + 0.5)) + + ggplot2::scale_x_discrete(limits = rev(levels(mem_data$message))) + + # In the above 8 lines of code, the first line creates + # the basic plot. The sixth and eigth lines display the + # x-axis labels at 90 degrees to the horizontal and + # correct the order of message labels on the x -axis, + # respectively. The seventh line plots a vertical seperator between + # the commit from branch2 and the commits from branch1. + ggplot2::xlab(label = "Commit messages") + + ggplot2::ylab(label = "Memory (in Mb") + + ggplot2::ggtitle(label = paste0("Variation in memory metrics across branches ", + branch2, " and ", branch1)) + + if (save_plots == TRUE) { + .save_plots(test_plot = test_plot, test_name = curr_name, metric = "memory") + print(test_plot) + } + else { + print(test_plot) + } }, error = function(e){ print("Encountered an error!") @@ -857,12 +655,6 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", } -## ----------------------------------------------------------------------------------------- - - -## ----------------------------------------------------------------------------------------- -## ----------------------------------------------------------------------------------------- - .save_data <- function(metric_frame, pattern = "*.[rR]$", replacement, replace_string) { # Create a directory for storing the metric data @@ -872,9 +664,12 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", if(grepl(pattern = "time", x = replacement) > 0) { time_frame <- metric_frame - save(time_frame, file = file.path("Rperform_Data", sub(pattern = pattern, - replacement = replacement, - x = basename(replace_string)))) + # save(time_frame, file = file.path("Rperform_Data", sub(pattern = pattern, + # replacement = replacement, + # x = basename(replace_string)))) + write.csv(time_frame, file = file.path("Rperform_Data", sub(pattern = pattern, + replacement = replacement, + x = basename(replace_string)))) } else if(grepl(pattern = "mem", x = replacement) > 0){ mem_frame <- metric_frame @@ -884,8 +679,6 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", } } -## ----------------------------------------------------------------------------------------- - .save_plots <- function(test_plot, test_name, metric, width = 1024, height = 768, units = "px") { if (metric == "time") { @@ -915,8 +708,6 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", grDevices::dev.off() } -## ----------------------------------------------------------------------------------------- - .find_midvals <- function(data) { extremes_list <- list() t_names <- as.character(unique(data$test_name)) @@ -940,3 +731,119 @@ plot_branchmetrics <- function(test_path, metric, branch1, branch2 = "master", extremes_frame } + +.input_check <- function(save_data, save_plots, interactive, num_commits, ...){ + + stopifnot(is.logical(save_data)) + stopifnot(length(save_data) == 1) + + stopifnot(is.logical(save_plots)) + stopifnot(length(save_plots) == 1) + + stopifnot(is.logical(interactive)) + stopifnot(length(interactive) == 1) + + stopifnot(is.numeric(num_commits)) + stopifnot(length(num_commits) == 1) + + for(chr_var in list(...)){ + stopifnot(is.character(chr_var)) + stopifnot(length(chr_var) == 1) + } +} + +.metrics <- function(metric, interactive, test_path, num_commits, save_data, save_plots){ + if (metric == "time") { + if (interactive) { + temp_out <- capture.output(.plot_interactive_time(test_path, num_commits, save_data, save_plots)) + } else { + temp_out <- capture.output(.plot_time(test_path, num_commits, save_data, save_plots)) + } + } + else if (metric == "memory") { + if (interactive) { + temp_out <- capture.output(.plot_interactive_mem(test_path, num_commits, save_data, save_plots)) + } else { + temp_out <- capture.output(.plot_mem(test_path, num_commits, save_data, save_plots)) + } + } + else if (metric == "memtime") { + if (interactive) { + temp_out <- capture.output(.plot_interactive_time(test_path, num_commits, save_data, save_plots)) + temp_out <- capture.output(.plot_interactive_mem(test_path, num_commits, save_data, save_plots)) + } else { + temp_out <- capture.output(.plot_time(test_path, num_commits, save_data, save_plots)) + temp_out <- capture.output(.plot_mem(test_path, num_commits, save_data, save_plots)) + } + } + else if (metric == "testMetrics") { + if (interactive) { + cat("Interactive mode not available for this metric!\nPrinting static plots instead.") + } + temp_out <- capture.output(.plot_testMetrics(test_path, num_commits, save_data, save_plots)) + } + else { + temp_out <- NULL + print("Input a valid metric parameter!") + } + remove(temp_out) +} + +.metrics_branch <- function(metric, test_path, branch1, branch2, save_data, save_plots){ + if (metric == "time") { + temp_out <- capture.output(.plot_btime(test_path, branch1, branch2, save_data, save_plots)) + } + else if (metric == "memory") { + temp_out <- capture.output(.plot_bmem(test_path, branch1, branch2, save_data, save_plots)) + } + else if (metric == "memtime") { + temp_out <- capture.output(.plot_btime(test_path, branch1, branch2, save_data, save_plots)) + temp_out <- capture.output(.plot_bmem(test_path, branch1, branch2, save_data, save_plots)) + } + else if (metric == "testMetrics") { + temp_out <- capture.output(.plot_btestMetrics(test_path, branch1, branch2, save_data, save_plots)) + } + else { + temp_out <- NULL + print("Enter valid metric!") + } + remove(temp_out) +} + + + +run_all_test <- function(num_commits = 1) { + test_file_list <- list.files(path = "./tests/testthat/", full.names = TRUE) + # stop(length(test_file_list) == 0) + # Obtain the metrics data + head_sha = git2r::commits(n=1)[[1]]$sha + benchmark_date = Sys.time() + time_data <- list() + for(test_file in test_file_list){ + temp_time_data <- data.frame(test_num= 0, test_name= basename(test_file), metric_name = "runtime (in seconds)", status="Fail", + metric_val = NA, commit_message = NA, commit_SHA = NA, commit_date = NA, benchmark_date = benchmark_date, benchmark_most_recent_SHA = head_sha) + tryCatch(expr={ + suppressMessages(temp_time_data <- time_compare(test_file, num_commits, benchmark_date, head_sha)) + }, + error = function(e){ + }, + finally = { + time_data <- rbind(time_data,temp_time_data) + }) + } + + .save_data_alt(time_data, pattern = "*.[rR]$", replacement = "_result.csv", + replace_string = getwd()) +} + +.save_data_alt <- function(metric_frame, pattern = "*.[rR]$", replacement, replace_string) { + + # Create a directory for storing the metric data + if (!dir.exists("./Rperform_Data")){ + dir.create(path = "./Rperform_Data") + } + + time_frame <- metric_frame + csv_file = file.path("Rperform_Data", paste(basename(replace_string), "Result.csv", sep = "_")) + write.table(time_frame, file = csv_file, sep = ",",row.names = FALSE ,col.names = !file.exists(csv_file), append = TRUE) +} diff --git a/R/repo_metrics.R b/R/repo_metrics.R index 83fb0242..fe20bc38 100644 --- a/R/repo_metrics.R +++ b/R/repo_metrics.R @@ -41,10 +41,6 @@ utils::globalVariables(c("mem_result")) # n commits in the repo. list_commits <- function(path = "./", num_commits = 20){ - stopifnot(is.character(path)) - stopifnot(length(path) == 1) - stopifnot(is.numeric(num_commits)) - stopifnot(length(num_commits) == 1) num_commits <- floor(num_commits) target <- git2r::repository(path) @@ -55,9 +51,9 @@ list_commits <- function(path = "./", num_commits = 20){ date_list <- list() for (i in 1:num_commits) { - com <- attr(commit_list[[i]], which = "sha") - msg <- attr(commit_list[[i]], which = "summary") - com_date <- as(commit_list[[i]]@committer@when, "character") + com <- commit_list[[i]]$sha + msg <- commit_list[[i]]$summary + com_date <- commit_list[[i]]$author$when sha_list[i] <- com msg_list[i] <- msg date_list[i] <- com_date @@ -119,11 +115,8 @@ list_commits <- function(path = "./", num_commits = 20){ # The time_commit function, given a test-file path, checks its run-time details # against the specified commit in the current git repository. -time_commit <- function(test_path, test_commit) { - - stopifnot(is.character(test_path)) - stopifnot(length(test_path) == 1) - stopifnot(!is.null(test_commit)) +time_commit <- function(test_path, test_commit, test_num = 0, current_date, head_sha) { + # browser() stopifnot(git2r::is_commit(test_commit)) # Get the meta-information from the commit @@ -152,7 +145,7 @@ time_commit <- function(test_path, test_commit) { target <- git2r::repository("./") # Reverting to the current branch on exit from the function ###################################################################### - original_state <- git2r::head(target) + original_state <- git2r::repository_head(target) git2r::checkout(test_commit) on.exit(expr = git2r::checkout(original_state)) ###################################################################### @@ -166,70 +159,52 @@ time_commit <- function(test_path, test_commit) { # -------------------------------------------------------------- # require(testthat) - file_status = "pass" + file_status <- "Fail" + seconds_file <- NA + test <- function(){ + base::source(temp_file_original, local = T) + } # We have used tryCatch so that execution doesn't stop in case of an error # in the test file. Rather we will modify the values in the result data frame # (time as NA, status as 'fail') to let the user know of the error. - seconds_file <- tryCatch(expr = { - if(requireNamespace('microbenchmark')){ - times <- microbenchmark::microbenchmark(test = { - base::source(temp_file_original, local = T) - }, times = 3) - times$time/1e9 - } else { - replicate(3, { - time_vec <- system.time( { - source(temp_file_original, local = T) - } ) - time_vec[["elapsed"]] - }) - } - }, - error = function(e){ - file_status = "fail" - NA - } - ) + # seconds_file <- .benchmark(test()) + tryCatch(expr={ + seconds_file <- .benchmark(test()) + file_status <- "Pass" + }, + error = function(e){ + file_status <- "Fail" + NA + }) # --------------------------------------------------------------- # Code block measuring the run-time of the testthat code blocks (if present) # -------------------------------------------------------------------------- - testthatQuantity <- function(test_name, code){ +testthatQuantity <- function(test_name, code){ e <- parent.frame() code_subs <- substitute(code) run <- function(){ testthat:::test_code(test_name, code_subs, env=e) } - status = "pass" + status <- "Fail" + seconds <- NA # We have used tryCatch so that execution doesn't stop in case of an error # in a testthat block. Rather we modify the values in the result data frame # (time as NA, status as 'fail') to let the user know of the error. - seconds <- tryCatch(expr = { - if(requireNamespace('microbenchmark')){ - times <- microbenchmark::microbenchmark(test = { - run() - }, times = 3) - times$time/1e9 - } else { - replicate(3, { - time_vec <- system.time( { - run() - } ) - time_vec[["elapsed"]] - }) - } - }, - error = function(e){ - status = "fail" - NA - } - ) - - time_df <- data.frame(test_name, metric_name = "runtime (in seconds)", status, - metric_val = seconds, message = msg_val, - sha = sha_val, date_time = commit_dtime) + tryCatch(expr={ + seconds <- .benchmark(run()) + status <- "Pass" + }, + error = function(e){ + status <- "Fail" + NA + }) + time_df <- data.frame(test_num, test_name, metric_name = "runtime (in seconds)", status, + metric_val = seconds, commit_message = msg_val, + commit_SHA = sha_val, commit_date = commit_dtime, + benchmark_date = current_date, benchmark_most_recent_SHA = head_sha) test_results[[test_name]] <<- time_df } @@ -244,10 +219,11 @@ time_commit <- function(test_path, test_commit) { test_results_df <- do.call(rbind, test_results) # test_results_df["file runtime"] <- seconds_file # test_results_df["file runtime-2"] <- seconds_file2 - test_results_df <- rbind(test_results_df, data.frame(test_name = basename(test_path), + test_results_df <- rbind(test_results_df, data.frame(test_num, test_name = basename(test_path), metric_name = "runtime (in seconds)", status = file_status, - metric_val = seconds_file, message = msg_val, - sha = sha_val, date_time = commit_dtime)) + metric_val = seconds_file, commit_message = msg_val, + commit_SHA = sha_val, commit_date = commit_dtime, + benchmark_date = current_date, benchmark_most_recent_SHA = head_sha)) rownames(test_results_df) <- NULL test_results_df @@ -307,11 +283,7 @@ time_commit <- function(test_path, test_commit) { # (if successful), datetime and message corresponding to the commit the value is # for. -time_compare <- function(test_path, num_commits = 10) { - stopifnot(is.character(test_path)) - stopifnot(length(test_path) == 1) - stopifnot(is.numeric(num_commits)) - stopifnot(length(num_commits) == 1) +time_compare <- function(test_path, num_commits = 10, current_date, head_sha) { num_commits <- floor(num_commits) target <- git2r::repository("./") @@ -320,7 +292,11 @@ time_compare <- function(test_path, num_commits = 10) { for(commit_i in seq_along(commit_list)){ one_commit <- commit_list[[commit_i]] - suppressMessages(result_list[[commit_i]] <- time_commit(test_path, one_commit)) + for (current_i in 1:3){ + suppressMessages(result_list[[3*(commit_i-1)+current_i]] <- time_commit(test_path, one_commit, test_num = current_i, + current_date, head_sha)) + } + # browser() } test_results <- do.call(rbind, result_list) @@ -415,7 +391,7 @@ mem_commit <- function(test_path, test_commit) { ## Git operations target <- git2r::repository("./") - original_state <- git2r::head(target) + original_state <- git2r::repository_head(target) git2r::checkout(test_commit) on.exit(expr = git2r::checkout(original_state)) test_results <- list() @@ -435,7 +411,7 @@ mem_commit <- function(test_path, test_commit) { } new_name <- gsub(pattern = " ", replacement = "", x = test_name) - test_status <- "pass" + test_status <- "Pass" # We have used tryCatch so that execution doesn't stop in case of an error # in a testthat block. Rather we modify the values in the result data frame # (memories as NA, status as 'fail') to let the user know of the error. @@ -471,7 +447,7 @@ mem_commit <- function(test_path, test_commit) { ## Obtaining the memory metrics for the file file_name <- basename(test_path) - file_status <- "pass" + file_status <- "Pass" rss_list <- tryCatch(expr = { .rss.profile.start(paste0(file_name, ".RSS")) @@ -643,11 +619,16 @@ mem_compare <- function(test_path, num_commits = 10) { result_list[[paste0(commit_i, as.character(test_t))]] <- mem_result } } - system("rm *RSS*") system("rm mem_result.RData") do.call(what = rbind, args = result_list) } -## ----------------------------------------------------------------------------------------- \ No newline at end of file +## ----------------------------------------------------------------------------------------- + +.benchmark <- function(func){ + times <- microbenchmark::microbenchmark(func, times = 1) + times$time/1e9 + +}