Skip to content

Commit 27a072f

Browse files
Pr/1183 (#1185)
* add signature attribute * roll minor version in config.h (to match DESCRIPTION) * disable codecov comments on PRs, lower threshold, increase delta * add checks for proper syntax of signature attribute * add checks for proper syntax of signature attribute * adding tinytest for rcpp attributes * add checks for proper syntax of signature attribute * add checks for proper syntax of signature attribute * adding tinytest for rcpp attributes * cleanup and rebase for signature attribute pr * cleanup and rebase for signature attribute pr * cleanup and rebase for signature attribute pr * cleanup and rebase for signature attribute pr Co-authored-by: Dirk Eddelbuettel <[email protected]>
1 parent fbbc7df commit 27a072f

File tree

6 files changed

+358
-12
lines changed

6 files changed

+358
-12
lines changed

ChangeLog

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
* .codecov.yml (comment): Disable codecov comments on PRs
1313

14-
2021-10-10 Travers Ching
14+
2021-10-10 Travers Ching <[email protected]>
1515

16-
* Added `signature` attribute to attributes.cpp
16+
* src/attributes.cpp: Add `signature` attribute and syntax checks
17+
* inst/tinytest/testRcppAttributePackage: Tests `signature` attribute
18+
* inst/tinytest/test_attribute_package.R: Tests `signature` attribute
1719

1820
2021-10-02 Dirk Eddelbuettel <[email protected]>
1921

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Package: testRcppAttributePackage
2+
Type: Package
3+
Title: Tests the signature attribute and other attributes in package compilation
4+
Version: 1.0
5+
Date: 2021-10-09
6+
Author: Travers Ching
7+
Maintainer: Dirk Eddelbuettel <[email protected]>
8+
Description: Small test package part of Rcpp unit tests
9+
License: GPL (>= 2)
10+
Imports: Rcpp (>= 1.0.7)
11+
LinkingTo: Rcpp
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
useDynLib(testRcppAttributePackage, .registration=TRUE)
2+
importFrom(Rcpp, evalCpp)
3+
exportPattern("^[[:alpha:]]+")
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include <Rcpp.h>
2+
using namespace Rcpp;
3+
4+
// [[Rcpp::interfaces(r, cpp)]]
5+
6+
// [[Rcpp::export]]
7+
List test_no_attributes(List x, bool verbose) {
8+
if(x.size() > 0) {
9+
CharacterVector first_element = x[0];
10+
return List::create(first_element, verbose);
11+
} else {
12+
return List::create(verbose);
13+
}
14+
}
15+
16+
// [[Rcpp::export( signature = {x = list("{A}", "B"), verbose = getOption("verbose")} )]]
17+
List test_signature(List x, bool verbose) {
18+
if(x.size() > 0) {
19+
CharacterVector first_element = x[0];
20+
return List::create(first_element, verbose);
21+
} else {
22+
return List::create(verbose);
23+
}
24+
}
25+
26+
// [[Rcpp::export( rng = false, signature = {x = list("{A}", "B"), verbose = getOption("verbose")}, invisible = true )]]
27+
List test_rng_false_signature_invisible_true(List x, bool verbose) {
28+
if(x.size() > 0) {
29+
CharacterVector first_element = x[0];
30+
return List::create(first_element, verbose);
31+
} else {
32+
return List::create(verbose);
33+
}
34+
}
35+
36+
// [[Rcpp::export( rng = false )]]
37+
List test_rng_false(List x, bool verbose) {
38+
if(x.size() > 0) {
39+
CharacterVector first_element = x[0];
40+
return List::create(first_element, verbose);
41+
} else {
42+
return List::create(verbose);
43+
}
44+
}
45+
46+
// [[Rcpp::export( rng = true )]]
47+
List test_rng_true(List x, bool verbose) {
48+
if(x.size() > 0) {
49+
CharacterVector first_element = x[0];
50+
return List::create(first_element, verbose);
51+
} else {
52+
return List::create(verbose);
53+
}
54+
}
55+
56+
// [[Rcpp::export( signature = {x = list("{A}", "B"), verbose = getOption("verbose")}, rng = true )]]
57+
List test_rng_true_signature(List x, bool verbose) {
58+
if(x.size() > 0) {
59+
CharacterVector first_element = x[0];
60+
return List::create(first_element, verbose);
61+
} else {
62+
return List::create(verbose);
63+
}
64+
}
65+
66+
67+
// [[Rcpp::export( invisible = true, rng = true )]]
68+
List test_invisible_true_rng_true(List x, bool verbose) {
69+
if(x.size() > 0) {
70+
CharacterVector first_element = x[0];
71+
return List::create(first_element, verbose);
72+
} else {
73+
return List::create(verbose);
74+
}
75+
}
76+
77+
// [[Rcpp::export( invisible = true )]]
78+
List test_invisible_true(List x, bool verbose) {
79+
if(x.size() > 0) {
80+
CharacterVector first_element = x[0];
81+
return List::create(first_element, verbose);
82+
} else {
83+
return List::create(verbose);
84+
}
85+
}
86+
87+
// [[Rcpp::export( invisible = true, signature = {x = list("{A}", "B"), verbose = getOption("verbose")} )]]
88+
List test_invisible_true_signature(List x, bool verbose) {
89+
if(x.size() > 0) {
90+
CharacterVector first_element = x[0];
91+
return List::create(first_element, verbose);
92+
} else {
93+
return List::create(verbose);
94+
}
95+
}
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
## Copyright (C) 2010 - 2020 Dirk Eddelbuettel and Romain Francois
2+
## Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and Travers Ching
3+
##
4+
## This file is part of Rcpp.
5+
##
6+
## Rcpp is free software: you can redistribute it and/or modify it
7+
## under the terms of the GNU General Public License as published by
8+
## the Free Software Foundation, either version 2 of the License, or
9+
## (at your option) any later version.
10+
##
11+
## Rcpp is distributed in the hope that it will be useful, but
12+
## WITHOUT ANY WARRANTY; without even the implied warranty of
13+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
## GNU General Public License for more details.
15+
##
16+
## You should have received a copy of the GNU General Public License
17+
## along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
18+
19+
.runThisTest <- Sys.getenv("RunAllRcppTests") == "yes" && Sys.getenv("RunVerboseRcppTests") == "yes"
20+
21+
if (! .runThisTest) exit_file("Set 'RunVerboseRcppTests' and 'RunAllRcppTests' to 'yes' to run.")
22+
23+
td <- tempfile()
24+
cwd <- getwd()
25+
dir.create(td)
26+
pkg <- "testRcppAttributePackage"
27+
file.copy(pkg, td, recursive = TRUE) # simpler direct path thanks to tinytest
28+
setwd(td)
29+
on.exit( { setwd(cwd); unlink(td, recursive = TRUE) } )
30+
R <- shQuote(file.path( R.home(component = "bin"), "R"))
31+
Rcpp::compileAttributes(pkg)
32+
cmd <- paste(R, "CMD build", pkg)
33+
invisible(system(cmd, intern=TRUE))
34+
dir.create("templib")
35+
pkgfile <- paste0(pkg, "_1.0.tar.gz")
36+
install.packages(pkgfile, "templib", repos = NULL, type = "source")
37+
require(pkg, lib.loc = "templib", character.only = TRUE)
38+
39+
# Test Package
40+
options(verbose=TRUE)
41+
expect_equal(test_no_attributes(list("{A}"), FALSE),list("{A}", FALSE))
42+
expect_equal(test_signature(),list("{A}", TRUE))
43+
expect_equal(test_rng_false_signature_invisible_true(),list("{A}", TRUE))
44+
expect_equal(test_rng_false(list("{A}"), FALSE),list("{A}", FALSE))
45+
expect_equal(test_rng_true(list("{A}"), FALSE),list("{A}", FALSE))
46+
expect_equal(test_rng_true_signature(),list("{A}", TRUE))
47+
expect_equal(test_invisible_true_rng_true(list("{A}"), FALSE),list("{A}", FALSE))
48+
expect_equal(test_invisible_true(list("{A}"), FALSE),list("{A}", FALSE))
49+
expect_equal(test_invisible_true_signature(),list("{A}", TRUE))
50+
options(verbose=FALSE)
51+
52+
# Test inline
53+
54+
# test 0
55+
# This example should just run and not crash
56+
Rcpp::sourceCpp(code='
57+
#include <Rcpp.h>
58+
using namespace Rcpp;
59+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B"), verbose = getOption("verbose")}, invisible = TRUE )]]
60+
List test_inline(List x, bool verbose) {
61+
if(x.size() > 0) {
62+
CharacterVector first_element = x[0];
63+
return List::create(first_element, verbose);
64+
} else {
65+
return List::create(verbose);
66+
}
67+
}')
68+
expect_equal(test_inline(), list("{A}", FALSE))
69+
options(verbose=TRUE)
70+
expect_equal(test_inline(), list("{A}", TRUE))
71+
options(verbose=FALSE)
72+
73+
# test 1, from Enchufa2
74+
# The verbose argument should be replaced with FALSE
75+
Rcpp::sourceCpp(code='
76+
#include <Rcpp.h>
77+
using namespace Rcpp;
78+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B"), verbose=FALSE} )]]
79+
List test_inline(List x, bool verbose=true) {
80+
if(x.size() > 0) {
81+
CharacterVector first_element = x[0];
82+
return List::create(first_element, verbose);
83+
} else {
84+
return List::create(verbose);
85+
}
86+
}')
87+
expect_equal(test_inline(), list("{A}", FALSE))
88+
89+
# test 2, from Enchufa2
90+
# This second example should not compile because of missing parameter verbose
91+
expect_error({
92+
Rcpp::sourceCpp(code='
93+
#include <Rcpp.h>
94+
using namespace Rcpp;
95+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B")} )]]
96+
List test_inline(List x, bool verbose=true) {
97+
if(x.size() > 0) {
98+
CharacterVector first_element = x[0];
99+
return List::create(first_element, verbose);
100+
} else {
101+
return List::create(verbose);
102+
}
103+
}')
104+
})
105+
106+
# test 3, from Enchufa2
107+
# This third example should not compile because of missing end bracket }
108+
# The bracket within the signature is taken as the end bracket, which results in
109+
# invalid R code. There are some additional warnings due to the incorrect syntax
110+
expect_warning({
111+
expect_error({
112+
Rcpp::sourceCpp(code='
113+
#include <Rcpp.h>
114+
using namespace Rcpp;
115+
// [[Rcpp::export( rng = false, signature = {x=list("{A}", "B"), verbose=FALSE )]]
116+
List test_inline(List x, bool verbose) {
117+
if(x.size() > 0) {
118+
CharacterVector first_element = x[0];
119+
return List::create(first_element, verbose);
120+
} else {
121+
return List::create(verbose);
122+
}
123+
}', verbose=T)
124+
})
125+
})
126+
127+
# test 4, from Enchufa2
128+
# This 4th example is missing the end bracket and will not compile
129+
expect_error({
130+
Rcpp::sourceCpp(code='
131+
#include <Rcpp.h>
132+
using namespace Rcpp;
133+
// [[Rcpp::export( rng = false, signature = {x=list("A", "B"), verbose=FALSE )]]
134+
List test_inline(List x, bool verbose) {
135+
if(x.size() > 0) {
136+
CharacterVector first_element = x[0];
137+
return List::create(first_element, verbose);
138+
} else {
139+
return List::create(verbose);
140+
}
141+
}')
142+
})
143+
144+
# This 5th example has brackets but incorrect R syntax
145+
expect_error({
146+
Rcpp::sourceCpp(code='
147+
#include <Rcpp.h>
148+
using namespace Rcpp;
149+
// [[Rcpp::export( rng = false, signature = {x=list("A", ###, verbose=FALSE} )]]
150+
List test_inline(List x, bool verbose) {
151+
if(x.size() > 0) {
152+
CharacterVector first_element = x[0];
153+
return List::create(first_element, verbose);
154+
} else {
155+
return List::create(verbose);
156+
}
157+
}')
158+
})
159+
160+
# This 6th example is missing a parameter in the signature
161+
expect_error({
162+
Rcpp::sourceCpp(code='
163+
#include <Rcpp.h>
164+
using namespace Rcpp;
165+
// [[Rcpp::export( rng = false, signature = {x=list("A", "B")} )]]
166+
List test_inline(List x, bool verbose) {
167+
if(x.size() > 0) {
168+
CharacterVector first_element = x[0];
169+
return List::create(first_element, verbose);
170+
} else {
171+
return List::create(verbose);
172+
}
173+
}')
174+
})
175+
176+
177+
remove.packages(pkg, lib="templib")
178+
unlink("templib", recursive = TRUE)
179+
setwd(cwd)
180+
unlink(pkgfile)

0 commit comments

Comments
 (0)