From ef36df69af494ed5023f3290cb18626769022696 Mon Sep 17 00:00:00 2001 From: "dyfan.jones" Date: Mon, 19 Aug 2024 10:14:34 +0100 Subject: [PATCH 1/8] ignore generated make.paws code --- .github/workflows/pr-commands.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-commands.yaml b/.github/workflows/pr-commands.yaml index 0bde88392..8bbbd9c27 100644 --- a/.github/workflows/pr-commands.yaml +++ b/.github/workflows/pr-commands.yaml @@ -66,7 +66,7 @@ jobs: - name: Style run: | - styler::style_pkg(pkg = 'paws.common') + styler::style_pkg(pkg = 'paws.common', exclude_files = c("R/RcppExports\\.R", "R/cpp11\\.R", "R/import-standalone.*\\.R", "R/service_parameter_helper\\.R")) styler::style_pkg(pkg = 'make.paws') shell: Rscript {0} From 31e90a510daa3289a8a4ff118e0c043104fa08b5 Mon Sep 17 00:00:00 2001 From: "dyfan.jones" Date: Mon, 19 Aug 2024 10:15:40 +0100 Subject: [PATCH 2/8] formatting --- paws.common/R/client.R | 3 ++- paws.common/R/custom_s3.R | 28 ++++++++++----------- paws.common/R/error.R | 2 +- paws.common/R/net.R | 2 +- paws.common/tests/testthat/test_custom_s3.R | 9 +++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/paws.common/R/client.R b/paws.common/R/client.R index add7291a0..f65660f61 100644 --- a/paws.common/R/client.R +++ b/paws.common/R/client.R @@ -112,8 +112,9 @@ resolver_endpoint <- function(service, region, endpoints, sts_regional_endpoint } signing_region <- if (e[["global"]]) "us-east-1" else region endpoint <- endpoint_unescape(e[["endpoint"]], service, signing_region) - if (grepl(HOST_PREFIX_RE, host_prefix)) + if (grepl(HOST_PREFIX_RE, host_prefix)) { endpoint <- sprintf("%s%s", host_prefix, endpoint) + } endpoint <- gsub("^(.+://)?", sprintf("%s://", scheme), endpoint) return(list( diff --git a/paws.common/R/custom_s3.R b/paws.common/R/custom_s3.R index 6747e75ed..a71db983f 100644 --- a/paws.common/R/custom_s3.R +++ b/paws.common/R/custom_s3.R @@ -5,14 +5,14 @@ #' @include head_bucket.R NULL -VERSION_ID_SUFFIX <- '?versionId=' +VERSION_ID_SUFFIX <- "?versionId=" ACCESSPOINT_ARN <- paste0( "^arn:(aws).*:(s3|s3-object-lambda):[a-z\\-0-9]*:[0-9]{12}:accesspoint[/:]", "[a-zA-Z0-9\\-.]{1,63}$" ) -OUTPOST_ARN = paste0( - '^arn:(aws).*:s3-outposts:[a-z\\-0-9]+:[0-9]{12}:outpost[/:]', - '[a-zA-Z0-9\\-]{1,63}[/:]accesspoint[/:][a-zA-Z0-9\\-]{1,63}$' +OUTPOST_ARN <- paste0( + "^arn:(aws).*:s3-outposts:[a-z\\-0-9]+:[0-9]{12}:outpost[/:]", + "[a-zA-Z0-9\\-]{1,63}[/:]accesspoint[/:][a-zA-Z0-9\\-]{1,63}$" ) VALID_S3_ARN <- paste(ACCESSPOINT_ARN, OUTPOST_ARN, sep = "|") @@ -499,26 +499,26 @@ handle_copy_source_param <- function(request) { quote_source_header <- function(source) { result <- strsplit(source, VERSION_ID_SUFFIX, fixed = T)[[1]] if (is.na(result[2])) { - return(paws_url_encoder(result[1], '-._~/')) + return(paws_url_encoder(result[1], "-._~/")) } else { - return(paste0(paws_url_encoder(result[1], '-._~/'), VERSION_ID_SUFFIX, result[2])) + return(paste0(paws_url_encoder(result[1], "-._~/"), VERSION_ID_SUFFIX, result[2])) } } quote_source_header_from_list <- function(source) { - if(is.null(bucket <- source[['Bucket']])) { - stopf('CopySource list is missing required parameter: Bucket') + if (is.null(bucket <- source[["Bucket"]])) { + stopf("CopySource list is missing required parameter: Bucket") } - if (is.null(key <- source[['Key']])) { - stopf('CopySource list is missing required parameter: Key') + if (is.null(key <- source[["Key"]])) { + stopf("CopySource list is missing required parameter: Key") } if (grepl(VALID_S3_ARN, bucket, perl = T)) { - final <- sprintf('%s/object/%s', bucket, key) + final <- sprintf("%s/object/%s", bucket, key) } else { - final <- sprintf('%s/%s', bucket, key) + final <- sprintf("%s/%s", bucket, key) } - final <- paws_url_encoder(final, '-._~/') - if (!is.null(version_id <- source[['VersionId']])) { + final <- paws_url_encoder(final, "-._~/") + if (!is.null(version_id <- source[["VersionId"]])) { final <- paste0(final, VERSION_ID_SUFFIX, version_id) } return(final) diff --git a/paws.common/R/error.R b/paws.common/R/error.R index 20f2c3732..e9a0c06bc 100644 --- a/paws.common/R/error.R +++ b/paws.common/R/error.R @@ -26,7 +26,7 @@ serialization_error <- function(request) { ) } -get_retry_info <- function(retry_count){ +get_retry_info <- function(retry_count) { if (retry_count) { retry_msg <- sprintf(" (reached max retries: %d)", retry_count) } else { diff --git a/paws.common/R/net.R b/paws.common/R/net.R index 255717253..2264688ea 100644 --- a/paws.common/R/net.R +++ b/paws.common/R/net.R @@ -154,7 +154,7 @@ issue <- function(http_request) { resp_body <- function(resp, path) { if (is.null(path)) { body <- httr::content(resp, as = "raw") - # return error message if call has failed or needs redirecting + # return error message if call has failed or needs redirecting } else if (resp$status_code %in% c(301, 400)) { body <- readBin(path, "raw", file.info(path)$size) unlink(path) diff --git a/paws.common/tests/testthat/test_custom_s3.R b/paws.common/tests/testthat/test_custom_s3.R index 8f9f83d55..ad495f5d2 100644 --- a/paws.common/tests/testthat/test_custom_s3.R +++ b/paws.common/tests/testthat/test_custom_s3.R @@ -411,16 +411,16 @@ build_copy_object_request <- function(bucket, key, copy_source, operation) { endpoints = list("*" = list(endpoint = "s3.amazonaws.com", global = FALSE)), service_name = "s3" ) - svc <- new_service(metadata, new_handlers("restxml", "s3")) - op <- new_operation( + svc <- new_service(metadata, new_handlers("restxml", "s3")) + op <- new_operation( name = operation, http_method = "GET", http_path = "/{Bucket}", paginator = list() ) - input <- tag_add(list(Bucket = bucket, Key = key, CopySource = copy_source), list(type = "structure")) + input <- tag_add(list(Bucket = bucket, Key = key, CopySource = copy_source), list(type = "structure")) output <- list() - request <- new_request(svc, op, input, output) + request <- new_request(svc, op, input, output) return(request) } @@ -505,4 +505,3 @@ test_that("check CopySource list missing params", { "CopySource list is missing required parameter: Key" ) }) - From 4428a6c1dafbca631b38d66e4caebfb9d4b1f00a Mon Sep 17 00:00:00 2001 From: "dyfan.jones" Date: Mon, 19 Aug 2024 13:33:11 +0100 Subject: [PATCH 3/8] add extra encoding checks --- paws.common/tests/testthat/test_custom_s3.R | 66 ++++++++++++++++----- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/paws.common/tests/testthat/test_custom_s3.R b/paws.common/tests/testthat/test_custom_s3.R index ad495f5d2..4746da1b8 100644 --- a/paws.common/tests/testthat/test_custom_s3.R +++ b/paws.common/tests/testthat/test_custom_s3.R @@ -406,14 +406,14 @@ test_that("redirect error without region", { }) -build_copy_object_request <- function(bucket, key, copy_source, operation) { +build_copy_object_request <- function(bucket, key, copy_source) { metadata <- list( endpoints = list("*" = list(endpoint = "s3.amazonaws.com", global = FALSE)), service_name = "s3" ) svc <- new_service(metadata, new_handlers("restxml", "s3")) op <- new_operation( - name = operation, + name = "CopyObject", http_method = "GET", http_path = "/{Bucket}", paginator = list() @@ -426,28 +426,49 @@ build_copy_object_request <- function(bucket, key, copy_source, operation) { test_that("check CopySource character encoded", { req <- build_copy_object_request( - bucket = "foo", - key = "file.txt", - copy_source = "/foo/%01file%/output.txt", - operation = "CopyObject" + bucket = "foo", key = "file.txt", copy_source = "/foo/%01file%/output.txt" ) req <- handle_copy_source_param(req) expect_equal(req$params$CopySource, "/foo/%2501file%25/output.txt") }) +test_that("check CopySource only quote url path not version id", { + req <- build_copy_object_request( + bucket = "foo", key = "file.txt", copy_source = "/foo/bar++baz?versionId=123" + ) + req <- handle_copy_source_param(req) + expect_equal(req$params$CopySource, "/foo/bar%2B%2Bbaz?versionId=123") +}) + +test_that("check CopySource only version id is special cased", { + req <- build_copy_object_request( + bucket = "foo", key = "file.txt", copy_source = "/foo/bar++baz?notVersion=foo+" + ) + req <- handle_copy_source_param(req) + expect_equal(req$params$CopySource, "/foo/bar%2B%2Bbaz%3FnotVersion%3Dfoo%2B") +}) + test_that("check CopySource character versionId encoded", { req <- build_copy_object_request( bucket = "foo", key = "file.txt", - copy_source = "/foo/%01file%/output.txt?versionId=123", - operation = "CopyObject" + copy_source = "/foo/%01file%/output.txt?versionId=123" ) req <- handle_copy_source_param(req) expect_equal(req$params$CopySource, "/foo/%2501file%25/output.txt?versionId=123") }) +test_that("check CopySource with multiple questions", { + req <- build_copy_object_request( + bucket = "foo", key = "file.txt", copy_source = "/foo/bar+baz?a=baz+?versionId=a+" + ) + req <- handle_copy_source_param(req) + expect_equal(req$params$CopySource, "/foo/bar%2Bbaz%3Fa%3Dbaz%2B?versionId=a+") +}) + + test_that("check CopySource list encoded", { req <- build_copy_object_request( bucket = "foo", @@ -455,8 +476,7 @@ test_that("check CopySource list encoded", { copy_source = list( Bucket = "foo", Key = "%01file%/output.txt" - ), - operation = "CopyObject" + ) ) req <- handle_copy_source_param(req) @@ -471,30 +491,44 @@ test_that("check CopySource list versionId encoded", { Bucket = "foo", Key = "%01file%/output.txt", VersionId = "123" - ), - operation = "CopyObject" + ) ) req <- handle_copy_source_param(req) expect_equal(req$params$CopySource, "foo/%2501file%25/output.txt?versionId=123") }) +test_that("check CopySource list bucket s3 access point", { + req <- build_copy_object_request( + bucket = "foo", + key = "file.txt", + copy_source = list( + Bucket = "arn:aws:s3:us-west-2:123456789012:accesspoint/test", + Key = "%01file%/output.txt" + ) + ) + + req <- handle_copy_source_param(req) + expect_equal( + req$params$CopySource, + "arn%3Aaws%3As3%3Aus-west-2%3A123456789012%3Aaccesspoint/test/object/%2501file%25/output.txt" + ) +}) + test_that("check CopySource list missing params", { req1 <- build_copy_object_request( bucket = "foo", key = "file.txt", copy_source = list( Key = "%01file%/output.txt" - ), - operation = "CopyObject" + ) ) req2 <- build_copy_object_request( bucket = "foo", key = "file.txt", copy_source = list( Bucket = "foo" - ), - operation = "CopyObject" + ) ) expect_error( handle_copy_source_param(req1), From e770f53553f8d94ab5ee1c6780076fc3663145b3 Mon Sep 17 00:00:00 2001 From: "dyfan.jones" Date: Mon, 19 Aug 2024 13:33:38 +0100 Subject: [PATCH 4/8] remove duplicate safe characters --- paws.common/R/custom_s3.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/paws.common/R/custom_s3.R b/paws.common/R/custom_s3.R index a71db983f..ce2ba831f 100644 --- a/paws.common/R/custom_s3.R +++ b/paws.common/R/custom_s3.R @@ -499,9 +499,9 @@ handle_copy_source_param <- function(request) { quote_source_header <- function(source) { result <- strsplit(source, VERSION_ID_SUFFIX, fixed = T)[[1]] if (is.na(result[2])) { - return(paws_url_encoder(result[1], "-._~/")) + return(paws_url_encoder(result[1], "/")) } else { - return(paste0(paws_url_encoder(result[1], "-._~/"), VERSION_ID_SUFFIX, result[2])) + return(paste0(paws_url_encoder(result[1], "/"), VERSION_ID_SUFFIX, result[2])) } } @@ -517,7 +517,7 @@ quote_source_header_from_list <- function(source) { } else { final <- sprintf("%s/%s", bucket, key) } - final <- paws_url_encoder(final, "-._~/") + final <- paws_url_encoder(final, "/") if (!is.null(version_id <- source[["VersionId"]])) { final <- paste0(final, VERSION_ID_SUFFIX, version_id) } From 01580585a2d83a1943bf0c82192a1d3b517faec9 Mon Sep 17 00:00:00 2001 From: "dyfan.jones" Date: Mon, 19 Aug 2024 13:38:39 +0100 Subject: [PATCH 5/8] simplify code --- paws.common/R/net.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paws.common/R/net.R b/paws.common/R/net.R index 2264688ea..82d0423a8 100644 --- a/paws.common/R/net.R +++ b/paws.common/R/net.R @@ -153,7 +153,7 @@ issue <- function(http_request) { resp_body <- function(resp, path) { if (is.null(path)) { - body <- httr::content(resp, as = "raw") + body <- resp$content # return error message if call has failed or needs redirecting } else if (resp$status_code %in% c(301, 400)) { body <- readBin(path, "raw", file.info(path)$size) From a97cafb88b0774f5535c028e9b0a9227379604f9 Mon Sep 17 00:00:00 2001 From: "dyfan.jones" Date: Mon, 19 Aug 2024 14:06:50 +0100 Subject: [PATCH 6/8] simplify code --- paws.common/R/signer_v4.R | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/paws.common/R/signer_v4.R b/paws.common/R/signer_v4.R index d8a078fde..0d41d0c42 100644 --- a/paws.common/R/signer_v4.R +++ b/paws.common/R/signer_v4.R @@ -141,9 +141,9 @@ sign_sdk_request_with_curr_time <- function(request, # set headers for anonymous credentials if (isTRUE(request$config$credentials$anonymous)) { - request$http_request$header <- anonymous_headers( - request$http_request$header - ) + # Clear down headers for anonymous credentials + # https://github.com/aws/aws-sdk-go/blob/a7b02935e4fefa40f175f4d2143ec9c88a5f90f5/aws/signer/v4/v4_test.go#L321-L355 + request$http_request$header["Authorization"] <- "" } return(request) @@ -462,10 +462,3 @@ get_uri_path <- function(url) { return(uri) } - -# Clear down headers for anonymous credentials -# https://github.com/aws/aws-sdk-go/blob/a7b02935e4fefa40f175f4d2143ec9c88a5f90f5/aws/signer/v4/v4_test.go#L321-L355 -anonymous_headers <- function(headers) { - headers["Authorization"] <- "" - return(headers) -} From 95f00a7422425f493fc8fbd5e61a26321faaa43a Mon Sep 17 00:00:00 2001 From: "dyfan.jones" Date: Mon, 19 Aug 2024 15:26:19 +0100 Subject: [PATCH 7/8] convert uuid function to cpp --- paws.common/NAMESPACE | 1 + paws.common/NEWS.md | 2 + paws.common/R/RcppExports.R | 6 ++ paws.common/R/idempotency.R | 19 +----- paws.common/R/queryutil.R | 3 +- paws.common/src/RcppExports.cpp | 12 ++++ paws.common/src/utils.cpp | 20 +++++++ paws.common/src/uuid.h | 58 +++++++++++++++++++ .../tests/testthat/test_handlers_ec2query.R | 6 +- .../tests/testthat/test_handlers_jsonrpc.R | 6 +- .../tests/testthat/test_handlers_query.R | 3 +- .../tests/testthat/test_handlers_restjson.R | 6 +- 12 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 paws.common/src/uuid.h diff --git a/paws.common/NAMESPACE b/paws.common/NAMESPACE index 71811d463..1a1a3cd4b 100644 --- a/paws.common/NAMESPACE +++ b/paws.common/NAMESPACE @@ -54,3 +54,4 @@ useDynLib(paws.common,"_paws_common_endpoint_unescape") useDynLib(paws.common,"_paws_common_get_region_pattern") useDynLib(paws.common,"_paws_common_json_convert_string") useDynLib(paws.common,"_paws_common_paws_url_encoder") +useDynLib(paws.common,"_paws_common_uuid_v4") diff --git a/paws.common/NEWS.md b/paws.common/NEWS.md index 4df361ac7..411ff7f81 100644 --- a/paws.common/NEWS.md +++ b/paws.common/NEWS.md @@ -35,6 +35,8 @@ client$copy_object( ) ``` +* convert `uuid` to `cpp` for performance improvement. + # paws.common 0.7.4 * fix `transpose` to correctly parse lists with empty first elements (#791), thanks to @FMKerckhof for raising issue. * support refreshable credentials for `sso` (#793) diff --git a/paws.common/R/RcppExports.R b/paws.common/R/RcppExports.R index 49c171a6d..b04ce109a 100644 --- a/paws.common/R/RcppExports.R +++ b/paws.common/R/RcppExports.R @@ -37,3 +37,9 @@ char_sort <- function(str) { .Call('_paws_common_char_sort', PACKAGE = 'paws.common', str) } +#' @useDynLib paws.common _paws_common_uuid_v4 +#' @importFrom Rcpp evalCpp +uuid_v4 <- function(n = 1L) { + .Call('_paws_common_uuid_v4', PACKAGE = 'paws.common', n) +} + diff --git a/paws.common/R/idempotency.R b/paws.common/R/idempotency.R index 424ec0f55..c0a06aebc 100644 --- a/paws.common/R/idempotency.R +++ b/paws.common/R/idempotency.R @@ -1,5 +1,6 @@ +#' @include RcppExports.R + IDEMPOTENCY_TOKEN_FILL_TAG <- "idempotencyToken" -IDEMPOTENCY_RAND_FN <- function(len) sample(0:(2^8 - 1), len, replace = TRUE) # Return whether the idempotency token can be automatically set. can_set_idempotency_token <- function(value) { @@ -8,19 +9,5 @@ can_set_idempotency_token <- function(value) { # Return a randomly-generated idempotency token. get_idempotency_token <- function() { - rand <- getOption("idempotency_rand_fn", default = IDEMPOTENCY_RAND_FN) - return(uuid(rand(16))) -} - -# Return a UUID version 4 based on the given `bytes`. -uuid <- function(bytes) { - bytes[7] <- bitwAnd(bitwOr(bytes[7], 0x40), 0x4F) - bytes[9] <- bitwAnd(bitwOr(bytes[9], 0x80), 0xBF) - h <- sprintf("%02X", bytes) - p <- function(x) paste(x, collapse = "") - u <- sprintf( - "%s-%s-%s-%s-%s", - p(h[1:4]), p(h[5:6]), p(h[7:8]), p(h[9:10]), p(h[11:16]) - ) - return(u) + return(uuid_v4(1)) } diff --git a/paws.common/R/queryutil.R b/paws.common/R/queryutil.R index 0af9262b6..5d8fb6e22 100644 --- a/paws.common/R/queryutil.R +++ b/paws.common/R/queryutil.R @@ -34,8 +34,7 @@ query_parse_structure <- function(values, value, prefix, tag, is_ec2 = FALSE) { } if (can_set_idempotency_token(field)) { - token <- get_idempotency_token() - field[[1]] <- token + field[[1]] <- get_idempotency_token() } name <- "" diff --git a/paws.common/src/RcppExports.cpp b/paws.common/src/RcppExports.cpp index c62721469..fbf9ce542 100644 --- a/paws.common/src/RcppExports.cpp +++ b/paws.common/src/RcppExports.cpp @@ -80,6 +80,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// uuid_v4 +CharacterVector uuid_v4(size_t n); +RcppExport SEXP _paws_common_uuid_v4(SEXP nSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< size_t >::type n(nSEXP); + rcpp_result_gen = Rcpp::wrap(uuid_v4(n)); + return rcpp_result_gen; +END_RCPP +} static const R_CallMethodDef CallEntries[] = { {"_paws_common_paws_url_encoder", (DL_FUNC) &_paws_common_paws_url_encoder, 2}, @@ -88,6 +99,7 @@ static const R_CallMethodDef CallEntries[] = { {"_paws_common_endpoint_unescape", (DL_FUNC) &_paws_common_endpoint_unescape, 3}, {"_paws_common_get_region_pattern", (DL_FUNC) &_paws_common_get_region_pattern, 2}, {"_paws_common_char_sort", (DL_FUNC) &_paws_common_char_sort, 1}, + {"_paws_common_uuid_v4", (DL_FUNC) &_paws_common_uuid_v4, 1}, {NULL, NULL, 0} }; diff --git a/paws.common/src/utils.cpp b/paws.common/src/utils.cpp index 295f3f53c..411ef9de9 100644 --- a/paws.common/src/utils.cpp +++ b/paws.common/src/utils.cpp @@ -1,4 +1,5 @@ #include +#include "uuid.h" using namespace Rcpp; // Sort character vector @@ -11,3 +12,22 @@ CharacterVector char_sort(CharacterVector str) { std::sort(idx.begin(), idx.end(), [&](int i, int j){return str[i] < str[j];}); return str[idx]; } + + +// Creates uuid v4 +// Developed from: https://github.com/rkg82/uuid-v4 +// param n A integer, number of uuid v4 to generate. +//' @useDynLib paws.common _paws_common_uuid_v4 +//' @importFrom Rcpp evalCpp +// [[Rcpp::export]] +CharacterVector uuid_v4(size_t n = 1) { + CharacterVector uuids(n); + + for (size_t i = 0; i < n; ++i) { + std::string s = uuid::v4::UUID::New().String(); + uuids[i] = s; + } + + return uuids; +} + diff --git a/paws.common/src/uuid.h b/paws.common/src/uuid.h new file mode 100644 index 000000000..df2b4d4c4 --- /dev/null +++ b/paws.common/src/uuid.h @@ -0,0 +1,58 @@ +#ifndef __UUID__ +#define __UUID__ + +#include +#include + +namespace uuid::v4 +{ +// Encaasulate the genaeration of a Version 4 UUID object +// A Version 4 UUID is a universally unique identifier that is generated using random numbers. +class UUID +{ +public: + // Factory method for creating UUID object. + static UUID New() + { + UUID uuid; + std::random_device rd; + std::mt19937 engine{rd()}; + std::uniform_int_distribution dist{0, 256}; //Limits of the interval + + for (int index = 0; index < 16; ++index) + { + uuid._data[index] = (unsigned char)dist(engine); + } + + uuid._data[6] = ((uuid._data[6] & 0x0f) | 0x40); // Version 4 + uuid._data[8] = ((uuid._data[8] & 0x3f) | 0x80); // Variant is 10 + + return uuid; + } + + // Returns UUID as formatted string + std::string String() + { + // Formats to "0065e7d7-418c-4da4-b4d6-b54b6cf7466a" + char buffer[256] = {0}; + std::snprintf(buffer, 255, + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + _data[0], _data[1], _data[2], _data[3], + _data[4], _data[5], + _data[6], _data[7], + _data[8], _data[9], + _data[10], _data[11], _data[12], _data[13], _data[14], _data[15]); + + std::string uuid = buffer; + + return uuid; + } + +private: + UUID() {} + + unsigned char _data[16] = {0}; +}; +}; + +#endif // #ifndef __UUID__ diff --git a/paws.common/tests/testthat/test_handlers_ec2query.R b/paws.common/tests/testthat/test_handlers_ec2query.R index 29ff23630..d4d6e57a9 100644 --- a/paws.common/tests/testthat/test_handlers_ec2query.R +++ b/paws.common/tests/testthat/test_handlers_ec2query.R @@ -6,9 +6,7 @@ op <- Operation(name = "OperationName") svc <- Client() svc$client_info$api_version <- "2014-01-01" svc$handlers$build <- HandlerList(ec2query_build) -options(idempotency_rand_fn = function(len) { - rep(0, len) -}) +UUID_V4_PATTERN <- "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" op_input1 <- function(Foo = NULL, Bar = NULL, Yuck = NULL) { args <- list(Foo = Foo, Bar = Bar, Yuck = Yuck) @@ -187,7 +185,7 @@ test_that("build idempotency token", { input <- op_input9() req <- new_request(svc, op, input, NULL) req <- build(req) - expect_equal(req$body, "Action=OperationName&Token=00000000-0000-4000-8000-000000000000&Version=2014-01-01") + expect_true(grepl(sprintf("Action=OperationName&Token=%s&Version=2014-01-01", UUID_V4_PATTERN), req$body)) }) op_input10 <- function(ListEnums = NULL) { diff --git a/paws.common/tests/testthat/test_handlers_jsonrpc.R b/paws.common/tests/testthat/test_handlers_jsonrpc.R index d1793cffe..c6a11c499 100644 --- a/paws.common/tests/testthat/test_handlers_jsonrpc.R +++ b/paws.common/tests/testthat/test_handlers_jsonrpc.R @@ -10,9 +10,7 @@ svc <- Client( ) ) svc$handlers$build <- HandlerList(jsonrpc_build) -options(idempotency_rand_fn = function(len) { - rep(0, len) -}) +UUID_V4_PATTERN <- "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" op_input1 <- function(Name) { args <- list(Name = Name) @@ -308,7 +306,7 @@ test_that("build idempotency token", { input <- op_input12() req <- new_request(svc, op, input, NULL) req <- build(req) - expect_equal(req$body, '{"Token":"00000000-0000-4000-8000-000000000000"}') + expect_true(grepl(sprintf('\\{"Token":"%s"\\}', UUID_V4_PATTERN), req$body)) }) op_input13 <- function(FooEnum, ListEnums) { diff --git a/paws.common/tests/testthat/test_handlers_query.R b/paws.common/tests/testthat/test_handlers_query.R index e68426ac9..c722f2376 100644 --- a/paws.common/tests/testthat/test_handlers_query.R +++ b/paws.common/tests/testthat/test_handlers_query.R @@ -6,6 +6,7 @@ op <- Operation(name = "OperationName") svc <- Client() svc$client_info$api_version <- "2014-01-01" svc$handlers$build <- HandlerList(query_build) +UUID_V4_PATTERN <- "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" op_input1 <- function(Foo = NULL, Bar = NULL, Baz = NULL) { args <- list(Foo = Foo, Bar = Bar, Baz = Baz) @@ -360,7 +361,7 @@ test_that("build idempotency token auto-fill", { input <- op_input14() req <- new_request(svc, op, input, NULL) req <- build(req) - expect_equal(req$body, "Action=OperationName&Token=00000000-0000-4000-8000-000000000000&Version=2014-01-01") + expect_true(grepl(sprintf("Action=OperationName&Token=%s&Version=2014-01-01", UUID_V4_PATTERN), req$body)) }) op_input15 <- function(FooEnum = NULL, ListEnums = NULL) { diff --git a/paws.common/tests/testthat/test_handlers_restjson.R b/paws.common/tests/testthat/test_handlers_restjson.R index 3386e9fe4..2f88e2196 100644 --- a/paws.common/tests/testthat/test_handlers_restjson.R +++ b/paws.common/tests/testthat/test_handlers_restjson.R @@ -8,9 +8,7 @@ svc <- Client( ) ) svc$handlers$build <- HandlerList(restjson_build) -options(idempotency_rand_fn = function(len) { - rep(0, len) -}) +UUID_V4_PATTERN <- "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" test_that("no parameters", { op1 <- Operation( @@ -583,7 +581,7 @@ test_that("auto-fill idempotency token", { req <- build(req) r <- req$http_request expect_equal(build_url(r$url), "https://test/path") - expect_equal(r$body, '{"Token":"00000000-0000-4000-8000-000000000000"}') + expect_true(grepl(sprintf('\\{"Token":"%s"\\}', UUID_V4_PATTERN), r$body)) }) # TODO: JSON value traits. From 12272f517da0e4e4350b4bfcc7b3a3c5a65a02ef Mon Sep 17 00:00:00 2001 From: DyfanJones Date: Mon, 19 Aug 2024 15:15:03 +0000 Subject: [PATCH 8/8] Style --- make.paws/R/sdk_helper.R | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/make.paws/R/sdk_helper.R b/make.paws/R/sdk_helper.R index 5cee24c1e..0ceacb2e6 100644 --- a/make.paws/R/sdk_helper.R +++ b/make.paws/R/sdk_helper.R @@ -128,7 +128,7 @@ paws_check_rhub_sub_cat <- function(in_dir = "../cran", #' @rdname paws_check_rhub #' @export -paws_rhub_action_check <- function (packages = "paws", platforms = c("linux", "macos", "macos-arm64", "windows")) { +paws_rhub_action_check <- function(packages = "paws", platforms = c("linux", "macos", "macos-arm64", "windows")) { url <- "https://api.github.com/repos/paws-r/paws-rhub/actions/workflows/rhub.yaml/dispatches" pat <- gitcreds::gitcreds_get(url = "https://github.com/paws-r/paws-rhub")$password config <- list(platforms = platforms) @@ -143,10 +143,11 @@ paws_rhub_action_check <- function (packages = "paws", platforms = c("linux", "m httr2::req_method("POST") }) |> httr2::req_perform_parallel() names(resps) <- unlist(packages) - + for (pkg in names(resps)) { - if (resps[[pkg]]$status_code != 204) + if (resps[[pkg]]$status_code != 204) { stop(sprintf("Failed to start rhub action for package: %s", pkg)) + } } writeLines("Please check results: https://github.com/paws-r/paws-rhub/actions") invisible(NULL)