#include #include #include "cpp11/doubles.hpp" #include "cpp11/sexp.hpp" context("doubles-C++") { test_that("doubles::vector()") { cpp11::doubles x(Rf_allocVector(REALSXP, 2)); expect_true(x.size() == 2); expect_error(cpp11::doubles(Rf_allocVector(INTSXP, 2))); } test_that("doubles.push_back()") { cpp11::writable::doubles x; x.push_back(1); x.push_back(2); expect_true(x.size() == 2); expect_true(x[0] == 1); expect_true(x[1] == 2); } test_that("doubles.resize()") { cpp11::writable::doubles x; x.resize(2); x[0] = 1; x[1] = 2; expect_true(x.size() == 2); expect_true(x[0] == 1); expect_true(x[1] == 2); } test_that("doubles.at()") { cpp11::writable::doubles x; expect_error(x.at(-1)); expect_error(x.at(0)); x.push_back(1); expect_true(x.at(0) == 1); expect_error(x.at(1)); } test_that("doubles.pop_back()") { cpp11::writable::doubles x; x.push_back(1); x.push_back(2); x.pop_back(); expect_true(x.size() == 1); expect_true(x[0] == 1); expect_error(x.at(1)); } test_that("doubles.insert()") { cpp11::writable::doubles x; x.insert(0, 1); x.insert(0, 2); x.insert(1, 3); expect_true(x.size() == 3); expect_true(x[0] == 2); expect_true(x[1] == 3); expect_true(x[2] == 1); } test_that("doubles.erase()") { cpp11::writable::doubles x; x.push_back(1); x.push_back(2); x.push_back(3); x.push_back(4); x.push_back(5); expect_true(x.size() == 5); x.erase(0); expect_true(x.size() == 4); expect_true(x[0] == 2); expect_true(x[1] == 3); expect_true(x[2] == 4); expect_true(x[3] == 5); x.erase(2); expect_true(x.size() == 3); expect_true(x[0] == 2); expect_true(x[1] == 3); expect_true(x[2] == 5); } test_that("doubles.iterator* = ") { cpp11::writable::doubles x; x.push_back(1); x.push_back(2); x.push_back(3); auto it = x.begin() + 1; *it = 3; ++it; *it = 4; expect_true(x.size() == 3); expect_true(x[0] == 1); expect_true(x[1] == 3); expect_true(x[2] == 4); } test_that("writable::doubles(SEXP)") { SEXP x = PROTECT(Rf_allocVector(REALSXP, 5)); REAL(x)[0] = 1; REAL(x)[1] = 2; REAL(x)[2] = 3; REAL(x)[3] = 4; REAL(x)[4] = 5; cpp11::writable::doubles y(x); y[0] = -1; expect_true(x != y.data()); expect_true(REAL(x)[0] == 1); expect_true(y[0] == -1); cpp11::writable::doubles z(y); z[0] = -2; expect_true(z.data() != y.data()); expect_true(REAL(x)[0] == 1); expect_true(y[0] == -1); expect_true(z[0] == -2); UNPROTECT(1); } #if defined(__APPLE__) && defined(R_VERSION) && R_VERSION >= R_Version(3, 5, 0) test_that("writable::doubles(ALTREP_SEXP)") { SEXP x = PROTECT(Rf_coerceVector(R_compact_intrange(1, 5), REALSXP)); // Need to find (or create) an altrep class that implements duplicate. cpp11::writable::doubles y(x); y[0] = -1; expect_true(x != y.data()); expect_true(REAL_ELT(x, 0) == 1); expect_true(y[0] == -1); cpp11::writable::doubles z(y); z[0] = -2; expect_true(z.data() != y.data()); expect_true(REAL_ELT(x, 0) == 1); expect_true(y[0] == -1); expect_true(z[0] == -2); z.push_back(6); expect_true(z[5] == 6); UNPROTECT(1); } test_that("writable::doubles(SEXP) assignment") { cpp11::writable::doubles x({1., 2., 3.}); cpp11::writable::doubles y({0.}); y = x; expect_true(y.size() == 3); expect_true(y.data() != x.data()); expect_true(y.is_altrep() == x.is_altrep()); cpp11::writable::doubles z( Rf_coerceVector(R_compact_intrange(1, 5), REALSXP)); cpp11::writable::doubles w({0.}); w = z; expect_true(w.size() == 5); expect_true(w.data() != z.data()); expect_true(w.is_altrep() == z.is_altrep()); } test_that("writable::doubles(SEXP) move assignment") { cpp11::writable::doubles x({1., 2., 3.}); cpp11::writable::doubles y({0.}); auto x_data = x.data(); y = std::move(x); expect_true(y.size() == 3); expect_true(y.data() == x_data); expect_true(y.is_altrep() == false); cpp11::writable::doubles z( Rf_coerceVector(R_compact_intrange(1, 5), REALSXP)); cpp11::writable::doubles w({0.}); expect_true(z.is_altrep() == true); auto z_data = z.data(); w = std::move(z); expect_true(w.size() == 5); expect_true(w.data() == z_data); expect_true(w.is_altrep() == true); } #endif test_that("doubles::names") { using namespace cpp11::literals; cpp11::writable::doubles x({"a"_nm = 1., "b"_nm = 2.}); expect_true(x[0] == 1.); expect_true(x[1] == 2.); expect_true(x["a"] == 1.); expect_true(x["b"] == 2.); cpp11::sexp nms(x.names()); expect_true(Rf_xlength(nms) == 2); auto nms0 = CHAR(STRING_ELT(nms, 0)); auto nms1 = CHAR(STRING_ELT(nms, 1)); expect_true(strcmp(nms0, "a") == 0); expect_true(strcmp(nms1, "b") == 0); } test_that("doubles::attr") { cpp11::doubles x(PROTECT(Rf_allocVector(REALSXP, 2))); REAL(x)[0] = 1; REAL(x)[1] = 2; SEXP foo = Rf_install("foo"); Rf_setAttrib(x, foo, Rf_mkString("bar")); // This doesn't compile by design // x.attr("foo") = "bar"; // But this will cpp11::writable::doubles y(x); y.attr("foo") = "baz"; expect_true(strcmp(CHAR(STRING_ELT(x.attr("foo"), 0)), "bar") == 0); expect_true(strcmp(CHAR(STRING_ELT(y.attr("foo"), 0)), "baz") == 0); UNPROTECT(1); } test_that("writable::doubles(std::vector::iterator)") { std::vector x({1, 2, 3, 4, 5}); cpp11::writable::doubles y(x.begin(), x.end()); expect_true(y.size() == 5); expect_true(y[0] == 1); expect_true(y[4] == 5); } test_that("writable::doubles(std::vector)") { std::vector x({1, 2, 3, 4, 5}); cpp11::writable::doubles y(x); expect_true(y.size() == 5); expect_true(y[0] == 1); expect_true(y[4] == 5); } }