mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-01 02:41:48 +00:00
Compare commits
309 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02336fc478 | ||
|
|
c00848c060 | ||
|
|
738a1c015c | ||
|
|
48ae6c954a | ||
|
|
07f70cf784 | ||
|
|
e4e1eab413 | ||
|
|
0e8ff4663d | ||
|
|
54a0a7654a | ||
|
|
59f938b584 | ||
|
|
5513888457 | ||
|
|
02b6615042 | ||
|
|
1f4822f332 | ||
|
|
bb38ef5642 | ||
|
|
ca36d1dce6 | ||
|
|
ee33296e1f | ||
|
|
0ef9803363 | ||
|
|
eedb8910c3 | ||
|
|
8346caed9c | ||
|
|
55b6764d50 | ||
|
|
2c4faee667 | ||
|
|
8d1dee16be | ||
|
|
76b182600a | ||
|
|
c647a801ad | ||
|
|
02131639bc | ||
|
|
566e283694 | ||
|
|
40eb6dfc9b | ||
|
|
a3e5378d14 | ||
|
|
691741cfcb | ||
|
|
166d9e01bf | ||
|
|
7eab4371f4 | ||
|
|
de134a5c60 | ||
|
|
7f074563d0 | ||
|
|
d3dd586362 | ||
|
|
9c85105591 | ||
|
|
86ac70a125 | ||
|
|
3c3a448d47 | ||
|
|
8744511f1d | ||
|
|
7729dd972f | ||
|
|
8b7aa61091 | ||
|
|
88a6b4ac38 | ||
|
|
217b1a2259 | ||
|
|
d2e7a90f41 | ||
|
|
8bd48d6c34 | ||
|
|
1fa0adb091 | ||
|
|
f615e68a43 | ||
|
|
aa4f0ef4f8 | ||
|
|
b42285fddd | ||
|
|
8106fbdbea | ||
|
|
942ba51765 | ||
|
|
33a08d5b34 | ||
|
|
4e3af0756d | ||
|
|
5078f6c92a | ||
|
|
899892c119 | ||
|
|
54326311ad | ||
|
|
fe53dd2f28 | ||
|
|
ab137abab5 | ||
|
|
001dedf3b2 | ||
|
|
f9bece2ffb | ||
|
|
3befc7015b | ||
|
|
de63e1c8a1 | ||
|
|
a76b1aa800 | ||
|
|
350b741adc | ||
|
|
64bfdc1a69 | ||
|
|
65cc85f68d | ||
|
|
6a00dc7976 | ||
|
|
e9e407a87d | ||
|
|
59c4984ed6 | ||
|
|
b428d1e4b3 | ||
|
|
0994364591 | ||
|
|
0b8d3f0260 | ||
|
|
52eba45c51 | ||
|
|
9090a82ef5 | ||
|
|
2a69a4c7dc | ||
|
|
9d2393f97e | ||
|
|
dae619b006 | ||
|
|
9c06d2878b | ||
|
|
e3a2abdf97 | ||
|
|
7867e906e9 | ||
|
|
65a044f633 | ||
|
|
cbd08a1e11 | ||
|
|
e308dd28f3 | ||
|
|
fa0b4428e9 | ||
|
|
26a36779a6 | ||
|
|
dfc0656e5c | ||
|
|
0f3f5218ad | ||
|
|
34c44b7ae9 | ||
|
|
7a250a1b93 | ||
|
|
a338ee8be0 | ||
|
|
c9d440f338 | ||
|
|
a00b2449db | ||
|
|
5c659fdcdf | ||
|
|
d36d72bd4f | ||
|
|
614093c0c4 | ||
|
|
12c4418bda | ||
|
|
0431cf97ff | ||
|
|
ba879f4663 | ||
|
|
96de0b5b11 | ||
|
|
85157a56c3 | ||
|
|
029246ed28 | ||
|
|
6377ab774d | ||
|
|
05e581f409 | ||
|
|
c73dd807e1 | ||
|
|
7a0dd9baa9 | ||
|
|
11f37683c3 | ||
|
|
5af0c9c101 | ||
|
|
259461aee9 | ||
|
|
d214b36786 | ||
|
|
4a07f0380f | ||
|
|
7f46b50b21 | ||
|
|
303c259b89 | ||
|
|
cd1dbb1e3a | ||
|
|
a20474bfc7 | ||
|
|
479d0beb5a | ||
|
|
b93aa176d6 | ||
|
|
9021b37fd2 | ||
|
|
6307d41002 | ||
|
|
df7c1389de | ||
|
|
6accc31ee7 | ||
|
|
f56ec10bcf | ||
|
|
e5e6d6a193 | ||
|
|
c663d7cd16 | ||
|
|
1e8d18b328 | ||
|
|
c2d95db3ab | ||
|
|
dd7563376b | ||
|
|
14fcf3f2f0 | ||
|
|
020ee227d2 | ||
|
|
4d559f3856 | ||
|
|
35d68d2a34 | ||
|
|
7007725d9f | ||
|
|
0c83cad70c | ||
|
|
0001047b8b | ||
|
|
c885251367 | ||
|
|
42096fac3f | ||
|
|
6be9e69d13 | ||
|
|
7bbd13d914 | ||
|
|
2225c4fee2 | ||
|
|
7efab4c43a | ||
|
|
c8e44256ef | ||
|
|
f3cd883c5c | ||
|
|
f34c736fb2 | ||
|
|
1276489961 | ||
|
|
8b2e656bde | ||
|
|
6e9d1f55c6 | ||
|
|
f4dce9e608 | ||
|
|
b9aabc71b0 | ||
|
|
0d54772362 | ||
|
|
faf134a674 | ||
|
|
c24e755409 | ||
|
|
bee9f1cb17 | ||
|
|
45d48d6b5a | ||
|
|
6401aa1fde | ||
|
|
6af4940c22 | ||
|
|
237b2df82f | ||
|
|
a70687aaec | ||
|
|
fbfe85568b | ||
|
|
595b1df380 | ||
|
|
efc7770e9b | ||
|
|
21585f70a8 | ||
|
|
c33fca34e9 | ||
|
|
de95f08a10 | ||
|
|
90f99dc571 | ||
|
|
f34332643a | ||
|
|
4ab095e9c9 | ||
|
|
541753c814 | ||
|
|
f02bb058bd | ||
|
|
12e96c6f13 | ||
|
|
b65447b6f5 | ||
|
|
9945a5b3c6 | ||
|
|
ce4c9edd1f | ||
|
|
a6e6ae41b9 | ||
|
|
f4e2e41aaf | ||
|
|
1e528669ff | ||
|
|
a1ea448406 | ||
|
|
9dc1de1d09 | ||
|
|
0521d85048 | ||
|
|
3c842d8234 | ||
|
|
be77f9cb26 | ||
|
|
2fc60680f4 | ||
|
|
0291a95f68 | ||
|
|
66002d6cac | ||
|
|
a7e9ac1062 | ||
|
|
434d60592c | ||
|
|
ee20747255 | ||
|
|
f4779379c3 | ||
|
|
877a9eae1f | ||
|
|
24752a9751 | ||
|
|
e1dc099517 | ||
|
|
f0cc623241 | ||
|
|
ba3a85d0cc | ||
|
|
79919a5f1c | ||
|
|
94ea5bfb06 | ||
|
|
24680bbd53 | ||
|
|
7fab0e0ef2 | ||
|
|
dd66b23845 | ||
|
|
19addb04cf | ||
|
|
abb66d3e4b | ||
|
|
db4981f166 | ||
|
|
6e1be897de | ||
|
|
423d8f6860 | ||
|
|
eb38204d1a | ||
|
|
1711291cd8 | ||
|
|
57ba58917d | ||
|
|
2249a8bac0 | ||
|
|
c572e6a307 | ||
|
|
e444b6015c | ||
|
|
38dbed8e09 | ||
|
|
34c18ef000 | ||
|
|
0d4fde17e0 | ||
|
|
040a8c6bcc | ||
|
|
4e80570c4c | ||
|
|
91529cc435 | ||
|
|
ef3267833f | ||
|
|
a5ef50c9e7 | ||
|
|
6eee457898 | ||
|
|
fb6d7b3470 | ||
|
|
2d78fdabb8 | ||
|
|
94c31ceeb1 | ||
|
|
67d4da51ee | ||
|
|
6e4f66cc8b | ||
|
|
a4e781a231 | ||
|
|
f151892db5 | ||
|
|
c45fb73f36 | ||
|
|
848280d1f1 | ||
|
|
f7016b359f | ||
|
|
be58a279a5 | ||
|
|
909e6c4857 | ||
|
|
5c0b08f4f5 | ||
|
|
05d1cfa276 | ||
|
|
ae675ae4e1 | ||
|
|
d3b636d073 | ||
|
|
8b460f5944 | ||
|
|
bdfa32876b | ||
|
|
4a3472ebb2 | ||
|
|
9c804c1351 | ||
|
|
2a9c454baa | ||
|
|
1a9a6c3678 | ||
|
|
e1195e8b9d | ||
|
|
50ed55e8e2 | ||
|
|
d682295ccd | ||
|
|
5e19c1881f | ||
|
|
617ff52f18 | ||
|
|
5d3af62c0e | ||
|
|
ddd5aeba19 | ||
|
|
3cfcbe9a95 | ||
|
|
6bc793505d | ||
|
|
3b44160cff | ||
|
|
d9586c8d38 | ||
|
|
74df3fac4e | ||
|
|
06321b8e87 | ||
|
|
f3efb948fe | ||
|
|
432c03bf63 | ||
|
|
bfd224278b | ||
|
|
822ea6abc8 | ||
|
|
97437ee58b | ||
|
|
aa7fe0db29 | ||
|
|
237685d4a5 | ||
|
|
abbe630274 | ||
|
|
89d3b08e77 | ||
|
|
f826216a28 | ||
|
|
aa0a874ad0 | ||
|
|
2da26c0579 | ||
|
|
d34c844900 | ||
|
|
68b63632c4 | ||
|
|
d2de94778e | ||
|
|
4fd4a50d41 | ||
|
|
9d93820717 | ||
|
|
c57a7f0a41 | ||
|
|
1d15fcd072 | ||
|
|
e824b1129e | ||
|
|
0cd03c66e3 | ||
|
|
462b231dac | ||
|
|
e4a918850f | ||
|
|
d472af3517 | ||
|
|
98a587a347 | ||
|
|
5fd996876b | ||
|
|
b433d98c02 | ||
|
|
7006672b06 | ||
|
|
efec0c5cc3 | ||
|
|
16e71eac43 | ||
|
|
68b62abb52 | ||
|
|
b2f3479692 | ||
|
|
67d62ba164 | ||
|
|
e1fc60b8dd | ||
|
|
f32e696fef | ||
|
|
fc81298fac | ||
|
|
5987cfeaaf | ||
|
|
cd0ece4511 | ||
|
|
dc9f85ebb9 | ||
|
|
35a2055cda | ||
|
|
a1066776a5 | ||
|
|
4dae747343 | ||
|
|
d348a5b947 | ||
|
|
f0c413f40d | ||
|
|
846eee2f6c | ||
|
|
0b9ff68da1 | ||
|
|
7187e005d4 | ||
|
|
a5cd24e7ea | ||
|
|
dbe821baee | ||
|
|
04486c6472 | ||
|
|
2ee8ba9361 | ||
|
|
b07782cd89 | ||
|
|
305450b6e4 | ||
|
|
fdd0b853ed | ||
|
|
1d025204e7 | ||
|
|
12f759860e | ||
|
|
1bdbb5ddcc | ||
|
|
b573fb6555 | ||
|
|
b50a7bdbee | ||
|
|
5a5f10dfc8 |
@@ -5,7 +5,7 @@ AccessModifierOffset: -1
|
|||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: false
|
AlignConsecutiveAssignments: false
|
||||||
AlignConsecutiveDeclarations: false
|
AlignConsecutiveDeclarations: false
|
||||||
AlignEscapedNewlinesLeft: true
|
AlignEscapedNewlines: Left
|
||||||
AlignOperands: true
|
AlignOperands: true
|
||||||
AlignTrailingComments: true
|
AlignTrailingComments: true
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
@@ -32,12 +32,20 @@ BraceWrapping:
|
|||||||
BeforeCatch: false
|
BeforeCatch: false
|
||||||
BeforeElse: false
|
BeforeElse: false
|
||||||
IndentBraces: false
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeBraces: Attach
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: true
|
||||||
BreakConstructorInitializersBeforeComma: false
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
ColumnLimit: 80
|
ColumnLimit: 80
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
ConstructorInitializerIndentWidth: 4
|
ConstructorInitializerIndentWidth: 4
|
||||||
ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 4
|
||||||
@@ -45,7 +53,11 @@ Cpp11BracedListStyle: true
|
|||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
- Regex: '^<.*\.h>'
|
- Regex: '^<.*\.h>'
|
||||||
Priority: 1
|
Priority: 1
|
||||||
@@ -53,9 +65,12 @@ IncludeCategories:
|
|||||||
Priority: 2
|
Priority: 2
|
||||||
- Regex: '.*'
|
- Regex: '.*'
|
||||||
Priority: 3
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
MacroBlockBegin: ''
|
MacroBlockBegin: ''
|
||||||
MacroBlockEnd: ''
|
MacroBlockEnd: ''
|
||||||
@@ -64,6 +79,7 @@ NamespaceIndentation: None
|
|||||||
ObjCBlockIndentWidth: 2
|
ObjCBlockIndentWidth: 2
|
||||||
ObjCSpaceAfterProperty: false
|
ObjCSpaceAfterProperty: false
|
||||||
ObjCSpaceBeforeProtocolList: false
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
PenaltyBreakBeforeFirstCallParameter: 1
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
PenaltyBreakComment: 300
|
PenaltyBreakComment: 300
|
||||||
PenaltyBreakFirstLessLess: 120
|
PenaltyBreakFirstLessLess: 120
|
||||||
@@ -72,8 +88,10 @@ PenaltyExcessCharacter: 1000000
|
|||||||
PenaltyReturnTypeOnItsOwnLine: 200
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
SortIncludes: true
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
|
|||||||
41
.gitignore
vendored
41
.gitignore
vendored
@@ -1,15 +1,10 @@
|
|||||||
# WPIlib Specific
|
# WPIlib Specific
|
||||||
|
|
||||||
dependency-reduced-pom.xml
|
dependency-reduced-pom.xml
|
||||||
/wpilibj/src/athena/cpp/nivision/*.c
|
|
||||||
/wpilibj/src/athena/cpp/nivision/*.cpp
|
|
||||||
/wpilibj/src/athena/cpp/nivision/*.s
|
|
||||||
/wpilibj/src/athena/cpp/nivision/*_arm.ini
|
|
||||||
/wpilibj/src/athena/cpp/nivision/*.java
|
|
||||||
/wpilibj/src/athena/cpp/nivision/nivision_funcs.txt
|
|
||||||
/wpilibj/src/athena/cpp/nivision/imaqdx_funcs.txt
|
|
||||||
/wpilibj/src/shared/java/edu/wpi/first/wpilibj/util/WPILibVersion.java
|
/wpilibj/src/shared/java/edu/wpi/first/wpilibj/util/WPILibVersion.java
|
||||||
/wpilibc/shared/src/WPILibVersion.cpp
|
/wpilibc/shared/src/WPILibVersion.cpp
|
||||||
|
/wpilibj/src/main/java/edu/wpi/first/wpilibj/util/WPILibVersion.java
|
||||||
|
/wpilibc/src/main/native/cpp/WPILibVersion.cpp
|
||||||
doxygen.log
|
doxygen.log
|
||||||
|
|
||||||
# Created by the jenkins test script
|
# Created by the jenkins test script
|
||||||
@@ -17,6 +12,8 @@ test-reports
|
|||||||
|
|
||||||
# IntelliJ
|
# IntelliJ
|
||||||
*.iml
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
# Created by http://www.gitignore.io
|
# Created by http://www.gitignore.io
|
||||||
@@ -157,6 +154,9 @@ local.properties
|
|||||||
*.pyc
|
*.pyc
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
||||||
|
# Gradle wrapper
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
# External tool builders
|
# External tool builders
|
||||||
.externalToolBuilders/
|
.externalToolBuilders/
|
||||||
|
|
||||||
@@ -190,3 +190,30 @@ NO
|
|||||||
#classpaths and projects
|
#classpaths and projects
|
||||||
.project
|
.project
|
||||||
.classpath
|
.classpath
|
||||||
|
|
||||||
|
#Visual Studio
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
*.VC.db-shm
|
||||||
|
*.VC.db-wal
|
||||||
|
|
||||||
|
*.sln
|
||||||
|
*.vcxproj
|
||||||
|
*.vcxproj.filters
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
|||||||
68
.styleguide
68
.styleguide
@@ -1,63 +1,39 @@
|
|||||||
cExtensions {
|
cppHeaderFileInclude {
|
||||||
|
\.h$
|
||||||
|
\.hpp$
|
||||||
|
\.inc$
|
||||||
}
|
}
|
||||||
|
|
||||||
cppHeaderExtensions {
|
cppSrcFileInclude {
|
||||||
h
|
\.cpp$
|
||||||
inc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cppSrcExtensions {
|
generatedFileExclude {
|
||||||
cpp
|
gmock/
|
||||||
}
|
ni-libraries/include/
|
||||||
|
ni-libraries/lib/
|
||||||
otherExtensions {
|
hal/src/main/native/athena/ctre/
|
||||||
java
|
hal/src/main/native/athena/frccansae/
|
||||||
}
|
hal/src/main/native/athena/visa/
|
||||||
|
hal/src/main/native/include/ctre/
|
||||||
genFolderExclude {
|
UsageReporting\.h$
|
||||||
FRC_FPGA_ChipObject
|
|
||||||
NetworkCommunication
|
|
||||||
ctre
|
|
||||||
frccansae
|
|
||||||
gtest
|
|
||||||
i2clib
|
|
||||||
msgs
|
|
||||||
ni-libraries
|
|
||||||
ni/vision
|
|
||||||
spilib
|
|
||||||
wpilibj/src/athena/cpp/nivision
|
|
||||||
visa
|
|
||||||
}
|
|
||||||
|
|
||||||
genFileExclude {
|
|
||||||
NIIMAQdx\.h$
|
|
||||||
can_proto\.h$
|
|
||||||
nivision\.h$
|
|
||||||
}
|
|
||||||
|
|
||||||
modifiableFolderExclude {
|
|
||||||
\.git
|
|
||||||
wpilibj/src/athena/cpp/include
|
|
||||||
wpilibj/src/athena/cpp/lib
|
|
||||||
}
|
}
|
||||||
|
|
||||||
modifiableFileExclude {
|
modifiableFileExclude {
|
||||||
|
wpilibj/src/arm-linux-jni/
|
||||||
|
wpilibj/src/main/native/cpp/
|
||||||
\.patch$
|
\.patch$
|
||||||
\.png$
|
\.png$
|
||||||
\.py$
|
\.py$
|
||||||
\.so$
|
\.so$
|
||||||
}
|
}
|
||||||
|
|
||||||
includeRelated {
|
|
||||||
}
|
|
||||||
|
|
||||||
includeCSys {
|
|
||||||
}
|
|
||||||
|
|
||||||
includeCppSys {
|
|
||||||
}
|
|
||||||
|
|
||||||
includeOtherLibs {
|
includeOtherLibs {
|
||||||
|
^HAL/
|
||||||
|
^llvm/
|
||||||
|
^networktables/
|
||||||
|
^opencv2/
|
||||||
|
^support/
|
||||||
}
|
}
|
||||||
|
|
||||||
includeProject {
|
includeProject {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* Copyright (c) FIRST {year}. All Rights Reserved.{padding}*/
|
/* Copyright (c) {year} FIRST. All Rights Reserved.{padding}*/
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||||
/* the project. */
|
/* the project. */
|
||||||
|
|||||||
32
.travis.yml
32
.travis.yml
@@ -1,24 +1,40 @@
|
|||||||
sudo: required
|
sudo: true
|
||||||
dist: trusty
|
dist: trusty
|
||||||
language: java
|
language: java
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- deadsnakes
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-6
|
||||||
|
- python3.5
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list'
|
- sudo sh -c 'echo "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main" > /etc/apt/sources.list.d/llvm.list'
|
||||||
- wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
|
- wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
|
||||||
- sudo add-apt-repository ppa:wpilib/toolchain -y
|
|
||||||
- sudo apt-get update -q || true
|
- sudo apt-get update -q || true
|
||||||
- sudo apt-get install frc-toolchain libgazebo7-dev protobuf-compiler libprotobuf-dev python3 clang-format-3.8 -y
|
- sudo apt-get install clang-format-5.0 -y
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip3 install wpiformat
|
- wget https://bootstrap.pypa.io/get-pip.py
|
||||||
|
- sudo python3.5 get-pip.py
|
||||||
|
- python3.5 -m pip install --user wpiformat
|
||||||
|
- mkdir -p $HOME/latest-gcc-symlinks # see travis-ci/travis-ci#3668
|
||||||
|
- ln -s /usr/bin/g++-6 $HOME/latest-gcc-symlinks/g++
|
||||||
|
- ln -s /usr/bin/gcc-6 $HOME/latest-gcc-symlinks/gcc
|
||||||
|
- export PATH=$HOME/latest-gcc-symlinks:$PATH
|
||||||
|
|
||||||
before_cache:
|
before_cache:
|
||||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/.gradle/caches/
|
- $HOME/.gradle/caches/
|
||||||
- $HOME/.gradle/wrapper/
|
- $HOME/.gradle/wrapper/
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- wpiformat
|
- python3.5 -m wpiformat -y 2018 -clang 5.0
|
||||||
- git --no-pager diff --exit-code HEAD # Ensure formatter made no changes
|
- git --no-pager diff --exit-code HEAD # Ensure formatter made no changes
|
||||||
- ./gradlew build -PmakeSim
|
- ./gradlew --no-daemon --console=plain -PskipAthena :hal:halSimSharedLibrary :wpilibc:wpilibcSharedLibrary :wpilibj:wpilibJNISharedSharedLibrary :wpilibj:jar
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
project(AllC++Sim)
|
|
||||||
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
include (FindPkgConfig)
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
|
|
||||||
#check for depenedencies
|
|
||||||
find_package(gazebo REQUIRED)
|
|
||||||
find_package(Boost COMPONENTS system filesystem REQUIRED)
|
|
||||||
|
|
||||||
#on windows we produce .dlls with no prefix
|
|
||||||
if(WIN32)
|
|
||||||
#allows us to define constexpr and noexcept in macros
|
|
||||||
#since msvc 2013 doesn't support them
|
|
||||||
add_definitions(-D_ALLOW_KEYWORD_MACROS)
|
|
||||||
|
|
||||||
# defines things like M_PI
|
|
||||||
add_definitions(-D_USE_MATH_DEFINES)
|
|
||||||
|
|
||||||
# get rid of min max macros on windows
|
|
||||||
add_definitions(-DNOMINMAX)
|
|
||||||
|
|
||||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
|
||||||
|
|
||||||
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
|
|
||||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (MSVC)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFRC_SIMULATOR /MDd /Zi")
|
|
||||||
else ()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++1y -DFRC_SIMULATOR -Wno-unused-parameter -pthread -fPIC -fpermissive")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include_directories("build")
|
|
||||||
add_subdirectory(simulation/gz_msgs)
|
|
||||||
add_subdirectory(wpilibc/sim)
|
|
||||||
add_subdirectory(simulation/frc_gazebo_plugins)
|
|
||||||
24
LICENSE.txt
Normal file
24
LICENSE.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Copyright (c) 2009-2017 FIRST
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the FIRST nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY FIRST AND CONTRIBUTORS``AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
@@ -23,9 +23,13 @@ Using Gradle makes building WPILib very straightforward. It only has a few depen
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
- A C++ compiler
|
||||||
|
- On Linux, gcc works fine
|
||||||
|
- On Windows, you need Visual Studio 2015 (the free community edition works fine).
|
||||||
|
Make sure to select the C++ Programming Language for installation
|
||||||
- [ARM Compiler Toolchain](http://first.wpi.edu/FRC/roborio/toolchains/)
|
- [ARM Compiler Toolchain](http://first.wpi.edu/FRC/roborio/toolchains/)
|
||||||
|
* Note that for 2017-2018 and beyond, you will need version 5 or greater of gcc
|
||||||
- Doxygen (Only required if you want to build the C++ documentation)
|
- Doxygen (Only required if you want to build the C++ documentation)
|
||||||
- [wpiformat](https://github.com/wpilibsuite/styleguide)
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
INCLUDE(CMakeForceCompiler)
|
|
||||||
set(ARM_PREFIX arm-frc-linux-gnueabi)
|
|
||||||
set(CMAKE_SYSTEM_NAME Linux)
|
|
||||||
CMAKE_FORCE_CXX_COMPILER(${ARM_PREFIX}-g++ GNU)
|
|
||||||
CMAKE_FORCE_C_COMPILER(${ARM_PREFIX}-gcc GNU)
|
|
||||||
set(CMAKE_CXX_FLAGS "-std=c++1y -Wformat=2 -Wall -Wextra -Werror -pedantic -Wno-psabi" CACHE STRING "" FORCE)
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3" CACHE STRING "" FORCE)
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -g" CACHE STRING "" FORCE) # still want debugging for release?
|
|
||||||
183
build.gradle
183
build.gradle
@@ -1,6 +1,131 @@
|
|||||||
|
import edu.wpi.first.nativeutils.NativeUtils
|
||||||
|
import edu.wpi.first.nativeutils.tasks.JNIHeaders
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'gradle.plugin.edu.wpi.first:native-utils:1.5.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'net.ltgt.errorprone' version '0.0.8'
|
id 'net.ltgt.errorprone' version '0.0.10'
|
||||||
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '1.6'
|
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '2.0'
|
||||||
|
id 'idea'
|
||||||
|
}
|
||||||
|
|
||||||
|
ext.licenseFile = file("$rootDir/LICENSE.txt")
|
||||||
|
|
||||||
|
ext.getJNIHeadersClass = {
|
||||||
|
return JNIHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
ext.getClassifier = { binary->
|
||||||
|
return NativeUtils.getClassifier(binary)
|
||||||
|
}
|
||||||
|
|
||||||
|
ext.getPlatformPath = { binary->
|
||||||
|
return NativeUtils.getPlatformPath(binary)
|
||||||
|
}
|
||||||
|
|
||||||
|
ext.createComponentZipTasks = { components, name, base, type, project, func ->
|
||||||
|
def configMap = [:]
|
||||||
|
components.each {
|
||||||
|
if (it in NativeLibrarySpec && it.name == name) {
|
||||||
|
it.binaries.each {
|
||||||
|
def target = getClassifier(it)
|
||||||
|
if (configMap.containsKey(target)) {
|
||||||
|
configMap.get(target).add(it)
|
||||||
|
} else {
|
||||||
|
configMap.put(target, [])
|
||||||
|
configMap.get(target).add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def taskList = []
|
||||||
|
def outputsFolder = file("$project.buildDir/outputs")
|
||||||
|
def baseN = base + name
|
||||||
|
configMap.each { key, value ->
|
||||||
|
def task = project.tasks.create(baseN + "-${key}", type) {
|
||||||
|
description = 'Creates component archive for platform ' + key
|
||||||
|
destinationDir = outputsFolder
|
||||||
|
classifier = key
|
||||||
|
baseName = baseN + '-classifier'
|
||||||
|
duplicatesStrategy = 'exclude'
|
||||||
|
|
||||||
|
from(licenseFile) {
|
||||||
|
into '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
func(it, value)
|
||||||
|
}
|
||||||
|
taskList.add(task)
|
||||||
|
|
||||||
|
project.build.dependsOn task
|
||||||
|
|
||||||
|
project.artifacts {
|
||||||
|
task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return taskList
|
||||||
|
}
|
||||||
|
|
||||||
|
ext.createAllCombined = { list, name, base, type, project ->
|
||||||
|
def outputsFolder = file("$project.buildDir/outputs")
|
||||||
|
def baseN = base + name
|
||||||
|
def task = project.tasks.create(baseN + '-all', type) {
|
||||||
|
description = 'Creates component archive for all classifiers'
|
||||||
|
destinationDir = outputsFolder
|
||||||
|
classifier = 'all'
|
||||||
|
baseName = baseN + '-classifier'
|
||||||
|
duplicatesStrategy = 'exclude'
|
||||||
|
|
||||||
|
list.each {
|
||||||
|
it.outputs.files.each {
|
||||||
|
from project.zipTree(it)
|
||||||
|
}
|
||||||
|
dependsOn it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.build.dependsOn task
|
||||||
|
|
||||||
|
project.artifacts {
|
||||||
|
task
|
||||||
|
}
|
||||||
|
|
||||||
|
return task
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ext.includeStandardZipFormat = { task, value ->
|
||||||
|
value.each { binary->
|
||||||
|
if (binary.buildable) {
|
||||||
|
if (binary instanceof SharedLibraryBinarySpec) {
|
||||||
|
task.dependsOn binary.buildTask
|
||||||
|
task.from(new File(binary.sharedLibraryFile.absolutePath + ".debug")) {
|
||||||
|
into getPlatformPath(binary) + '/shared'
|
||||||
|
}
|
||||||
|
task.from (binary.sharedLibraryFile) {
|
||||||
|
into getPlatformPath(binary) + '/shared'
|
||||||
|
}
|
||||||
|
task.from (binary.sharedLibraryLinkFile) {
|
||||||
|
into getPlatformPath(binary) + '/shared'
|
||||||
|
}
|
||||||
|
} else if (binary instanceof StaticLibraryBinarySpec) {
|
||||||
|
task.dependsOn binary.buildTask
|
||||||
|
task.from (binary.staticLibraryFile) {
|
||||||
|
into getPlatformPath(binary) + '/static'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the WPILibVersioningPlugin is setup by setting the release type, if releaseType wasn't
|
// Ensure that the WPILibVersioningPlugin is setup by setting the release type, if releaseType wasn't
|
||||||
@@ -11,28 +136,38 @@ if (!hasProperty('releaseType')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def enableSimulation = hasProperty('makeSim')
|
def pubVersion
|
||||||
|
if (project.hasProperty("publishVersion")) {
|
||||||
|
pubVersion = project.publishVersion
|
||||||
|
} else {
|
||||||
|
pubVersion = WPILibVersion.version
|
||||||
|
}
|
||||||
|
|
||||||
ext.simulationInstallDir = "$rootDir/build/install/simulation"
|
def outputsFolder = file("$buildDir/outputs")
|
||||||
|
|
||||||
allprojects {
|
def versionFile = file("$outputsFolder/version.txt")
|
||||||
ext.enableSimulation = enableSimulation
|
|
||||||
|
|
||||||
repositories {
|
task outputVersions() {
|
||||||
mavenCentral()
|
description = 'Prints the versions of wpilib to a file for use by the downstream packaging project'
|
||||||
|
group = 'Build'
|
||||||
|
outputs.files(versionFile)
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
buildDir.mkdir()
|
||||||
|
outputsFolder.mkdir()
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.ntcoreDep = { lang, classifier, extension = null ->
|
doLast {
|
||||||
return "edu.wpi.first.wpilib.networktables.$lang:NetworkTables:+:$classifier${extension == null ? '' : '@' + extension}"
|
versionFile.write pubVersion
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ext.cscoreDep = { lang, classifier, extension = null ->
|
task build() {}
|
||||||
return "edu.wpi.cscore.$lang:cscore:+:$classifier${extension == null ? '' : '@' + extension}"
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.wpiUtilDep = { classifier ->
|
build.dependsOn outputVersions
|
||||||
return "edu.wpi.first.wpilib:wpiutil:+:$classifier@zip"
|
|
||||||
}
|
task clean(type: Delete) {
|
||||||
|
delete buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
@@ -40,12 +175,14 @@ subprojects {
|
|||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'checkstyle'
|
apply plugin: 'checkstyle'
|
||||||
|
|
||||||
checkstyle {
|
repositories {
|
||||||
toolVersion = "6.18"
|
mavenCentral()
|
||||||
configFile = new File(rootDir, "styleguide/checkstyle.xml")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.armBuild = true
|
checkstyle {
|
||||||
|
toolVersion = "8.1"
|
||||||
|
configFile = new File(rootDir, "styleguide/checkstyle.xml")
|
||||||
|
}
|
||||||
|
|
||||||
// Disables doclint in java 8.
|
// Disables doclint in java 8.
|
||||||
if (JavaVersion.current().isJava8Compatible()) {
|
if (JavaVersion.current().isJava8Compatible()) {
|
||||||
@@ -60,10 +197,6 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: 'cppSettings.gradle'
|
|
||||||
|
|
||||||
apply from: 'ni-libraries/ni-libraries.gradle'
|
|
||||||
|
|
||||||
task wrapper(type: Wrapper) {
|
task wrapper(type: Wrapper) {
|
||||||
gradleVersion = '3.3'
|
gradleVersion = '4.1'
|
||||||
}
|
}
|
||||||
|
|||||||
235
config.gradle
Normal file
235
config.gradle
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
import edu.wpi.first.nativeutils.*
|
||||||
|
import org.gradle.internal.os.OperatingSystem
|
||||||
|
|
||||||
|
def windowsCompilerArgs = ['/EHsc', '/DNOMINMAX', '/Zi', '/FS', '/Zc:inline', '/MT']
|
||||||
|
def windowsReleaseCompilerArgs = ['/O2']
|
||||||
|
def windowsLinkerArgs = [ '/DEBUG:FULL' ]
|
||||||
|
def windowsReleaseLinkerArgs = [ '/OPT:REF', '/OPT:ICF' ]
|
||||||
|
|
||||||
|
def linuxCompilerArgs = ['-std=c++11', '-Wformat=2', '-Wall', '-Wextra', '-Werror', '-pedantic', '-Wno-psabi', '-g',
|
||||||
|
'-Wno-unused-parameter', '-fPIC', '-rdynamic', '-Wno-error=deprecated-declarations', '-pthread']
|
||||||
|
def linuxLinkerArgs = ['-rdynamic', '-pthread']
|
||||||
|
def linuxReleaseCompilerArgs = ['-Og']
|
||||||
|
def linuxDebugCompilerArgs = ['-O0']
|
||||||
|
def linux32BitArg = '-m32'
|
||||||
|
|
||||||
|
def macCompilerArgs = ['-std=c++11', '-Wall', '-Wextra', '-Werror', '-pedantic-errors', '-fPIC', '-g',
|
||||||
|
'-Wno-unused-parameter', '-Wno-missing-field-initializers', '-Wno-unused-private-field',
|
||||||
|
'-Wno-unused-const-variable', '-pthread']
|
||||||
|
def macReleaseCompilerArgs = ['-O2']
|
||||||
|
def macDebugCompilerArgs = ['-O0']
|
||||||
|
def mac32BitArg = '-m32'
|
||||||
|
|
||||||
|
def buildAll = project.hasProperty('buildAll')
|
||||||
|
|
||||||
|
def windows64PlatformDetect = {
|
||||||
|
def arch = System.getProperty("os.arch")
|
||||||
|
def isWin = OperatingSystem.current().isWindows()
|
||||||
|
if (buildAll) {
|
||||||
|
return isWin
|
||||||
|
} else {
|
||||||
|
return isWin && arch == 'amd64'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def windows32PlatformDetect = {
|
||||||
|
def arch = System.getProperty("os.arch")
|
||||||
|
def isWin = OperatingSystem.current().isWindows()
|
||||||
|
if (buildAll) {
|
||||||
|
return isWin
|
||||||
|
} else {
|
||||||
|
return isWin && arch == 'x86'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def linux32IntelPlatformDetect = {
|
||||||
|
def arch = System.getProperty("os.arch")
|
||||||
|
def isLinux = OperatingSystem.current().isLinux()
|
||||||
|
def isIntel = (arch == 'amd64' || arch == 'i386')
|
||||||
|
if (buildAll) {
|
||||||
|
return isLinux && isIntel
|
||||||
|
} else {
|
||||||
|
return isLinux && arch == 'i386'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def linux64IntelPlatformDetect = {
|
||||||
|
def arch = System.getProperty("os.arch")
|
||||||
|
def isLinux = OperatingSystem.current().isLinux()
|
||||||
|
def isIntel = (arch == 'amd64' || arch == 'i386')
|
||||||
|
if (buildAll) {
|
||||||
|
return isLinux && isIntel
|
||||||
|
} else {
|
||||||
|
return isLinux && arch == 'amd64'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def linuxArmPlatformDetect = {
|
||||||
|
def arch = System.getProperty("os.arch")
|
||||||
|
def isIntel = (arch == 'amd64' || arch == 'i386')
|
||||||
|
return OperatingSystem.current().isLinux() && !isIntel
|
||||||
|
}
|
||||||
|
|
||||||
|
def mac64PlatformDetect = {
|
||||||
|
def arch = System.getProperty("os.arch")
|
||||||
|
def isMac = OperatingSystem.current().isMacOsX()
|
||||||
|
if (buildAll) {
|
||||||
|
return isMac
|
||||||
|
} else {
|
||||||
|
return isMac && arch == 'x86_64'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def mac32PlatformDetect = {
|
||||||
|
def arch = System.getProperty("os.arch")
|
||||||
|
def isMac = OperatingSystem.current().isMacOsX()
|
||||||
|
if (buildAll) {
|
||||||
|
return isMac
|
||||||
|
} else {
|
||||||
|
return isMac && arch == 'x86'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!project.hasProperty('skipAthena')) {
|
||||||
|
model {
|
||||||
|
buildConfigs {
|
||||||
|
roboRio(CrossBuildConfig) {
|
||||||
|
architecture = 'athena'
|
||||||
|
operatingSystem = 'linux'
|
||||||
|
toolChainPrefix = 'arm-frc-linux-gnueabi-'
|
||||||
|
compilerArgs = linuxCompilerArgs
|
||||||
|
linkerArgs = linuxLinkerArgs
|
||||||
|
debugCompilerArgs = linuxDebugCompilerArgs
|
||||||
|
releaseCompilerArgs = linuxReleaseCompilerArgs
|
||||||
|
releaseStripBinaries = true
|
||||||
|
compilerFamily = 'Gcc'
|
||||||
|
exclude << 'halSim'
|
||||||
|
exclude << 'halSimStaticDeps'
|
||||||
|
exclude << 'halSimTestingBase'
|
||||||
|
exclude << 'wpilibcTestingBase'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!project.hasProperty('onlyAthena')) {
|
||||||
|
model {
|
||||||
|
buildConfigs {
|
||||||
|
winX86(BuildConfig) {
|
||||||
|
architecture = 'x86'
|
||||||
|
operatingSystem = 'windows'
|
||||||
|
compilerArgs = windowsCompilerArgs
|
||||||
|
linkerArgs = windowsLinkerArgs
|
||||||
|
releaseCompilerArgs = windowsReleaseCompilerArgs
|
||||||
|
releaseLinkerArgs = windowsReleaseLinkerArgs
|
||||||
|
compilerFamily = 'VisualCpp'
|
||||||
|
detectPlatform = windows32PlatformDetect
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
winX64(BuildConfig) {
|
||||||
|
architecture = 'x86-64'
|
||||||
|
operatingSystem = 'windows'
|
||||||
|
compilerArgs = windowsCompilerArgs
|
||||||
|
linkerArgs = windowsLinkerArgs
|
||||||
|
releaseCompilerArgs = windowsReleaseCompilerArgs
|
||||||
|
releaseLinkerArgs = windowsReleaseLinkerArgs
|
||||||
|
compilerFamily = 'VisualCpp'
|
||||||
|
detectPlatform = windows64PlatformDetect
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
/* Disable 32 bit linux until we can figure out jenkins
|
||||||
|
linuxX86(BuildConfig) {
|
||||||
|
architecture = 'x86'
|
||||||
|
operatingSystem = 'linux'
|
||||||
|
compilerArgs = linuxCompilerArgs
|
||||||
|
compilerArgs << linux32BitArg
|
||||||
|
linkerArgs = linuxLinkerArgs
|
||||||
|
linkerArgs << linux32BitArg
|
||||||
|
debugCompilerArgs = linuxDebugCompilerArgs
|
||||||
|
releaseCompilerArgs = linuxReleaseCompilerArgs
|
||||||
|
releaseStripBinaries = true
|
||||||
|
compilerFamily = 'Gcc'
|
||||||
|
detectPlatform = linux32IntelPlatformDetect
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
linuxX64(BuildConfig) {
|
||||||
|
architecture = 'x86-64'
|
||||||
|
operatingSystem = 'linux'
|
||||||
|
compilerArgs = linuxCompilerArgs
|
||||||
|
linkerArgs = linuxLinkerArgs
|
||||||
|
debugCompilerArgs = linuxDebugCompilerArgs
|
||||||
|
releaseCompilerArgs = linuxReleaseCompilerArgs
|
||||||
|
releaseStripBinaries = true
|
||||||
|
compilerFamily = 'Gcc'
|
||||||
|
detectPlatform = linux64IntelPlatformDetect
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
/* 32 bit Mac OS X not supported by OpenCV.
|
||||||
|
* If support is ever added, will add this back in
|
||||||
|
macX86(BuildConfig) {
|
||||||
|
architecture = 'x86'
|
||||||
|
operatingSystem = 'osx'
|
||||||
|
compilerArgs = macCompilerArgs
|
||||||
|
compilerArgs << mac32BitArg
|
||||||
|
linkerArgs << mac32BitArg
|
||||||
|
debugCompilerArgs = macDebugCompilerArgs
|
||||||
|
releaseCompilerArgs = macReleaseCompilerArgs
|
||||||
|
releaseStripBinaries = true
|
||||||
|
compilerFamily = 'Clang'
|
||||||
|
detectPlatform = mac32PlatformDetect
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
macX64(BuildConfig) {
|
||||||
|
architecture = 'x86-64'
|
||||||
|
operatingSystem = 'osx'
|
||||||
|
compilerArgs = macCompilerArgs
|
||||||
|
debugCompilerArgs = macDebugCompilerArgs
|
||||||
|
releaseCompilerArgs = macReleaseCompilerArgs
|
||||||
|
releaseStripBinaries = true
|
||||||
|
compilerFamily = 'Clang'
|
||||||
|
detectPlatform = mac64PlatformDetect
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project.hasProperty('linuxCross')) {
|
||||||
|
model {
|
||||||
|
buildConfigs {
|
||||||
|
linuxArm(CrossBuildConfig) {
|
||||||
|
architecture = 'nativearm'
|
||||||
|
operatingSystem = 'linux'
|
||||||
|
toolChainPrefix = 'PLEASE_PROVIDE_A_COMPILER_NAME'
|
||||||
|
compilerArgs = linuxCompilerArgs
|
||||||
|
linkerArgs = linuxLinkerArgs
|
||||||
|
debugCompilerArgs = linuxDebugCompilerArgs
|
||||||
|
releaseCompilerArgs = linuxReleaseCompilerArgs
|
||||||
|
releaseStripBinaries = true
|
||||||
|
skipByDefault = true
|
||||||
|
compilerFamily = 'Gcc'
|
||||||
|
exclude << 'gmock'
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
model {
|
||||||
|
buildConfigs {
|
||||||
|
linuxArm(BuildConfig) {
|
||||||
|
architecture = 'nativearm'
|
||||||
|
operatingSystem = 'linux'
|
||||||
|
compilerArgs = linuxCompilerArgs
|
||||||
|
linkerArgs = linuxLinkerArgs
|
||||||
|
debugCompilerArgs = linuxDebugCompilerArgs
|
||||||
|
releaseCompilerArgs = linuxReleaseCompilerArgs
|
||||||
|
releaseStripBinaries = true
|
||||||
|
compilerFamily = 'Gcc'
|
||||||
|
detectPlatform = linuxArmPlatformDetect
|
||||||
|
exclude << 'halAthena'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
:: This file is a helper for allC++Sim
|
|
||||||
::
|
|
||||||
:: Usage: cd /build && ../configure
|
|
||||||
::
|
|
||||||
:: WARNING -- this is only temporary, and only meant for debug, and only works on my computer
|
|
||||||
@set WS=C:\Users\peter\gz-ws
|
|
||||||
@set BOOST_PATH=%WS%\boost_1_56_0
|
|
||||||
@set BOOST_LIBRARY_DIR=%BOOST_PATH%\lib64-msvc-12.0
|
|
||||||
|
|
||||||
@set PROTOBUF_PATH=%WS%\protobuf-2.6.0-win64-vc12
|
|
||||||
|
|
||||||
@set OGRE_PATH=%WS%\ogre_src_v1-8-1-vc12-x64-release-debug\build\install\Debug
|
|
||||||
@set OGRE_INCLUDE_DIR=%OGRE_PATH%\include;%OGRE_PATH%\include\OGRE;%OGRE_PATH%\include\OGRE\RTShaderSystem;%OGRE_PATH%\include\OGRE\Terrain;%OGRE_PATH%\include\OGRE\Paging
|
|
||||||
@set OGRE_LIBRARY_DIR=%OGRE_PATH%\lib\Debug
|
|
||||||
set OGRE_LIB_SUFFIX=_d.lib
|
|
||||||
@set OGRE_LIBS=%OGRE_LIBRARY_DIR%\OgreMain%OGRE_LIB_SUFFIX%;%OGRE_LIBRARY_DIR%\OgreOverlay%OGRE_LIB_SUFFIX%;%OGRE_LIBRARY_DIR%\OgreRTShaderSystem%OGRE_LIB_SUFFIX%;%OGRE_LIBRARY_DIR%\OgreTerrain%OGRE_LIB_SUFFIX%;%OGRE_LIBRARY_DIR%\OgrePaging%OGRE_LIB_SUFFIX%
|
|
||||||
@set OGRE_LIBS=%OGRE_LIBRARY_DIR%\OgreMain%OGRE_LIB_SUFFIX%;%OGRE_LIBRARY_DIR%\OgreRTShaderSystem%OGRE_LIB_SUFFIX%;%OGRE_LIBRARY_DIR%\OgreTerrain%OGRE_LIB_SUFFIX%;%OGRE_LIBRARY_DIR%\OgrePaging%OGRE_LIB_SUFFIX%
|
|
||||||
|
|
||||||
@set FREEIMAGE_PATH=%WS%\FreeImage-vc12-x64-release-debug
|
|
||||||
@set FREEIMAGE_INCLUDE_DIR=%FREEIMAGE_PATH%\Source
|
|
||||||
|
|
||||||
@set TBB_PATH=%WS%\tbb43_20141023oss
|
|
||||||
@set TBB_INCLUDEDIR=%TBB_PATH%\include
|
|
||||||
|
|
||||||
@set DLFCN_WIN32_PATH=%WS%\dlfcn-win32-vc12-x64-release-debug\build\install\Debug
|
|
||||||
@set DLFCN_WIN32_INCLUDE_DIR=%DLFCN_WIN32_PATH%\include
|
|
||||||
|
|
||||||
@set TINY_XML_INCLUDE_DIR=%WS%\sdformat\src\win\tinyxml
|
|
||||||
|
|
||||||
@set GAZEBO_PATH=%WS%\gazebo\build\install\Debug\lib\cmake\gazebo
|
|
||||||
@set SDFORMAT_PATH=%WS%\sdformat\build\install\Debug\lib\cmake\sdformat
|
|
||||||
@set IGNITION-MATH_PATH=%WS%\ign-math\build\install\Debug\lib\cmake\ignition-math2
|
|
||||||
|
|
||||||
@set INCLUDE=%TINY_XML_INCLUDE_DIR%;%FREEIMAGE_INCLUDE_DIR%;%TBB_INCLUDEDIR%;%DLFCN_WIN32_INCLUDE_DIR%;%INCLUDE%
|
|
||||||
@set LIB=%LIB%
|
|
||||||
|
|
||||||
cmake -G "NMake Makefiles"^
|
|
||||||
-DCMAKE_INSTALL_PREFIX=build^
|
|
||||||
-DCMAKE_PREFIX_PATH="%GAZEBO_PATH%;%SDFORMAT_PATH%;%IGNITION-MATH_PATH%"^
|
|
||||||
-DOGRE_FOUND=1^
|
|
||||||
-DOGRE_INCLUDE_DIRS="%OGRE_INCLUDE_DIR%"^
|
|
||||||
-DOGRE_LIBRARIES="%OGRE_LIBS%"^
|
|
||||||
-DPROTOBUF_SRC_ROOT_FOLDER="%PROTOBUF_PATH%"^
|
|
||||||
-DBOOST_ROOT="%BOOST_PATH%"^
|
|
||||||
-DBOOST_LIBRARYDIR="%BOOST_LIBRARY_DIR%"^
|
|
||||||
..
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
// These add the nilibraries shared library to the linker args
|
|
||||||
def niLibraryPath = file('ni-libraries/lib').path
|
|
||||||
def niLibrary = niLibraryPath + "/libnilibraries.so"
|
|
||||||
|
|
||||||
configurations.create('armDeps')
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
armDeps ntcoreDep('cpp', 'arm', 'zip')
|
|
||||||
armDeps wpiUtilDep('arm')
|
|
||||||
armDeps cscoreDep('cpp', 'athena-uberzip', 'zip')
|
|
||||||
}
|
|
||||||
|
|
||||||
def depLocation = "$buildDir/dependencies"
|
|
||||||
|
|
||||||
configurations.armDeps.files.each { file ->
|
|
||||||
def depName = file.name.substring(0, file.name.indexOf('-'))
|
|
||||||
def t = tasks.create("downloadArm${depName.capitalize()}", Copy) {
|
|
||||||
description = "Downloads and unzips the $depName dependency."
|
|
||||||
group = 'Dependencies'
|
|
||||||
from zipTree(file)
|
|
||||||
into "$depLocation/${depName.toLowerCase()}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task downloadNetworkTables {
|
|
||||||
description = 'Downloads all needed versions of networktables.'
|
|
||||||
group = 'Dependencies'
|
|
||||||
dependsOn downloadArmNetworkTables
|
|
||||||
}
|
|
||||||
|
|
||||||
task downloadWpiutil {
|
|
||||||
description = 'Downloads all needed versions of WPIUtil.'
|
|
||||||
group = 'Dependencies'
|
|
||||||
dependsOn downloadArmWpiutil
|
|
||||||
}
|
|
||||||
|
|
||||||
task downloadCscore {
|
|
||||||
description = 'Downloads all needed versions of cscore.'
|
|
||||||
group = 'Dependencies'
|
|
||||||
dependsOn downloadArmCscore
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableSimulation) {
|
|
||||||
configurations.create('nativeDeps')
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
nativeDeps ntcoreDep('cpp', 'desktop', 'zip')
|
|
||||||
nativeDeps wpiUtilDep('desktop')
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.nativeDeps.files.each { file ->
|
|
||||||
def depName = file.name.substring(0, file.name.indexOf('-'))
|
|
||||||
def t = tasks.create("downloadNative${depName.capitalize()}", Copy) {
|
|
||||||
description = "Downloads and unzips the $depName dependency."
|
|
||||||
group = 'Dependencies'
|
|
||||||
from zipTree(file)
|
|
||||||
into "$depLocation/${depName.toLowerCase()}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadNetworkTables.dependsOn downloadNativeNetworkTables
|
|
||||||
downloadWpiutil.dependsOn downloadNativeWpiutil
|
|
||||||
}
|
|
||||||
|
|
||||||
def netTablesUnzipLocation = "$depLocation/networktables"
|
|
||||||
def wpiUtilUnzipLocation = "$depLocation/wpiutil"
|
|
||||||
def csCoreUnzipLocation = "$depLocation/cscore"
|
|
||||||
|
|
||||||
task clean(type: Delete) {
|
|
||||||
description = "Deletes the build directory"
|
|
||||||
group = "Build"
|
|
||||||
delete buildDir
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasProperty("toolChainPath")) {
|
|
||||||
ext.toolChainPath = null
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
|
||||||
ext.defineWpiUtilProperties = {
|
|
||||||
ext.wpiUtil = wpiUtilUnzipLocation
|
|
||||||
ext.wpiUtilInclude = "$wpiUtilUnzipLocation/include"
|
|
||||||
ext.wpiUtilLibArmLocation = "$wpiUtilUnzipLocation/Linux/arm"
|
|
||||||
if (enableSimulation) {
|
|
||||||
ext.wpiUtilLibDesktopLocation = "$wpiUtilUnzipLocation/Linux/amd64"
|
|
||||||
}
|
|
||||||
ext.wpiUtilSharedLib = "$wpiUtilLibArmLocation/libwpiutil.so"
|
|
||||||
ext.wpiUtilSharedLibDebug = "$wpiUtilLibArmLocation/libwpiutil.so.debug"
|
|
||||||
ext.wpiUtilStaticLib = "$wpiUtilLibArmLocation/libwpiutil.a"
|
|
||||||
|
|
||||||
ext.addWpiUtilLibraryLinks = { compileTask, linker, targetPlatform ->
|
|
||||||
compileTask.dependsOn project(':').downloadWpiutil
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')) {
|
|
||||||
linker.args wpiUtilSharedLib
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.addStaticWpiUtilLibraryLinks = { compileTask, linker, targetPlatform ->
|
|
||||||
compileTask.dependsOn project(':').downloadWpiutil
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')) {
|
|
||||||
linker.args wpiUtilStaticLib
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This defines a project property that projects depending on network tables can use to setup that dependency.
|
|
||||||
ext.defineNetworkTablesProperties = {
|
|
||||||
ext.netTables = netTablesUnzipLocation
|
|
||||||
ext.netTablesInclude = "$netTablesUnzipLocation/include"
|
|
||||||
ext.netLibArmLocation = "$netTablesUnzipLocation/Linux/arm"
|
|
||||||
if (enableSimulation) {
|
|
||||||
ext.netLibDesktopLocation = "$netTablesUnzipLocation/Linux/amd64"
|
|
||||||
}
|
|
||||||
ext.netSharedLib = "$netLibArmLocation/libntcore.so"
|
|
||||||
ext.netSharedLibDebug = "$netLibArmLocation/libntcore.so.debug"
|
|
||||||
ext.netStaticLib = "$netLibArmLocation/libntcore.a"
|
|
||||||
|
|
||||||
ext.addNetworkTablesLibraryLinks = { compileTask, linker, targetPlatform ->
|
|
||||||
compileTask.dependsOn project(':').downloadNetworkTables
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')) {
|
|
||||||
linker.args netSharedLib
|
|
||||||
}
|
|
||||||
addWpiUtilLibraryLinks(compileTask, linker, targetPlatform)
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.addStaticNetworkTablesLibraryLinks = { compileTask, linker, targetPlatform ->
|
|
||||||
compileTask.dependsOn project(':').downloadNetworkTables
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')) {
|
|
||||||
linker.args netStaticLib
|
|
||||||
}
|
|
||||||
addStaticWpiUtilLibraryLinks(compileTask, linker, targetPlatform)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This defines a project property that projects depending on cscore can use to setup that dependency.
|
|
||||||
ext.defineCsCoreProperties = {
|
|
||||||
ext.csCore = csCoreUnzipLocation
|
|
||||||
ext.csCoreInclude = "$csCoreUnzipLocation/include"
|
|
||||||
ext.csLibArmLocation = "$csCoreUnzipLocation/lib"
|
|
||||||
ext.csSharedLib = "$csLibArmLocation/libcscore.so"
|
|
||||||
ext.cvSharedLib = "$csLibArmLocation/libopencv.so"
|
|
||||||
|
|
||||||
ext.addCsCoreLibraryLinks = { compileTask, linker, targetPlatform ->
|
|
||||||
compileTask.dependsOn project(':').downloadCscore
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')) {
|
|
||||||
linker.args << '-L' + csLibArmLocation
|
|
||||||
linker.args csSharedLib
|
|
||||||
linker.args cvSharedLib
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.defineCrossCompilerProperties = {
|
|
||||||
// We use a custom-built cross compiler with the prefix arm-frc-linux-gnueabi-<util name>
|
|
||||||
// If this ever changes, the prefix will need to be changed here
|
|
||||||
ext.compilerPrefix = 'arm-frc-linux-gnueabi-'
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins.withType(CppPlugin).whenPluginAdded {
|
|
||||||
defineCrossCompilerProperties()
|
|
||||||
model {
|
|
||||||
buildTypes {
|
|
||||||
debug
|
|
||||||
}
|
|
||||||
// Adds a custom toolchain for our compiler prefix and options
|
|
||||||
toolChains {
|
|
||||||
roborioGcc(Gcc) {
|
|
||||||
if (toolChainPath != null)
|
|
||||||
path toolChainPath
|
|
||||||
target('roborio-arm') {
|
|
||||||
cCompiler.executable = compilerPrefix + cCompiler.executable
|
|
||||||
cppCompiler.executable = compilerPrefix + cppCompiler.executable
|
|
||||||
linker.executable = compilerPrefix + linker.executable
|
|
||||||
assembler.executable = compilerPrefix + assembler.executable
|
|
||||||
// Gradle auto-adds the -m32 argument to the linker and compiler. Our compiler only supports
|
|
||||||
// arm, and doesn't understand this flag, so it is removed from both
|
|
||||||
cppCompiler.withArguments { args ->
|
|
||||||
args << '-std=c++1y' << '-Wformat=2' << '-Wall' << '-Wextra' << '-Werror' << '-pedantic'
|
|
||||||
args << '-Wno-psabi' << '-Wno-unused-parameter' << '-fPIC' << '-Og' << '-g3' << '-rdynamic'
|
|
||||||
//TODO: When the compiler allows us to actually call deprecated functions from within
|
|
||||||
// deprecated function, remove this line (this will cause calling deprecated functions
|
|
||||||
// to be treated as a warning rather than an error).
|
|
||||||
args << '-Wno-error=deprecated-declarations'
|
|
||||||
args.remove('-m32')
|
|
||||||
}
|
|
||||||
linker.withArguments { args ->
|
|
||||||
args << '-rdynamic'
|
|
||||||
args.remove('-m32')
|
|
||||||
}
|
|
||||||
staticLibArchiver.executable = compilerPrefix + staticLibArchiver.executable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
platforms {
|
|
||||||
'roborio-arm' {
|
|
||||||
architecture 'arm'
|
|
||||||
operatingSystem 'linux'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.niLibraryHeadersRoot = "${rootDir}/ni-libraries/include"
|
|
||||||
ext.niLibraryHeadersChipObject = "${rootDir}/ni-libraries/include/FRC_FPGA_ChipObject"
|
|
||||||
|
|
||||||
ext.binTool = { tool ->
|
|
||||||
if (toolChainPath != null) return "${toolChainPath}/${compilerPrefix}${tool}"
|
|
||||||
return "${compilerPrefix}${tool}"
|
|
||||||
}
|
|
||||||
|
|
||||||
// This task adds the appropriate linker flags for the NI libraries
|
|
||||||
ext.addNiLibraryLinks = { linker, targetPlatform ->
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')){
|
|
||||||
linker.args << '-L' + niLibraryPath
|
|
||||||
linker.args niLibrary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This task sets up the shared libraries to be stripped
|
|
||||||
ext.debugStripSetup = { project->
|
|
||||||
if (!project.hasProperty('debug')) {
|
|
||||||
project.tasks.whenObjectAdded { task ->
|
|
||||||
def name = task.name.toLowerCase()
|
|
||||||
if (name.contains('link') && name.contains('sharedlibrary')) {
|
|
||||||
def library = task.outputFile.absolutePath
|
|
||||||
def debugLibrary = task.outputFile.absolutePath + ".debug"
|
|
||||||
task.doLast {
|
|
||||||
exec { commandLine binTool('objcopy'), '--only-keep-debug', library, debugLibrary }
|
|
||||||
exec { commandLine binTool('strip'), '-g', library }
|
|
||||||
exec { commandLine binTool('objcopy'), "--add-gnu-debuglink=$debugLibrary", library }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
86
gmock/CMakeLists.txt
Normal file
86
gmock/CMakeLists.txt
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
########################################################################
|
||||||
|
# CMake build script for Google Mock.
|
||||||
|
#
|
||||||
|
# To run the tests for Google Mock itself on Linux, use 'make test' or
|
||||||
|
# ctest. You can select which tests to run using 'ctest -R regex'.
|
||||||
|
# For more options, run 'ctest --help'.
|
||||||
|
|
||||||
|
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
|
||||||
|
# make it prominent in the GUI.
|
||||||
|
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
|
||||||
|
|
||||||
|
# A directory to find Google Test sources.
|
||||||
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/gtest/CMakeLists.txt")
|
||||||
|
set(gtest_dir gtest)
|
||||||
|
else()
|
||||||
|
set(gtest_dir ../gtest)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
|
||||||
|
include("${gtest_dir}/cmake/hermetic_build.cmake" OPTIONAL)
|
||||||
|
|
||||||
|
if (COMMAND pre_project_set_up_hermetic_build)
|
||||||
|
# Google Test also calls hermetic setup functions from add_subdirectory,
|
||||||
|
# although its changes will not affect things at the current scope.
|
||||||
|
pre_project_set_up_hermetic_build()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Project-wide settings
|
||||||
|
|
||||||
|
# Name of the project.
|
||||||
|
#
|
||||||
|
# CMake files in this project can refer to the root source directory
|
||||||
|
# as ${gmock_SOURCE_DIR} and to the root binary directory as
|
||||||
|
# ${gmock_BINARY_DIR}.
|
||||||
|
# Language "C" is required for find_package(Threads).
|
||||||
|
project(gmock CXX C)
|
||||||
|
cmake_minimum_required(VERSION 2.6.2)
|
||||||
|
|
||||||
|
if (COMMAND set_up_hermetic_build)
|
||||||
|
set_up_hermetic_build()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers -Wno-format-nonliteral")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Instructs CMake to process Google Test's CMakeLists.txt and add its
|
||||||
|
# targets to the current scope. We are placing Google Test's binary
|
||||||
|
# directory in a subdirectory of our own as VC compilation may break
|
||||||
|
# if they are the same (the default).
|
||||||
|
add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/gtest")
|
||||||
|
|
||||||
|
# Although Google Test's CMakeLists.txt calls this function, the
|
||||||
|
# changes there don't affect the current scope. Therefore we have to
|
||||||
|
# call it again here.
|
||||||
|
config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake
|
||||||
|
|
||||||
|
# Adds Google Mock's and Google Test's header directories to the search path.
|
||||||
|
include_directories("${gmock_SOURCE_DIR}/include"
|
||||||
|
"${gmock_SOURCE_DIR}"
|
||||||
|
"${gtest_SOURCE_DIR}/include"
|
||||||
|
# This directory is needed to build directly from Google
|
||||||
|
# Test sources.
|
||||||
|
"${gtest_SOURCE_DIR}")
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Defines the gmock & gmock_main libraries. User tests should link
|
||||||
|
# with one of them.
|
||||||
|
|
||||||
|
# Google Mock libraries. We build them using more strict warnings than what
|
||||||
|
# are used for other targets, to ensure that Google Mock can be compiled by
|
||||||
|
# a user aggressive about warnings.
|
||||||
|
cxx_library(gmock
|
||||||
|
"${cxx_strict}"
|
||||||
|
"${gtest_dir}/src/gtest-all.cc"
|
||||||
|
src/gmock-all.cc)
|
||||||
|
|
||||||
|
cxx_library(gmock_main
|
||||||
|
"${cxx_strict}"
|
||||||
|
"${gtest_dir}/src/gtest-all.cc"
|
||||||
|
src/gmock-all.cc
|
||||||
|
src/gmock_main.cc)
|
||||||
|
|
||||||
28
gmock/LICENSE
Normal file
28
gmock/LICENSE
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
Copyright 2008, Google Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
44
gmock/build.gradle
Normal file
44
gmock/build.gradle
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import org.gradle.internal.os.OperatingSystem
|
||||||
|
|
||||||
|
if (!project.hasProperty('onlyAthena')) {
|
||||||
|
apply plugin: 'cpp'
|
||||||
|
apply plugin: 'visual-studio'
|
||||||
|
apply plugin: 'edu.wpi.first.NativeUtils'
|
||||||
|
|
||||||
|
ext.gmockProject = true
|
||||||
|
|
||||||
|
apply from: '../config.gradle'
|
||||||
|
|
||||||
|
ext.addGmockToLinker = { binary->
|
||||||
|
binary.lib project: ':gmock', library: 'gmock', linkage: 'static'
|
||||||
|
}
|
||||||
|
|
||||||
|
model {
|
||||||
|
components {
|
||||||
|
gmock(NativeLibrarySpec) {
|
||||||
|
sources {
|
||||||
|
cpp {
|
||||||
|
source {
|
||||||
|
srcDirs = ['src', 'gtest/src']
|
||||||
|
includes = ['*-all.cc']
|
||||||
|
}
|
||||||
|
exportedHeaders {
|
||||||
|
srcDirs = ['include', 'gtest/include', '.', 'gtest']
|
||||||
|
includes = ['**/*.h', '**/*.cc']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binaries.all {
|
||||||
|
if (toolChain in VisualCpp) {
|
||||||
|
cppCompiler.args '-D_UNICODE', '-DUNICODE', '-DWIN32', '-D_WIN32', '-DSTRICT', '-DWIN32_LEAN_AND_MEAN', '-D_HAS_EXCEPTIONS=1'
|
||||||
|
} else {
|
||||||
|
cppCompiler.args '-Wall', '-Wshadow', '-fexceptions', '-Wextra', '-Wno-unused-parameter', '-Wno-missing-field-initializers', '-pthread', '-fPIC'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binaries.withType(SharedLibraryBinarySpec) {
|
||||||
|
buildable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
gmock/gtest/CMakeLists.txt
Normal file
69
gmock/gtest/CMakeLists.txt
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
########################################################################
|
||||||
|
# CMake build script for Google Test.
|
||||||
|
#
|
||||||
|
# To run the tests for Google Test itself on Linux, use 'make test' or
|
||||||
|
# ctest. You can select which tests to run using 'ctest -R regex'.
|
||||||
|
# For more options, run 'ctest --help'.
|
||||||
|
|
||||||
|
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
|
||||||
|
# make it prominent in the GUI.
|
||||||
|
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
|
||||||
|
|
||||||
|
# When other libraries are using a shared version of runtime libraries,
|
||||||
|
# Google Test also has to use one.
|
||||||
|
option(
|
||||||
|
gtest_force_shared_crt
|
||||||
|
"Use shared (DLL) run-time lib even when Google Test is built as static lib."
|
||||||
|
OFF)
|
||||||
|
|
||||||
|
option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
|
||||||
|
|
||||||
|
# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
|
||||||
|
include(cmake/hermetic_build.cmake OPTIONAL)
|
||||||
|
|
||||||
|
if (COMMAND pre_project_set_up_hermetic_build)
|
||||||
|
pre_project_set_up_hermetic_build()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Project-wide settings
|
||||||
|
|
||||||
|
# Name of the project.
|
||||||
|
#
|
||||||
|
# CMake files in this project can refer to the root source directory
|
||||||
|
# as ${gtest_SOURCE_DIR} and to the root binary directory as
|
||||||
|
# ${gtest_BINARY_DIR}.
|
||||||
|
# Language "C" is required for find_package(Threads).
|
||||||
|
project(gtest CXX C)
|
||||||
|
cmake_minimum_required(VERSION 2.6.2)
|
||||||
|
|
||||||
|
if (COMMAND set_up_hermetic_build)
|
||||||
|
set_up_hermetic_build()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Define helper functions and macros used by Google Test.
|
||||||
|
include(cmake/internal_utils.cmake)
|
||||||
|
|
||||||
|
config_compiler_and_linker() # Defined in internal_utils.cmake.
|
||||||
|
|
||||||
|
# Where Google Test's .h files can be found.
|
||||||
|
include_directories(
|
||||||
|
${gtest_SOURCE_DIR}/include
|
||||||
|
${gtest_SOURCE_DIR})
|
||||||
|
|
||||||
|
# Where Google Test's libraries can be found.
|
||||||
|
link_directories(${gtest_BINARY_DIR}/src)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Defines the gtest & gtest_main libraries. User tests should link
|
||||||
|
# with one of them.
|
||||||
|
|
||||||
|
# Google Test libraries. We build them using more strict warnings than what
|
||||||
|
# are used for other targets, to ensure that gtest can be compiled by a user
|
||||||
|
# aggressive about warnings.
|
||||||
|
cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
|
||||||
|
cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
|
||||||
|
target_link_libraries(gtest_main gtest)
|
||||||
|
|
||||||
28
gmock/gtest/LICENSE
Normal file
28
gmock/gtest/LICENSE
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
Copyright 2008, Google Inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
206
gmock/gtest/cmake/internal_utils.cmake
Normal file
206
gmock/gtest/cmake/internal_utils.cmake
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
# Defines functions and macros useful for building Google Test and
|
||||||
|
# Google Mock.
|
||||||
|
#
|
||||||
|
# Note:
|
||||||
|
#
|
||||||
|
# - This file will be run twice when building Google Mock (once via
|
||||||
|
# Google Test's CMakeLists.txt, and once via Google Mock's).
|
||||||
|
# Therefore it shouldn't have any side effects other than defining
|
||||||
|
# the functions and macros.
|
||||||
|
#
|
||||||
|
# - The functions/macros defined in this file may depend on Google
|
||||||
|
# Test and Google Mock's option() definitions, and thus must be
|
||||||
|
# called *after* the options have been defined.
|
||||||
|
|
||||||
|
# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
|
||||||
|
#
|
||||||
|
# This must be a macro(), as inside a function string() can only
|
||||||
|
# update variables in the function scope.
|
||||||
|
macro(fix_default_compiler_settings_)
|
||||||
|
if (MSVC)
|
||||||
|
# For MSVC, CMake sets certain flags to defaults we want to override.
|
||||||
|
# This replacement code is taken from sample in the CMake Wiki at
|
||||||
|
# http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
|
||||||
|
foreach (flag_var
|
||||||
|
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||||
|
if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
|
||||||
|
# When Google Test is built as a shared library, it should also use
|
||||||
|
# shared runtime libraries. Otherwise, it may end up with multiple
|
||||||
|
# copies of runtime library data in different modules, resulting in
|
||||||
|
# hard-to-find crashes. When it is built as a static library, it is
|
||||||
|
# preferable to use CRT as static libraries, as we don't have to rely
|
||||||
|
# on CRT DLLs being available. CMake always defaults to using shared
|
||||||
|
# CRT libraries, so we override that default here.
|
||||||
|
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# We prefer more strict warning checking for building Google Test.
|
||||||
|
# Replaces /W3 with /W4 in defaults.
|
||||||
|
string(REPLACE "/W3" "-W4" ${flag_var} "${${flag_var}}")
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Defines the compiler/linker flags used to build Google Test and
|
||||||
|
# Google Mock. You can tweak these definitions to suit your need. A
|
||||||
|
# variable's value is empty before it's explicitly assigned to.
|
||||||
|
macro(config_compiler_and_linker)
|
||||||
|
if (NOT gtest_disable_pthreads)
|
||||||
|
# Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
|
||||||
|
find_package(Threads)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
fix_default_compiler_settings_()
|
||||||
|
if (MSVC)
|
||||||
|
# Newlines inside flags variables break CMake's NMake generator.
|
||||||
|
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
|
||||||
|
set(cxx_base_flags "-GS -W4 -WX -wd4127 -wd4251 -wd4275 -nologo -J -Zi")
|
||||||
|
if (MSVC_VERSION LESS 1400)
|
||||||
|
# Suppress spurious warnings MSVC 7.1 sometimes issues.
|
||||||
|
# Forcing value to bool.
|
||||||
|
set(cxx_base_flags "${cxx_base_flags} -wd4800")
|
||||||
|
# Copy constructor and assignment operator could not be generated.
|
||||||
|
set(cxx_base_flags "${cxx_base_flags} -wd4511 -wd4512")
|
||||||
|
# Compatibility warnings not applicable to Google Test.
|
||||||
|
# Resolved overload was found by argument-dependent lookup.
|
||||||
|
set(cxx_base_flags "${cxx_base_flags} -wd4675")
|
||||||
|
endif()
|
||||||
|
set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
|
||||||
|
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
|
||||||
|
set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
|
||||||
|
set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
|
||||||
|
set(cxx_no_rtti_flags "-GR-")
|
||||||
|
elseif (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(cxx_base_flags "-Wall -Wshadow")
|
||||||
|
set(cxx_exception_flags "-fexceptions")
|
||||||
|
set(cxx_no_exception_flags "-fno-exceptions")
|
||||||
|
# Until version 4.3.2, GCC doesn't define a macro to indicate
|
||||||
|
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
|
||||||
|
# explicitly.
|
||||||
|
set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
|
||||||
|
set(cxx_strict_flags
|
||||||
|
"-Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
|
||||||
|
set(cxx_exception_flags "-features=except")
|
||||||
|
# Sun Pro doesn't provide macros to indicate whether exceptions and
|
||||||
|
# RTTI are enabled, so we define GTEST_HAS_* explicitly.
|
||||||
|
set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
|
||||||
|
set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
|
||||||
|
CMAKE_CXX_COMPILER_ID STREQUAL "XL")
|
||||||
|
# CMake 2.8 changes Visual Age's compiler ID to "XL".
|
||||||
|
set(cxx_exception_flags "-qeh")
|
||||||
|
set(cxx_no_exception_flags "-qnoeh")
|
||||||
|
# Until version 9.0, Visual Age doesn't define a macro to indicate
|
||||||
|
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
|
||||||
|
# explicitly.
|
||||||
|
set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
|
||||||
|
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
|
||||||
|
set(cxx_base_flags "-AA -mt")
|
||||||
|
set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
|
||||||
|
set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
|
||||||
|
# RTTI can not be disabled in HP aCC compiler.
|
||||||
|
set(cxx_no_rtti_flags "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_USE_PTHREADS_INIT) # The pthreads library is available and allowed.
|
||||||
|
set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
|
||||||
|
else()
|
||||||
|
set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=0")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# For building gtest's own tests and samples.
|
||||||
|
set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
|
||||||
|
set(cxx_no_exception
|
||||||
|
"${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
|
||||||
|
set(cxx_default "${cxx_exception}")
|
||||||
|
set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
|
||||||
|
set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
|
||||||
|
|
||||||
|
# For building the gtest libraries.
|
||||||
|
set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Defines the gtest & gtest_main libraries. User tests should link
|
||||||
|
# with one of them.
|
||||||
|
function(cxx_library_with_type name type cxx_flags)
|
||||||
|
# type can be either STATIC or SHARED to denote a static or shared library.
|
||||||
|
# ARGN refers to additional arguments after 'cxx_flags'.
|
||||||
|
add_library(${name} ${type} ${ARGN})
|
||||||
|
set_target_properties(${name}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_FLAGS "${cxx_flags}")
|
||||||
|
if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
|
||||||
|
set_target_properties(${name}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
|
||||||
|
endif()
|
||||||
|
if (CMAKE_USE_PTHREADS_INIT)
|
||||||
|
target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
# Helper functions for creating build targets.
|
||||||
|
|
||||||
|
function(cxx_shared_library name cxx_flags)
|
||||||
|
cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cxx_library name cxx_flags)
|
||||||
|
cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# cxx_executable_with_flags(name cxx_flags libs srcs...)
|
||||||
|
#
|
||||||
|
# creates a named C++ executable that depends on the given libraries and
|
||||||
|
# is built from the given source files with the given compiler flags.
|
||||||
|
function(cxx_executable_with_flags name cxx_flags libs)
|
||||||
|
add_executable(${name} ${ARGN})
|
||||||
|
if (cxx_flags)
|
||||||
|
set_target_properties(${name}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_FLAGS "${cxx_flags}")
|
||||||
|
endif()
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
set_target_properties(${name}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
|
||||||
|
endif()
|
||||||
|
# To support mixing linking in static and dynamic libraries, link each
|
||||||
|
# library in with an extra call to target_link_libraries.
|
||||||
|
foreach (lib "${libs}")
|
||||||
|
target_link_libraries(${name} ${lib})
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# cxx_executable(name dir lib srcs...)
|
||||||
|
#
|
||||||
|
# creates a named target that depends on the given libs and is built
|
||||||
|
# from the given source files. dir/name.cc is implicitly included in
|
||||||
|
# the source file list.
|
||||||
|
function(cxx_executable name dir libs)
|
||||||
|
cxx_executable_with_flags(
|
||||||
|
${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# cxx_test_with_flags(name cxx_flags libs srcs...)
|
||||||
|
#
|
||||||
|
# creates a named C++ test that depends on the given libs and is built
|
||||||
|
# from the given source files with the given compiler flags.
|
||||||
|
function(cxx_test_with_flags name cxx_flags libs)
|
||||||
|
cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
|
||||||
|
add_test(${name} ${name})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# cxx_test(name libs srcs...)
|
||||||
|
#
|
||||||
|
# creates a named test target that depends on the given libs and is
|
||||||
|
# built from the given source files. Unlike cxx_test_with_flags,
|
||||||
|
# test/name.cc is already implicitly included in the source file list.
|
||||||
|
function(cxx_test name libs)
|
||||||
|
cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
|
||||||
|
"test/${name}.cc" ${ARGN})
|
||||||
|
endfunction()
|
||||||
@@ -1,294 +1,294 @@
|
|||||||
// Copyright 2005, Google Inc.
|
// Copyright 2005, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
//
|
//
|
||||||
// The Google C++ Testing Framework (Google Test)
|
// The Google C++ Testing Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines the public API for death tests. It is
|
// This header file defines the public API for death tests. It is
|
||||||
// #included by gtest.h so a user doesn't need to include this
|
// #included by gtest.h so a user doesn't need to include this
|
||||||
// directly.
|
// directly.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||||
|
|
||||||
#include "gtest/internal/gtest-death-test-internal.h"
|
#include "gtest/internal/gtest-death-test-internal.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// This flag controls the style of death tests. Valid values are "threadsafe",
|
// This flag controls the style of death tests. Valid values are "threadsafe",
|
||||||
// meaning that the death test child process will re-execute the test binary
|
// meaning that the death test child process will re-execute the test binary
|
||||||
// from the start, running only a single death test, or "fast",
|
// from the start, running only a single death test, or "fast",
|
||||||
// meaning that the child process will execute the test logic immediately
|
// meaning that the child process will execute the test logic immediately
|
||||||
// after forking.
|
// after forking.
|
||||||
GTEST_DECLARE_string_(death_test_style);
|
GTEST_DECLARE_string_(death_test_style);
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Returns a Boolean value indicating whether the caller is currently
|
// Returns a Boolean value indicating whether the caller is currently
|
||||||
// executing in the context of the death test child process. Tools such as
|
// executing in the context of the death test child process. Tools such as
|
||||||
// Valgrind heap checkers may need this to modify their behavior in death
|
// Valgrind heap checkers may need this to modify their behavior in death
|
||||||
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
// tests. IMPORTANT: This is an internal utility. Using it may break the
|
||||||
// implementation of death tests. User code MUST NOT use it.
|
// implementation of death tests. User code MUST NOT use it.
|
||||||
GTEST_API_ bool InDeathTestChild();
|
GTEST_API_ bool InDeathTestChild();
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// The following macros are useful for writing death tests.
|
// The following macros are useful for writing death tests.
|
||||||
|
|
||||||
// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
|
// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
|
||||||
// executed:
|
// executed:
|
||||||
//
|
//
|
||||||
// 1. It generates a warning if there is more than one active
|
// 1. It generates a warning if there is more than one active
|
||||||
// thread. This is because it's safe to fork() or clone() only
|
// thread. This is because it's safe to fork() or clone() only
|
||||||
// when there is a single thread.
|
// when there is a single thread.
|
||||||
//
|
//
|
||||||
// 2. The parent process clone()s a sub-process and runs the death
|
// 2. The parent process clone()s a sub-process and runs the death
|
||||||
// test in it; the sub-process exits with code 0 at the end of the
|
// test in it; the sub-process exits with code 0 at the end of the
|
||||||
// death test, if it hasn't exited already.
|
// death test, if it hasn't exited already.
|
||||||
//
|
//
|
||||||
// 3. The parent process waits for the sub-process to terminate.
|
// 3. The parent process waits for the sub-process to terminate.
|
||||||
//
|
//
|
||||||
// 4. The parent process checks the exit code and error message of
|
// 4. The parent process checks the exit code and error message of
|
||||||
// the sub-process.
|
// the sub-process.
|
||||||
//
|
//
|
||||||
// Examples:
|
// Examples:
|
||||||
//
|
//
|
||||||
// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
|
// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
|
||||||
// for (int i = 0; i < 5; i++) {
|
// for (int i = 0; i < 5; i++) {
|
||||||
// EXPECT_DEATH(server.ProcessRequest(i),
|
// EXPECT_DEATH(server.ProcessRequest(i),
|
||||||
// "Invalid request .* in ProcessRequest()")
|
// "Invalid request .* in ProcessRequest()")
|
||||||
// << "Failed to die on request " << i;
|
// << "Failed to die on request " << i;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
|
// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
|
||||||
//
|
//
|
||||||
// bool KilledBySIGHUP(int exit_code) {
|
// bool KilledBySIGHUP(int exit_code) {
|
||||||
// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
|
// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
|
// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
|
||||||
//
|
//
|
||||||
// On the regular expressions used in death tests:
|
// On the regular expressions used in death tests:
|
||||||
//
|
//
|
||||||
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
|
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
|
||||||
// which uses the POSIX extended regex syntax.
|
// which uses the POSIX extended regex syntax.
|
||||||
//
|
//
|
||||||
// On other platforms (e.g. Windows), we only support a simple regex
|
// On other platforms (e.g. Windows), we only support a simple regex
|
||||||
// syntax implemented as part of Google Test. This limited
|
// syntax implemented as part of Google Test. This limited
|
||||||
// implementation should be enough most of the time when writing
|
// implementation should be enough most of the time when writing
|
||||||
// death tests; though it lacks many features you can find in PCRE
|
// death tests; though it lacks many features you can find in PCRE
|
||||||
// or POSIX extended regex syntax. For example, we don't support
|
// or POSIX extended regex syntax. For example, we don't support
|
||||||
// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
|
// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
|
||||||
// repetition count ("x{5,7}"), among others.
|
// repetition count ("x{5,7}"), among others.
|
||||||
//
|
//
|
||||||
// Below is the syntax that we do support. We chose it to be a
|
// Below is the syntax that we do support. We chose it to be a
|
||||||
// subset of both PCRE and POSIX extended regex, so it's easy to
|
// subset of both PCRE and POSIX extended regex, so it's easy to
|
||||||
// learn wherever you come from. In the following: 'A' denotes a
|
// learn wherever you come from. In the following: 'A' denotes a
|
||||||
// literal character, period (.), or a single \\ escape sequence;
|
// literal character, period (.), or a single \\ escape sequence;
|
||||||
// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
|
// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
|
||||||
// natural numbers.
|
// natural numbers.
|
||||||
//
|
//
|
||||||
// c matches any literal character c
|
// c matches any literal character c
|
||||||
// \\d matches any decimal digit
|
// \\d matches any decimal digit
|
||||||
// \\D matches any character that's not a decimal digit
|
// \\D matches any character that's not a decimal digit
|
||||||
// \\f matches \f
|
// \\f matches \f
|
||||||
// \\n matches \n
|
// \\n matches \n
|
||||||
// \\r matches \r
|
// \\r matches \r
|
||||||
// \\s matches any ASCII whitespace, including \n
|
// \\s matches any ASCII whitespace, including \n
|
||||||
// \\S matches any character that's not a whitespace
|
// \\S matches any character that's not a whitespace
|
||||||
// \\t matches \t
|
// \\t matches \t
|
||||||
// \\v matches \v
|
// \\v matches \v
|
||||||
// \\w matches any letter, _, or decimal digit
|
// \\w matches any letter, _, or decimal digit
|
||||||
// \\W matches any character that \\w doesn't match
|
// \\W matches any character that \\w doesn't match
|
||||||
// \\c matches any literal character c, which must be a punctuation
|
// \\c matches any literal character c, which must be a punctuation
|
||||||
// . matches any single character except \n
|
// . matches any single character except \n
|
||||||
// A? matches 0 or 1 occurrences of A
|
// A? matches 0 or 1 occurrences of A
|
||||||
// A* matches 0 or many occurrences of A
|
// A* matches 0 or many occurrences of A
|
||||||
// A+ matches 1 or many occurrences of A
|
// A+ matches 1 or many occurrences of A
|
||||||
// ^ matches the beginning of a string (not that of each line)
|
// ^ matches the beginning of a string (not that of each line)
|
||||||
// $ matches the end of a string (not that of each line)
|
// $ matches the end of a string (not that of each line)
|
||||||
// xy matches x followed by y
|
// xy matches x followed by y
|
||||||
//
|
//
|
||||||
// If you accidentally use PCRE or POSIX extended regex features
|
// If you accidentally use PCRE or POSIX extended regex features
|
||||||
// not implemented by us, you will get a run-time failure. In that
|
// not implemented by us, you will get a run-time failure. In that
|
||||||
// case, please try to rewrite your regular expression within the
|
// case, please try to rewrite your regular expression within the
|
||||||
// above syntax.
|
// above syntax.
|
||||||
//
|
//
|
||||||
// This implementation is *not* meant to be as highly tuned or robust
|
// This implementation is *not* meant to be as highly tuned or robust
|
||||||
// as a compiled regex library, but should perform well enough for a
|
// as a compiled regex library, but should perform well enough for a
|
||||||
// death test, which already incurs significant overhead by launching
|
// death test, which already incurs significant overhead by launching
|
||||||
// a child process.
|
// a child process.
|
||||||
//
|
//
|
||||||
// Known caveats:
|
// Known caveats:
|
||||||
//
|
//
|
||||||
// A "threadsafe" style death test obtains the path to the test
|
// A "threadsafe" style death test obtains the path to the test
|
||||||
// program from argv[0] and re-executes it in the sub-process. For
|
// program from argv[0] and re-executes it in the sub-process. For
|
||||||
// simplicity, the current implementation doesn't search the PATH
|
// simplicity, the current implementation doesn't search the PATH
|
||||||
// when launching the sub-process. This means that the user must
|
// when launching the sub-process. This means that the user must
|
||||||
// invoke the test program via a path that contains at least one
|
// invoke the test program via a path that contains at least one
|
||||||
// path separator (e.g. path/to/foo_test and
|
// path separator (e.g. path/to/foo_test and
|
||||||
// /absolute/path/to/bar_test are fine, but foo_test is not). This
|
// /absolute/path/to/bar_test are fine, but foo_test is not). This
|
||||||
// is rarely a problem as people usually don't put the test binary
|
// is rarely a problem as people usually don't put the test binary
|
||||||
// directory in PATH.
|
// directory in PATH.
|
||||||
//
|
//
|
||||||
// TODO(wan@google.com): make thread-safe death tests search the PATH.
|
// TODO(wan@google.com): make thread-safe death tests search the PATH.
|
||||||
|
|
||||||
// Asserts that a given statement causes the program to exit, with an
|
// Asserts that a given statement causes the program to exit, with an
|
||||||
// integer exit status that satisfies predicate, and emitting error output
|
// integer exit status that satisfies predicate, and emitting error output
|
||||||
// that matches regex.
|
// that matches regex.
|
||||||
# define ASSERT_EXIT(statement, predicate, regex) \
|
# define ASSERT_EXIT(statement, predicate, regex) \
|
||||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
|
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
// Like ASSERT_EXIT, but continues on to successive tests in the
|
// Like ASSERT_EXIT, but continues on to successive tests in the
|
||||||
// test case, if any:
|
// test case, if any:
|
||||||
# define EXPECT_EXIT(statement, predicate, regex) \
|
# define EXPECT_EXIT(statement, predicate, regex) \
|
||||||
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
|
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
|
||||||
|
|
||||||
// Asserts that a given statement causes the program to exit, either by
|
// Asserts that a given statement causes the program to exit, either by
|
||||||
// explicitly exiting with a nonzero exit code or being killed by a
|
// explicitly exiting with a nonzero exit code or being killed by a
|
||||||
// signal, and emitting error output that matches regex.
|
// signal, and emitting error output that matches regex.
|
||||||
# define ASSERT_DEATH(statement, regex) \
|
# define ASSERT_DEATH(statement, regex) \
|
||||||
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||||
|
|
||||||
// Like ASSERT_DEATH, but continues on to successive tests in the
|
// Like ASSERT_DEATH, but continues on to successive tests in the
|
||||||
// test case, if any:
|
// test case, if any:
|
||||||
# define EXPECT_DEATH(statement, regex) \
|
# define EXPECT_DEATH(statement, regex) \
|
||||||
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
|
||||||
|
|
||||||
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
||||||
|
|
||||||
// Tests that an exit code describes a normal exit with a given exit code.
|
// Tests that an exit code describes a normal exit with a given exit code.
|
||||||
class GTEST_API_ ExitedWithCode {
|
class GTEST_API_ ExitedWithCode {
|
||||||
public:
|
public:
|
||||||
explicit ExitedWithCode(int exit_code);
|
explicit ExitedWithCode(int exit_code);
|
||||||
bool operator()(int exit_status) const;
|
bool operator()(int exit_status) const;
|
||||||
private:
|
private:
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
void operator=(const ExitedWithCode& other);
|
void operator=(const ExitedWithCode& other);
|
||||||
|
|
||||||
const int exit_code_;
|
const int exit_code_;
|
||||||
};
|
};
|
||||||
|
|
||||||
# if !GTEST_OS_WINDOWS
|
# if !GTEST_OS_WINDOWS
|
||||||
// Tests that an exit code describes an exit due to termination by a
|
// Tests that an exit code describes an exit due to termination by a
|
||||||
// given signal.
|
// given signal.
|
||||||
class GTEST_API_ KilledBySignal {
|
class GTEST_API_ KilledBySignal {
|
||||||
public:
|
public:
|
||||||
explicit KilledBySignal(int signum);
|
explicit KilledBySignal(int signum);
|
||||||
bool operator()(int exit_status) const;
|
bool operator()(int exit_status) const;
|
||||||
private:
|
private:
|
||||||
const int signum_;
|
const int signum_;
|
||||||
};
|
};
|
||||||
# endif // !GTEST_OS_WINDOWS
|
# endif // !GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
|
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
|
||||||
// The death testing framework causes this to have interesting semantics,
|
// The death testing framework causes this to have interesting semantics,
|
||||||
// since the sideeffects of the call are only visible in opt mode, and not
|
// since the sideeffects of the call are only visible in opt mode, and not
|
||||||
// in debug mode.
|
// in debug mode.
|
||||||
//
|
//
|
||||||
// In practice, this can be used to test functions that utilize the
|
// In practice, this can be used to test functions that utilize the
|
||||||
// LOG(DFATAL) macro using the following style:
|
// LOG(DFATAL) macro using the following style:
|
||||||
//
|
//
|
||||||
// int DieInDebugOr12(int* sideeffect) {
|
// int DieInDebugOr12(int* sideeffect) {
|
||||||
// if (sideeffect) {
|
// if (sideeffect) {
|
||||||
// *sideeffect = 12;
|
// *sideeffect = 12;
|
||||||
// }
|
// }
|
||||||
// LOG(DFATAL) << "death";
|
// LOG(DFATAL) << "death";
|
||||||
// return 12;
|
// return 12;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
|
// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
|
||||||
// int sideeffect = 0;
|
// int sideeffect = 0;
|
||||||
// // Only asserts in dbg.
|
// // Only asserts in dbg.
|
||||||
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
|
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
|
||||||
//
|
//
|
||||||
// #ifdef NDEBUG
|
// #ifdef NDEBUG
|
||||||
// // opt-mode has sideeffect visible.
|
// // opt-mode has sideeffect visible.
|
||||||
// EXPECT_EQ(12, sideeffect);
|
// EXPECT_EQ(12, sideeffect);
|
||||||
// #else
|
// #else
|
||||||
// // dbg-mode no visible sideeffect.
|
// // dbg-mode no visible sideeffect.
|
||||||
// EXPECT_EQ(0, sideeffect);
|
// EXPECT_EQ(0, sideeffect);
|
||||||
// #endif
|
// #endif
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// This will assert that DieInDebugReturn12InOpt() crashes in debug
|
// This will assert that DieInDebugReturn12InOpt() crashes in debug
|
||||||
// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
|
// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
|
||||||
// appropriate fallback value (12 in this case) in opt mode. If you
|
// appropriate fallback value (12 in this case) in opt mode. If you
|
||||||
// need to test that a function has appropriate side-effects in opt
|
// need to test that a function has appropriate side-effects in opt
|
||||||
// mode, include assertions against the side-effects. A general
|
// mode, include assertions against the side-effects. A general
|
||||||
// pattern for this is:
|
// pattern for this is:
|
||||||
//
|
//
|
||||||
// EXPECT_DEBUG_DEATH({
|
// EXPECT_DEBUG_DEATH({
|
||||||
// // Side-effects here will have an effect after this statement in
|
// // Side-effects here will have an effect after this statement in
|
||||||
// // opt mode, but none in debug mode.
|
// // opt mode, but none in debug mode.
|
||||||
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
|
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
|
||||||
// }, "death");
|
// }, "death");
|
||||||
//
|
//
|
||||||
# ifdef NDEBUG
|
# ifdef NDEBUG
|
||||||
|
|
||||||
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||||
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
||||||
|
|
||||||
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||||
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
GTEST_EXECUTE_STATEMENT_(statement, regex)
|
||||||
|
|
||||||
# else
|
# else
|
||||||
|
|
||||||
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
# define EXPECT_DEBUG_DEATH(statement, regex) \
|
||||||
EXPECT_DEATH(statement, regex)
|
EXPECT_DEATH(statement, regex)
|
||||||
|
|
||||||
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
# define ASSERT_DEBUG_DEATH(statement, regex) \
|
||||||
ASSERT_DEATH(statement, regex)
|
ASSERT_DEATH(statement, regex)
|
||||||
|
|
||||||
# endif // NDEBUG for EXPECT_DEBUG_DEATH
|
# endif // NDEBUG for EXPECT_DEBUG_DEATH
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
|
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
|
||||||
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
|
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
|
||||||
// death tests are supported; otherwise they just issue a warning. This is
|
// death tests are supported; otherwise they just issue a warning. This is
|
||||||
// useful when you are combining death test assertions with normal test
|
// useful when you are combining death test assertions with normal test
|
||||||
// assertions in one test.
|
// assertions in one test.
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
EXPECT_DEATH(statement, regex)
|
EXPECT_DEATH(statement, regex)
|
||||||
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
ASSERT_DEATH(statement, regex)
|
ASSERT_DEATH(statement, regex)
|
||||||
#else
|
#else
|
||||||
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
|
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
|
||||||
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
|
||||||
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
|
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
|
||||||
@@ -1,250 +1,250 @@
|
|||||||
// Copyright 2005, Google Inc.
|
// Copyright 2005, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
//
|
//
|
||||||
// The Google C++ Testing Framework (Google Test)
|
// The Google C++ Testing Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines the Message class.
|
// This header file defines the Message class.
|
||||||
//
|
//
|
||||||
// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
|
// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
|
||||||
// leave some internal implementation details in this header file.
|
// leave some internal implementation details in this header file.
|
||||||
// They are clearly marked by comments like this:
|
// They are clearly marked by comments like this:
|
||||||
//
|
//
|
||||||
// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
//
|
//
|
||||||
// Such code is NOT meant to be used by a user directly, and is subject
|
// Such code is NOT meant to be used by a user directly, and is subject
|
||||||
// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
|
// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
|
||||||
// program!
|
// program!
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
// Ensures that there is at least one operator<< in the global namespace.
|
// Ensures that there is at least one operator<< in the global namespace.
|
||||||
// See Message& operator<<(...) below for why.
|
// See Message& operator<<(...) below for why.
|
||||||
void operator<<(const testing::internal::Secret&, int);
|
void operator<<(const testing::internal::Secret&, int);
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// The Message class works like an ostream repeater.
|
// The Message class works like an ostream repeater.
|
||||||
//
|
//
|
||||||
// Typical usage:
|
// Typical usage:
|
||||||
//
|
//
|
||||||
// 1. You stream a bunch of values to a Message object.
|
// 1. You stream a bunch of values to a Message object.
|
||||||
// It will remember the text in a stringstream.
|
// It will remember the text in a stringstream.
|
||||||
// 2. Then you stream the Message object to an ostream.
|
// 2. Then you stream the Message object to an ostream.
|
||||||
// This causes the text in the Message to be streamed
|
// This causes the text in the Message to be streamed
|
||||||
// to the ostream.
|
// to the ostream.
|
||||||
//
|
//
|
||||||
// For example;
|
// For example;
|
||||||
//
|
//
|
||||||
// testing::Message foo;
|
// testing::Message foo;
|
||||||
// foo << 1 << " != " << 2;
|
// foo << 1 << " != " << 2;
|
||||||
// std::cout << foo;
|
// std::cout << foo;
|
||||||
//
|
//
|
||||||
// will print "1 != 2".
|
// will print "1 != 2".
|
||||||
//
|
//
|
||||||
// Message is not intended to be inherited from. In particular, its
|
// Message is not intended to be inherited from. In particular, its
|
||||||
// destructor is not virtual.
|
// destructor is not virtual.
|
||||||
//
|
//
|
||||||
// Note that stringstream behaves differently in gcc and in MSVC. You
|
// Note that stringstream behaves differently in gcc and in MSVC. You
|
||||||
// can stream a NULL char pointer to it in the former, but not in the
|
// can stream a NULL char pointer to it in the former, but not in the
|
||||||
// latter (it causes an access violation if you do). The Message
|
// latter (it causes an access violation if you do). The Message
|
||||||
// class hides this difference by treating a NULL char pointer as
|
// class hides this difference by treating a NULL char pointer as
|
||||||
// "(null)".
|
// "(null)".
|
||||||
class GTEST_API_ Message {
|
class GTEST_API_ Message {
|
||||||
private:
|
private:
|
||||||
// The type of basic IO manipulators (endl, ends, and flush) for
|
// The type of basic IO manipulators (endl, ends, and flush) for
|
||||||
// narrow streams.
|
// narrow streams.
|
||||||
typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
|
typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructs an empty Message.
|
// Constructs an empty Message.
|
||||||
Message();
|
Message();
|
||||||
|
|
||||||
// Copy constructor.
|
// Copy constructor.
|
||||||
Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
|
Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
|
||||||
*ss_ << msg.GetString();
|
*ss_ << msg.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a Message from a C-string.
|
// Constructs a Message from a C-string.
|
||||||
explicit Message(const char* str) : ss_(new ::std::stringstream) {
|
explicit Message(const char* str) : ss_(new ::std::stringstream) {
|
||||||
*ss_ << str;
|
*ss_ << str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_OS_SYMBIAN
|
#if GTEST_OS_SYMBIAN
|
||||||
// Streams a value (either a pointer or not) to this object.
|
// Streams a value (either a pointer or not) to this object.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(const T& value) {
|
inline Message& operator <<(const T& value) {
|
||||||
StreamHelper(typename internal::is_pointer<T>::type(), value);
|
StreamHelper(typename internal::is_pointer<T>::type(), value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Streams a non-pointer value to this object.
|
// Streams a non-pointer value to this object.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(const T& val) {
|
inline Message& operator <<(const T& val) {
|
||||||
// Some libraries overload << for STL containers. These
|
// Some libraries overload << for STL containers. These
|
||||||
// overloads are defined in the global namespace instead of ::std.
|
// overloads are defined in the global namespace instead of ::std.
|
||||||
//
|
//
|
||||||
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
|
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
|
||||||
// overloads are visible in either the std namespace or the global
|
// overloads are visible in either the std namespace or the global
|
||||||
// namespace, but not other namespaces, including the testing
|
// namespace, but not other namespaces, including the testing
|
||||||
// namespace which Google Test's Message class is in.
|
// namespace which Google Test's Message class is in.
|
||||||
//
|
//
|
||||||
// To allow STL containers (and other types that has a << operator
|
// To allow STL containers (and other types that has a << operator
|
||||||
// defined in the global namespace) to be used in Google Test
|
// defined in the global namespace) to be used in Google Test
|
||||||
// assertions, testing::Message must access the custom << operator
|
// assertions, testing::Message must access the custom << operator
|
||||||
// from the global namespace. With this using declaration,
|
// from the global namespace. With this using declaration,
|
||||||
// overloads of << defined in the global namespace and those
|
// overloads of << defined in the global namespace and those
|
||||||
// visible via Koenig lookup are both exposed in this function.
|
// visible via Koenig lookup are both exposed in this function.
|
||||||
using ::operator <<;
|
using ::operator <<;
|
||||||
*ss_ << val;
|
*ss_ << val;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Streams a pointer value to this object.
|
// Streams a pointer value to this object.
|
||||||
//
|
//
|
||||||
// This function is an overload of the previous one. When you
|
// This function is an overload of the previous one. When you
|
||||||
// stream a pointer to a Message, this definition will be used as it
|
// stream a pointer to a Message, this definition will be used as it
|
||||||
// is more specialized. (The C++ Standard, section
|
// is more specialized. (The C++ Standard, section
|
||||||
// [temp.func.order].) If you stream a non-pointer, then the
|
// [temp.func.order].) If you stream a non-pointer, then the
|
||||||
// previous definition will be used.
|
// previous definition will be used.
|
||||||
//
|
//
|
||||||
// The reason for this overload is that streaming a NULL pointer to
|
// The reason for this overload is that streaming a NULL pointer to
|
||||||
// ostream is undefined behavior. Depending on the compiler, you
|
// ostream is undefined behavior. Depending on the compiler, you
|
||||||
// may get "0", "(nil)", "(null)", or an access violation. To
|
// may get "0", "(nil)", "(null)", or an access violation. To
|
||||||
// ensure consistent result across compilers, we always treat NULL
|
// ensure consistent result across compilers, we always treat NULL
|
||||||
// as "(null)".
|
// as "(null)".
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Message& operator <<(T* const& pointer) { // NOLINT
|
inline Message& operator <<(T* const& pointer) { // NOLINT
|
||||||
if (pointer == NULL) {
|
if (pointer == NULL) {
|
||||||
*ss_ << "(null)";
|
*ss_ << "(null)";
|
||||||
} else {
|
} else {
|
||||||
*ss_ << pointer;
|
*ss_ << pointer;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif // GTEST_OS_SYMBIAN
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
|
||||||
// Since the basic IO manipulators are overloaded for both narrow
|
// Since the basic IO manipulators are overloaded for both narrow
|
||||||
// and wide streams, we have to provide this specialized definition
|
// and wide streams, we have to provide this specialized definition
|
||||||
// of operator <<, even though its body is the same as the
|
// of operator <<, even though its body is the same as the
|
||||||
// templatized version above. Without this definition, streaming
|
// templatized version above. Without this definition, streaming
|
||||||
// endl or other basic IO manipulators to Message will confuse the
|
// endl or other basic IO manipulators to Message will confuse the
|
||||||
// compiler.
|
// compiler.
|
||||||
Message& operator <<(BasicNarrowIoManip val) {
|
Message& operator <<(BasicNarrowIoManip val) {
|
||||||
*ss_ << val;
|
*ss_ << val;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instead of 1/0, we want to see true/false for bool values.
|
// Instead of 1/0, we want to see true/false for bool values.
|
||||||
Message& operator <<(bool b) {
|
Message& operator <<(bool b) {
|
||||||
return *this << (b ? "true" : "false");
|
return *this << (b ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
// These two overloads allow streaming a wide C string to a Message
|
// These two overloads allow streaming a wide C string to a Message
|
||||||
// using the UTF-8 encoding.
|
// using the UTF-8 encoding.
|
||||||
Message& operator <<(const wchar_t* wide_c_str);
|
Message& operator <<(const wchar_t* wide_c_str);
|
||||||
Message& operator <<(wchar_t* wide_c_str);
|
Message& operator <<(wchar_t* wide_c_str);
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
// Converts the given wide string to a narrow string using the UTF-8
|
// Converts the given wide string to a narrow string using the UTF-8
|
||||||
// encoding, and streams the result to this Message object.
|
// encoding, and streams the result to this Message object.
|
||||||
Message& operator <<(const ::std::wstring& wstr);
|
Message& operator <<(const ::std::wstring& wstr);
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
#if GTEST_HAS_GLOBAL_WSTRING
|
#if GTEST_HAS_GLOBAL_WSTRING
|
||||||
// Converts the given wide string to a narrow string using the UTF-8
|
// Converts the given wide string to a narrow string using the UTF-8
|
||||||
// encoding, and streams the result to this Message object.
|
// encoding, and streams the result to this Message object.
|
||||||
Message& operator <<(const ::wstring& wstr);
|
Message& operator <<(const ::wstring& wstr);
|
||||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||||
|
|
||||||
// Gets the text streamed to this object so far as an std::string.
|
// Gets the text streamed to this object so far as an std::string.
|
||||||
// Each '\0' character in the buffer is replaced with "\\0".
|
// Each '\0' character in the buffer is replaced with "\\0".
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
std::string GetString() const;
|
std::string GetString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#if GTEST_OS_SYMBIAN
|
#if GTEST_OS_SYMBIAN
|
||||||
// These are needed as the Nokia Symbian Compiler cannot decide between
|
// These are needed as the Nokia Symbian Compiler cannot decide between
|
||||||
// const T& and const T* in a function template. The Nokia compiler _can_
|
// const T& and const T* in a function template. The Nokia compiler _can_
|
||||||
// decide between class template specializations for T and T*, so a
|
// decide between class template specializations for T and T*, so a
|
||||||
// tr1::type_traits-like is_pointer works, and we can overload on that.
|
// tr1::type_traits-like is_pointer works, and we can overload on that.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
|
inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
|
||||||
if (pointer == NULL) {
|
if (pointer == NULL) {
|
||||||
*ss_ << "(null)";
|
*ss_ << "(null)";
|
||||||
} else {
|
} else {
|
||||||
*ss_ << pointer;
|
*ss_ << pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void StreamHelper(internal::false_type /*is_pointer*/,
|
inline void StreamHelper(internal::false_type /*is_pointer*/,
|
||||||
const T& value) {
|
const T& value) {
|
||||||
// See the comments in Message& operator <<(const T&) above for why
|
// See the comments in Message& operator <<(const T&) above for why
|
||||||
// we need this using statement.
|
// we need this using statement.
|
||||||
using ::operator <<;
|
using ::operator <<;
|
||||||
*ss_ << value;
|
*ss_ << value;
|
||||||
}
|
}
|
||||||
#endif // GTEST_OS_SYMBIAN
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
|
||||||
// We'll hold the text streamed to this object here.
|
// We'll hold the text streamed to this object here.
|
||||||
const internal::scoped_ptr< ::std::stringstream> ss_;
|
const internal::scoped_ptr< ::std::stringstream> ss_;
|
||||||
|
|
||||||
// We declare (but don't implement) this to prevent the compiler
|
// We declare (but don't implement) this to prevent the compiler
|
||||||
// from implementing the assignment operator.
|
// from implementing the assignment operator.
|
||||||
void operator=(const Message&);
|
void operator=(const Message&);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Streams a Message to an ostream.
|
// Streams a Message to an ostream.
|
||||||
inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
|
inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
|
||||||
return os << sb.GetString();
|
return os << sb.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Converts a streamable value to an std::string. A NULL pointer is
|
// Converts a streamable value to an std::string. A NULL pointer is
|
||||||
// converted to "(null)". When the input value is a ::string,
|
// converted to "(null)". When the input value is a ::string,
|
||||||
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
// ::std::string, ::wstring, or ::std::wstring object, each NUL
|
||||||
// character in it is replaced with "\\0".
|
// character in it is replaced with "\\0".
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string StreamableToString(const T& streamable) {
|
std::string StreamableToString(const T& streamable) {
|
||||||
return (Message() << streamable).GetString();
|
return (Message() << streamable).GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,487 +1,487 @@
|
|||||||
$$ -*- mode: c++; -*-
|
$$ -*- mode: c++; -*-
|
||||||
$var n = 50 $$ Maximum length of Values arguments we want to support.
|
$var n = 50 $$ Maximum length of Values arguments we want to support.
|
||||||
$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
|
$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
|
||||||
// Copyright 2008, Google Inc.
|
// Copyright 2008, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Authors: vladl@google.com (Vlad Losev)
|
// Authors: vladl@google.com (Vlad Losev)
|
||||||
//
|
//
|
||||||
// Macros and functions for implementing parameterized tests
|
// Macros and functions for implementing parameterized tests
|
||||||
// in Google C++ Testing Framework (Google Test)
|
// in Google C++ Testing Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||||
//
|
//
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||||
|
|
||||||
|
|
||||||
// Value-parameterized tests allow you to test your code with different
|
// Value-parameterized tests allow you to test your code with different
|
||||||
// parameters without writing multiple copies of the same test.
|
// parameters without writing multiple copies of the same test.
|
||||||
//
|
//
|
||||||
// Here is how you use value-parameterized tests:
|
// Here is how you use value-parameterized tests:
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
// To write value-parameterized tests, first you should define a fixture
|
// To write value-parameterized tests, first you should define a fixture
|
||||||
// class. It is usually derived from testing::TestWithParam<T> (see below for
|
// class. It is usually derived from testing::TestWithParam<T> (see below for
|
||||||
// another inheritance scheme that's sometimes useful in more complicated
|
// another inheritance scheme that's sometimes useful in more complicated
|
||||||
// class hierarchies), where the type of your parameter values.
|
// class hierarchies), where the type of your parameter values.
|
||||||
// TestWithParam<T> is itself derived from testing::Test. T can be any
|
// TestWithParam<T> is itself derived from testing::Test. T can be any
|
||||||
// copyable type. If it's a raw pointer, you are responsible for managing the
|
// copyable type. If it's a raw pointer, you are responsible for managing the
|
||||||
// lifespan of the pointed values.
|
// lifespan of the pointed values.
|
||||||
|
|
||||||
class FooTest : public ::testing::TestWithParam<const char*> {
|
class FooTest : public ::testing::TestWithParam<const char*> {
|
||||||
// You can implement all the usual class fixture members here.
|
// You can implement all the usual class fixture members here.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Then, use the TEST_P macro to define as many parameterized tests
|
// Then, use the TEST_P macro to define as many parameterized tests
|
||||||
// for this fixture as you want. The _P suffix is for "parameterized"
|
// for this fixture as you want. The _P suffix is for "parameterized"
|
||||||
// or "pattern", whichever you prefer to think.
|
// or "pattern", whichever you prefer to think.
|
||||||
|
|
||||||
TEST_P(FooTest, DoesBlah) {
|
TEST_P(FooTest, DoesBlah) {
|
||||||
// Inside a test, access the test parameter with the GetParam() method
|
// Inside a test, access the test parameter with the GetParam() method
|
||||||
// of the TestWithParam<T> class:
|
// of the TestWithParam<T> class:
|
||||||
EXPECT_TRUE(foo.Blah(GetParam()));
|
EXPECT_TRUE(foo.Blah(GetParam()));
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(FooTest, HasBlahBlah) {
|
TEST_P(FooTest, HasBlahBlah) {
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
|
// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
|
||||||
// case with any set of parameters you want. Google Test defines a number
|
// case with any set of parameters you want. Google Test defines a number
|
||||||
// of functions for generating test parameters. They return what we call
|
// of functions for generating test parameters. They return what we call
|
||||||
// (surprise!) parameter generators. Here is a summary of them, which
|
// (surprise!) parameter generators. Here is a summary of them, which
|
||||||
// are all in the testing namespace:
|
// are all in the testing namespace:
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Range(begin, end [, step]) - Yields values {begin, begin+step,
|
// Range(begin, end [, step]) - Yields values {begin, begin+step,
|
||||||
// begin+step+step, ...}. The values do not
|
// begin+step+step, ...}. The values do not
|
||||||
// include end. step defaults to 1.
|
// include end. step defaults to 1.
|
||||||
// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
|
// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
|
||||||
// ValuesIn(container) - Yields values from a C-style array, an STL
|
// ValuesIn(container) - Yields values from a C-style array, an STL
|
||||||
// ValuesIn(begin,end) container, or an iterator range [begin, end).
|
// ValuesIn(begin,end) container, or an iterator range [begin, end).
|
||||||
// Bool() - Yields sequence {false, true}.
|
// Bool() - Yields sequence {false, true}.
|
||||||
// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
|
// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
|
||||||
// for the math savvy) of the values generated
|
// for the math savvy) of the values generated
|
||||||
// by the N generators.
|
// by the N generators.
|
||||||
//
|
//
|
||||||
// For more details, see comments at the definitions of these functions below
|
// For more details, see comments at the definitions of these functions below
|
||||||
// in this file.
|
// in this file.
|
||||||
//
|
//
|
||||||
// The following statement will instantiate tests from the FooTest test case
|
// The following statement will instantiate tests from the FooTest test case
|
||||||
// each with parameter values "meeny", "miny", and "moe".
|
// each with parameter values "meeny", "miny", and "moe".
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(InstantiationName,
|
INSTANTIATE_TEST_CASE_P(InstantiationName,
|
||||||
FooTest,
|
FooTest,
|
||||||
Values("meeny", "miny", "moe"));
|
Values("meeny", "miny", "moe"));
|
||||||
|
|
||||||
// To distinguish different instances of the pattern, (yes, you
|
// To distinguish different instances of the pattern, (yes, you
|
||||||
// can instantiate it more then once) the first argument to the
|
// can instantiate it more then once) the first argument to the
|
||||||
// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
|
// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
|
||||||
// actual test case name. Remember to pick unique prefixes for different
|
// actual test case name. Remember to pick unique prefixes for different
|
||||||
// instantiations. The tests from the instantiation above will have
|
// instantiations. The tests from the instantiation above will have
|
||||||
// these names:
|
// these names:
|
||||||
//
|
//
|
||||||
// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
|
// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
|
||||||
// * InstantiationName/FooTest.DoesBlah/1 for "miny"
|
// * InstantiationName/FooTest.DoesBlah/1 for "miny"
|
||||||
// * InstantiationName/FooTest.DoesBlah/2 for "moe"
|
// * InstantiationName/FooTest.DoesBlah/2 for "moe"
|
||||||
// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
|
// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
|
||||||
// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
|
// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
|
||||||
// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
|
// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
|
||||||
//
|
//
|
||||||
// You can use these names in --gtest_filter.
|
// You can use these names in --gtest_filter.
|
||||||
//
|
//
|
||||||
// This statement will instantiate all tests from FooTest again, each
|
// This statement will instantiate all tests from FooTest again, each
|
||||||
// with parameter values "cat" and "dog":
|
// with parameter values "cat" and "dog":
|
||||||
|
|
||||||
const char* pets[] = {"cat", "dog"};
|
const char* pets[] = {"cat", "dog"};
|
||||||
INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
|
INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
|
||||||
|
|
||||||
// The tests from the instantiation above will have these names:
|
// The tests from the instantiation above will have these names:
|
||||||
//
|
//
|
||||||
// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
|
// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
|
||||||
// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
|
// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
|
||||||
// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
|
// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
|
||||||
// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
|
// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
|
||||||
//
|
//
|
||||||
// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
|
// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
|
||||||
// in the given test case, whether their definitions come before or
|
// in the given test case, whether their definitions come before or
|
||||||
// AFTER the INSTANTIATE_TEST_CASE_P statement.
|
// AFTER the INSTANTIATE_TEST_CASE_P statement.
|
||||||
//
|
//
|
||||||
// Please also note that generator expressions (including parameters to the
|
// Please also note that generator expressions (including parameters to the
|
||||||
// generators) are evaluated in InitGoogleTest(), after main() has started.
|
// generators) are evaluated in InitGoogleTest(), after main() has started.
|
||||||
// This allows the user on one hand, to adjust generator parameters in order
|
// This allows the user on one hand, to adjust generator parameters in order
|
||||||
// to dynamically determine a set of tests to run and on the other hand,
|
// to dynamically determine a set of tests to run and on the other hand,
|
||||||
// give the user a chance to inspect the generated tests with Google Test
|
// give the user a chance to inspect the generated tests with Google Test
|
||||||
// reflection API before RUN_ALL_TESTS() is executed.
|
// reflection API before RUN_ALL_TESTS() is executed.
|
||||||
//
|
//
|
||||||
// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
|
// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
|
||||||
// for more examples.
|
// for more examples.
|
||||||
//
|
//
|
||||||
// In the future, we plan to publish the API for defining new parameter
|
// In the future, we plan to publish the API for defining new parameter
|
||||||
// generators. But for now this interface remains part of the internal
|
// generators. But for now this interface remains part of the internal
|
||||||
// implementation and is subject to change.
|
// implementation and is subject to change.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// A parameterized test fixture must be derived from testing::Test and from
|
// A parameterized test fixture must be derived from testing::Test and from
|
||||||
// testing::WithParamInterface<T>, where T is the type of the parameter
|
// testing::WithParamInterface<T>, where T is the type of the parameter
|
||||||
// values. Inheriting from TestWithParam<T> satisfies that requirement because
|
// values. Inheriting from TestWithParam<T> satisfies that requirement because
|
||||||
// TestWithParam<T> inherits from both Test and WithParamInterface. In more
|
// TestWithParam<T> inherits from both Test and WithParamInterface. In more
|
||||||
// complicated hierarchies, however, it is occasionally useful to inherit
|
// complicated hierarchies, however, it is occasionally useful to inherit
|
||||||
// separately from Test and WithParamInterface. For example:
|
// separately from Test and WithParamInterface. For example:
|
||||||
|
|
||||||
class BaseTest : public ::testing::Test {
|
class BaseTest : public ::testing::Test {
|
||||||
// You can inherit all the usual members for a non-parameterized test
|
// You can inherit all the usual members for a non-parameterized test
|
||||||
// fixture here.
|
// fixture here.
|
||||||
};
|
};
|
||||||
|
|
||||||
class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
|
class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
|
||||||
// The usual test fixture members go here too.
|
// The usual test fixture members go here too.
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(BaseTest, HasFoo) {
|
TEST_F(BaseTest, HasFoo) {
|
||||||
// This is an ordinary non-parameterized test.
|
// This is an ordinary non-parameterized test.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(DerivedTest, DoesBlah) {
|
TEST_P(DerivedTest, DoesBlah) {
|
||||||
// GetParam works just the same here as if you inherit from TestWithParam.
|
// GetParam works just the same here as if you inherit from TestWithParam.
|
||||||
EXPECT_TRUE(foo.Blah(GetParam()));
|
EXPECT_TRUE(foo.Blah(GetParam()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#if !GTEST_OS_SYMBIAN
|
#if !GTEST_OS_SYMBIAN
|
||||||
# include <utility>
|
# include <utility>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||||
// *unconditionally*. Therefore these #includes cannot be moved
|
// *unconditionally*. Therefore these #includes cannot be moved
|
||||||
// inside #if GTEST_HAS_PARAM_TEST.
|
// inside #if GTEST_HAS_PARAM_TEST.
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
#include "gtest/internal/gtest-param-util.h"
|
#include "gtest/internal/gtest-param-util.h"
|
||||||
#include "gtest/internal/gtest-param-util-generated.h"
|
#include "gtest/internal/gtest-param-util-generated.h"
|
||||||
|
|
||||||
#if GTEST_HAS_PARAM_TEST
|
#if GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// Functions producing parameter generators.
|
// Functions producing parameter generators.
|
||||||
//
|
//
|
||||||
// Google Test uses these generators to produce parameters for value-
|
// Google Test uses these generators to produce parameters for value-
|
||||||
// parameterized tests. When a parameterized test case is instantiated
|
// parameterized tests. When a parameterized test case is instantiated
|
||||||
// with a particular generator, Google Test creates and runs tests
|
// with a particular generator, Google Test creates and runs tests
|
||||||
// for each element in the sequence produced by the generator.
|
// for each element in the sequence produced by the generator.
|
||||||
//
|
//
|
||||||
// In the following sample, tests from test case FooTest are instantiated
|
// In the following sample, tests from test case FooTest are instantiated
|
||||||
// each three times with parameter values 3, 5, and 8:
|
// each three times with parameter values 3, 5, and 8:
|
||||||
//
|
//
|
||||||
// class FooTest : public TestWithParam<int> { ... };
|
// class FooTest : public TestWithParam<int> { ... };
|
||||||
//
|
//
|
||||||
// TEST_P(FooTest, TestThis) {
|
// TEST_P(FooTest, TestThis) {
|
||||||
// }
|
// }
|
||||||
// TEST_P(FooTest, TestThat) {
|
// TEST_P(FooTest, TestThat) {
|
||||||
// }
|
// }
|
||||||
// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
|
// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
|
||||||
//
|
//
|
||||||
|
|
||||||
// Range() returns generators providing sequences of values in a range.
|
// Range() returns generators providing sequences of values in a range.
|
||||||
//
|
//
|
||||||
// Synopsis:
|
// Synopsis:
|
||||||
// Range(start, end)
|
// Range(start, end)
|
||||||
// - returns a generator producing a sequence of values {start, start+1,
|
// - returns a generator producing a sequence of values {start, start+1,
|
||||||
// start+2, ..., }.
|
// start+2, ..., }.
|
||||||
// Range(start, end, step)
|
// Range(start, end, step)
|
||||||
// - returns a generator producing a sequence of values {start, start+step,
|
// - returns a generator producing a sequence of values {start, start+step,
|
||||||
// start+step+step, ..., }.
|
// start+step+step, ..., }.
|
||||||
// Notes:
|
// Notes:
|
||||||
// * The generated sequences never include end. For example, Range(1, 5)
|
// * The generated sequences never include end. For example, Range(1, 5)
|
||||||
// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
|
// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
|
||||||
// returns a generator producing {1, 3, 5, 7}.
|
// returns a generator producing {1, 3, 5, 7}.
|
||||||
// * start and end must have the same type. That type may be any integral or
|
// * start and end must have the same type. That type may be any integral or
|
||||||
// floating-point type or a user defined type satisfying these conditions:
|
// floating-point type or a user defined type satisfying these conditions:
|
||||||
// * It must be assignable (have operator=() defined).
|
// * It must be assignable (have operator=() defined).
|
||||||
// * It must have operator+() (operator+(int-compatible type) for
|
// * It must have operator+() (operator+(int-compatible type) for
|
||||||
// two-operand version).
|
// two-operand version).
|
||||||
// * It must have operator<() defined.
|
// * It must have operator<() defined.
|
||||||
// Elements in the resulting sequences will also have that type.
|
// Elements in the resulting sequences will also have that type.
|
||||||
// * Condition start < end must be satisfied in order for resulting sequences
|
// * Condition start < end must be satisfied in order for resulting sequences
|
||||||
// to contain any elements.
|
// to contain any elements.
|
||||||
//
|
//
|
||||||
template <typename T, typename IncrementT>
|
template <typename T, typename IncrementT>
|
||||||
internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
|
internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
|
||||||
return internal::ParamGenerator<T>(
|
return internal::ParamGenerator<T>(
|
||||||
new internal::RangeGenerator<T, IncrementT>(start, end, step));
|
new internal::RangeGenerator<T, IncrementT>(start, end, step));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
internal::ParamGenerator<T> Range(T start, T end) {
|
internal::ParamGenerator<T> Range(T start, T end) {
|
||||||
return Range(start, end, 1);
|
return Range(start, end, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValuesIn() function allows generation of tests with parameters coming from
|
// ValuesIn() function allows generation of tests with parameters coming from
|
||||||
// a container.
|
// a container.
|
||||||
//
|
//
|
||||||
// Synopsis:
|
// Synopsis:
|
||||||
// ValuesIn(const T (&array)[N])
|
// ValuesIn(const T (&array)[N])
|
||||||
// - returns a generator producing sequences with elements from
|
// - returns a generator producing sequences with elements from
|
||||||
// a C-style array.
|
// a C-style array.
|
||||||
// ValuesIn(const Container& container)
|
// ValuesIn(const Container& container)
|
||||||
// - returns a generator producing sequences with elements from
|
// - returns a generator producing sequences with elements from
|
||||||
// an STL-style container.
|
// an STL-style container.
|
||||||
// ValuesIn(Iterator begin, Iterator end)
|
// ValuesIn(Iterator begin, Iterator end)
|
||||||
// - returns a generator producing sequences with elements from
|
// - returns a generator producing sequences with elements from
|
||||||
// a range [begin, end) defined by a pair of STL-style iterators. These
|
// a range [begin, end) defined by a pair of STL-style iterators. These
|
||||||
// iterators can also be plain C pointers.
|
// iterators can also be plain C pointers.
|
||||||
//
|
//
|
||||||
// Please note that ValuesIn copies the values from the containers
|
// Please note that ValuesIn copies the values from the containers
|
||||||
// passed in and keeps them to generate tests in RUN_ALL_TESTS().
|
// passed in and keeps them to generate tests in RUN_ALL_TESTS().
|
||||||
//
|
//
|
||||||
// Examples:
|
// Examples:
|
||||||
//
|
//
|
||||||
// This instantiates tests from test case StringTest
|
// This instantiates tests from test case StringTest
|
||||||
// each with C-string values of "foo", "bar", and "baz":
|
// each with C-string values of "foo", "bar", and "baz":
|
||||||
//
|
//
|
||||||
// const char* strings[] = {"foo", "bar", "baz"};
|
// const char* strings[] = {"foo", "bar", "baz"};
|
||||||
// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
|
// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
|
||||||
//
|
//
|
||||||
// This instantiates tests from test case StlStringTest
|
// This instantiates tests from test case StlStringTest
|
||||||
// each with STL strings with values "a" and "b":
|
// each with STL strings with values "a" and "b":
|
||||||
//
|
//
|
||||||
// ::std::vector< ::std::string> GetParameterStrings() {
|
// ::std::vector< ::std::string> GetParameterStrings() {
|
||||||
// ::std::vector< ::std::string> v;
|
// ::std::vector< ::std::string> v;
|
||||||
// v.push_back("a");
|
// v.push_back("a");
|
||||||
// v.push_back("b");
|
// v.push_back("b");
|
||||||
// return v;
|
// return v;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// INSTANTIATE_TEST_CASE_P(CharSequence,
|
// INSTANTIATE_TEST_CASE_P(CharSequence,
|
||||||
// StlStringTest,
|
// StlStringTest,
|
||||||
// ValuesIn(GetParameterStrings()));
|
// ValuesIn(GetParameterStrings()));
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// This will also instantiate tests from CharTest
|
// This will also instantiate tests from CharTest
|
||||||
// each with parameter values 'a' and 'b':
|
// each with parameter values 'a' and 'b':
|
||||||
//
|
//
|
||||||
// ::std::list<char> GetParameterChars() {
|
// ::std::list<char> GetParameterChars() {
|
||||||
// ::std::list<char> list;
|
// ::std::list<char> list;
|
||||||
// list.push_back('a');
|
// list.push_back('a');
|
||||||
// list.push_back('b');
|
// list.push_back('b');
|
||||||
// return list;
|
// return list;
|
||||||
// }
|
// }
|
||||||
// ::std::list<char> l = GetParameterChars();
|
// ::std::list<char> l = GetParameterChars();
|
||||||
// INSTANTIATE_TEST_CASE_P(CharSequence2,
|
// INSTANTIATE_TEST_CASE_P(CharSequence2,
|
||||||
// CharTest,
|
// CharTest,
|
||||||
// ValuesIn(l.begin(), l.end()));
|
// ValuesIn(l.begin(), l.end()));
|
||||||
//
|
//
|
||||||
template <typename ForwardIterator>
|
template <typename ForwardIterator>
|
||||||
internal::ParamGenerator<
|
internal::ParamGenerator<
|
||||||
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
|
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
|
||||||
ValuesIn(ForwardIterator begin, ForwardIterator end) {
|
ValuesIn(ForwardIterator begin, ForwardIterator end) {
|
||||||
typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
|
typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
|
||||||
::value_type ParamType;
|
::value_type ParamType;
|
||||||
return internal::ParamGenerator<ParamType>(
|
return internal::ParamGenerator<ParamType>(
|
||||||
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
|
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
|
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
|
||||||
return ValuesIn(array, array + N);
|
return ValuesIn(array, array + N);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Container>
|
template <class Container>
|
||||||
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
||||||
const Container& container) {
|
const Container& container) {
|
||||||
return ValuesIn(container.begin(), container.end());
|
return ValuesIn(container.begin(), container.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values() allows generating tests from explicitly specified list of
|
// Values() allows generating tests from explicitly specified list of
|
||||||
// parameters.
|
// parameters.
|
||||||
//
|
//
|
||||||
// Synopsis:
|
// Synopsis:
|
||||||
// Values(T v1, T v2, ..., T vN)
|
// Values(T v1, T v2, ..., T vN)
|
||||||
// - returns a generator producing sequences with elements v1, v2, ..., vN.
|
// - returns a generator producing sequences with elements v1, v2, ..., vN.
|
||||||
//
|
//
|
||||||
// For example, this instantiates tests from test case BarTest each
|
// For example, this instantiates tests from test case BarTest each
|
||||||
// with values "one", "two", and "three":
|
// with values "one", "two", and "three":
|
||||||
//
|
//
|
||||||
// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
|
// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
|
||||||
//
|
//
|
||||||
// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
|
// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
|
||||||
// The exact type of values will depend on the type of parameter in BazTest.
|
// The exact type of values will depend on the type of parameter in BazTest.
|
||||||
//
|
//
|
||||||
// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
|
// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
|
||||||
//
|
//
|
||||||
// Currently, Values() supports from 1 to $n parameters.
|
// Currently, Values() supports from 1 to $n parameters.
|
||||||
//
|
//
|
||||||
$range i 1..n
|
$range i 1..n
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
template <$for j, [[typename T$j]]>
|
||||||
internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
|
internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
|
||||||
return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
|
return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
// Bool() allows generating tests with parameters in a set of (false, true).
|
// Bool() allows generating tests with parameters in a set of (false, true).
|
||||||
//
|
//
|
||||||
// Synopsis:
|
// Synopsis:
|
||||||
// Bool()
|
// Bool()
|
||||||
// - returns a generator producing sequences with elements {false, true}.
|
// - returns a generator producing sequences with elements {false, true}.
|
||||||
//
|
//
|
||||||
// It is useful when testing code that depends on Boolean flags. Combinations
|
// It is useful when testing code that depends on Boolean flags. Combinations
|
||||||
// of multiple flags can be tested when several Bool()'s are combined using
|
// of multiple flags can be tested when several Bool()'s are combined using
|
||||||
// Combine() function.
|
// Combine() function.
|
||||||
//
|
//
|
||||||
// In the following example all tests in the test case FlagDependentTest
|
// In the following example all tests in the test case FlagDependentTest
|
||||||
// will be instantiated twice with parameters false and true.
|
// will be instantiated twice with parameters false and true.
|
||||||
//
|
//
|
||||||
// class FlagDependentTest : public testing::TestWithParam<bool> {
|
// class FlagDependentTest : public testing::TestWithParam<bool> {
|
||||||
// virtual void SetUp() {
|
// virtual void SetUp() {
|
||||||
// external_flag = GetParam();
|
// external_flag = GetParam();
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
|
// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
|
||||||
//
|
//
|
||||||
inline internal::ParamGenerator<bool> Bool() {
|
inline internal::ParamGenerator<bool> Bool() {
|
||||||
return Values(false, true);
|
return Values(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
# if GTEST_HAS_COMBINE
|
# if GTEST_HAS_COMBINE
|
||||||
// Combine() allows the user to combine two or more sequences to produce
|
// Combine() allows the user to combine two or more sequences to produce
|
||||||
// values of a Cartesian product of those sequences' elements.
|
// values of a Cartesian product of those sequences' elements.
|
||||||
//
|
//
|
||||||
// Synopsis:
|
// Synopsis:
|
||||||
// Combine(gen1, gen2, ..., genN)
|
// Combine(gen1, gen2, ..., genN)
|
||||||
// - returns a generator producing sequences with elements coming from
|
// - returns a generator producing sequences with elements coming from
|
||||||
// the Cartesian product of elements from the sequences generated by
|
// the Cartesian product of elements from the sequences generated by
|
||||||
// gen1, gen2, ..., genN. The sequence elements will have a type of
|
// gen1, gen2, ..., genN. The sequence elements will have a type of
|
||||||
// tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
|
// tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
|
||||||
// of elements from sequences produces by gen1, gen2, ..., genN.
|
// of elements from sequences produces by gen1, gen2, ..., genN.
|
||||||
//
|
//
|
||||||
// Combine can have up to $maxtuple arguments. This number is currently limited
|
// Combine can have up to $maxtuple arguments. This number is currently limited
|
||||||
// by the maximum number of elements in the tuple implementation used by Google
|
// by the maximum number of elements in the tuple implementation used by Google
|
||||||
// Test.
|
// Test.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// This will instantiate tests in test case AnimalTest each one with
|
// This will instantiate tests in test case AnimalTest each one with
|
||||||
// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
|
// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
|
||||||
// tuple("dog", BLACK), and tuple("dog", WHITE):
|
// tuple("dog", BLACK), and tuple("dog", WHITE):
|
||||||
//
|
//
|
||||||
// enum Color { BLACK, GRAY, WHITE };
|
// enum Color { BLACK, GRAY, WHITE };
|
||||||
// class AnimalTest
|
// class AnimalTest
|
||||||
// : public testing::TestWithParam<tuple<const char*, Color> > {...};
|
// : public testing::TestWithParam<tuple<const char*, Color> > {...};
|
||||||
//
|
//
|
||||||
// TEST_P(AnimalTest, AnimalLooksNice) {...}
|
// TEST_P(AnimalTest, AnimalLooksNice) {...}
|
||||||
//
|
//
|
||||||
// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
|
// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
|
||||||
// Combine(Values("cat", "dog"),
|
// Combine(Values("cat", "dog"),
|
||||||
// Values(BLACK, WHITE)));
|
// Values(BLACK, WHITE)));
|
||||||
//
|
//
|
||||||
// This will instantiate tests in FlagDependentTest with all variations of two
|
// This will instantiate tests in FlagDependentTest with all variations of two
|
||||||
// Boolean flags:
|
// Boolean flags:
|
||||||
//
|
//
|
||||||
// class FlagDependentTest
|
// class FlagDependentTest
|
||||||
// : public testing::TestWithParam<tuple<bool, bool> > {
|
// : public testing::TestWithParam<tuple<bool, bool> > {
|
||||||
// virtual void SetUp() {
|
// virtual void SetUp() {
|
||||||
// // Assigns external_flag_1 and external_flag_2 values from the tuple.
|
// // Assigns external_flag_1 and external_flag_2 values from the tuple.
|
||||||
// tie(external_flag_1, external_flag_2) = GetParam();
|
// tie(external_flag_1, external_flag_2) = GetParam();
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
//
|
//
|
||||||
// TEST_P(FlagDependentTest, TestFeature1) {
|
// TEST_P(FlagDependentTest, TestFeature1) {
|
||||||
// // Test your code using external_flag_1 and external_flag_2 here.
|
// // Test your code using external_flag_1 and external_flag_2 here.
|
||||||
// }
|
// }
|
||||||
// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
|
// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
|
||||||
// Combine(Bool(), Bool()));
|
// Combine(Bool(), Bool()));
|
||||||
//
|
//
|
||||||
$range i 2..maxtuple
|
$range i 2..maxtuple
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
|
|
||||||
template <$for j, [[typename Generator$j]]>
|
template <$for j, [[typename Generator$j]]>
|
||||||
internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
|
internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
|
||||||
$for j, [[const Generator$j& g$j]]) {
|
$for j, [[const Generator$j& g$j]]) {
|
||||||
return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
|
return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
|
||||||
$for j, [[g$j]]);
|
$for j, [[g$j]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
]]
|
]]
|
||||||
# endif // GTEST_HAS_COMBINE
|
# endif // GTEST_HAS_COMBINE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# define TEST_P(test_case_name, test_name) \
|
# define TEST_P(test_case_name, test_name) \
|
||||||
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
|
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
|
||||||
: public test_case_name { \
|
: public test_case_name { \
|
||||||
public: \
|
public: \
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
|
||||||
virtual void TestBody(); \
|
virtual void TestBody(); \
|
||||||
private: \
|
private: \
|
||||||
static int AddToRegistry() { \
|
static int AddToRegistry() { \
|
||||||
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
|
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
|
||||||
GetTestCasePatternHolder<test_case_name>(\
|
GetTestCasePatternHolder<test_case_name>(\
|
||||||
#test_case_name, __FILE__, __LINE__)->AddTestPattern(\
|
#test_case_name, __FILE__, __LINE__)->AddTestPattern(\
|
||||||
#test_case_name, \
|
#test_case_name, \
|
||||||
#test_name, \
|
#test_name, \
|
||||||
new ::testing::internal::TestMetaFactory< \
|
new ::testing::internal::TestMetaFactory< \
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
static int gtest_registering_dummy_; \
|
static int gtest_registering_dummy_; \
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
|
||||||
}; \
|
}; \
|
||||||
int GTEST_TEST_CLASS_NAME_(test_case_name, \
|
int GTEST_TEST_CLASS_NAME_(test_case_name, \
|
||||||
test_name)::gtest_registering_dummy_ = \
|
test_name)::gtest_registering_dummy_ = \
|
||||||
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
|
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
|
||||||
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
||||||
|
|
||||||
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
|
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
|
||||||
::testing::internal::ParamGenerator<test_case_name::ParamType> \
|
::testing::internal::ParamGenerator<test_case_name::ParamType> \
|
||||||
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
|
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
|
||||||
int gtest_##prefix##test_case_name##_dummy_ = \
|
int gtest_##prefix##test_case_name##_dummy_ = \
|
||||||
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
|
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
|
||||||
GetTestCasePatternHolder<test_case_name>(\
|
GetTestCasePatternHolder<test_case_name>(\
|
||||||
#test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
|
#test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
|
||||||
#prefix, \
|
#prefix, \
|
||||||
>est_##prefix##test_case_name##_EvalGenerator_, \
|
>est_##prefix##test_case_name##_EvalGenerator_, \
|
||||||
__FILE__, __LINE__)
|
__FILE__, __LINE__)
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_HAS_PARAM_TEST
|
#endif // GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,232 +1,232 @@
|
|||||||
// Copyright 2007, Google Inc.
|
// Copyright 2007, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
//
|
//
|
||||||
// Utilities for testing Google Test itself and code that uses Google Test
|
// Utilities for testing Google Test itself and code that uses Google Test
|
||||||
// (e.g. frameworks built on top of Google Test).
|
// (e.g. frameworks built on top of Google Test).
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// This helper class can be used to mock out Google Test failure reporting
|
// This helper class can be used to mock out Google Test failure reporting
|
||||||
// so that we can test Google Test or code that builds on Google Test.
|
// so that we can test Google Test or code that builds on Google Test.
|
||||||
//
|
//
|
||||||
// An object of this class appends a TestPartResult object to the
|
// An object of this class appends a TestPartResult object to the
|
||||||
// TestPartResultArray object given in the constructor whenever a Google Test
|
// TestPartResultArray object given in the constructor whenever a Google Test
|
||||||
// failure is reported. It can either intercept only failures that are
|
// failure is reported. It can either intercept only failures that are
|
||||||
// generated in the same thread that created this object or it can intercept
|
// generated in the same thread that created this object or it can intercept
|
||||||
// all generated failures. The scope of this mock object can be controlled with
|
// all generated failures. The scope of this mock object can be controlled with
|
||||||
// the second argument to the two arguments constructor.
|
// the second argument to the two arguments constructor.
|
||||||
class GTEST_API_ ScopedFakeTestPartResultReporter
|
class GTEST_API_ ScopedFakeTestPartResultReporter
|
||||||
: public TestPartResultReporterInterface {
|
: public TestPartResultReporterInterface {
|
||||||
public:
|
public:
|
||||||
// The two possible mocking modes of this object.
|
// The two possible mocking modes of this object.
|
||||||
enum InterceptMode {
|
enum InterceptMode {
|
||||||
INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
|
INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
|
||||||
INTERCEPT_ALL_THREADS // Intercepts all failures.
|
INTERCEPT_ALL_THREADS // Intercepts all failures.
|
||||||
};
|
};
|
||||||
|
|
||||||
// The c'tor sets this object as the test part result reporter used
|
// The c'tor sets this object as the test part result reporter used
|
||||||
// by Google Test. The 'result' parameter specifies where to report the
|
// by Google Test. The 'result' parameter specifies where to report the
|
||||||
// results. This reporter will only catch failures generated in the current
|
// results. This reporter will only catch failures generated in the current
|
||||||
// thread. DEPRECATED
|
// thread. DEPRECATED
|
||||||
explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
|
explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
|
||||||
|
|
||||||
// Same as above, but you can choose the interception scope of this object.
|
// Same as above, but you can choose the interception scope of this object.
|
||||||
ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
|
ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
|
||||||
TestPartResultArray* result);
|
TestPartResultArray* result);
|
||||||
|
|
||||||
// The d'tor restores the previous test part result reporter.
|
// The d'tor restores the previous test part result reporter.
|
||||||
virtual ~ScopedFakeTestPartResultReporter();
|
virtual ~ScopedFakeTestPartResultReporter();
|
||||||
|
|
||||||
// Appends the TestPartResult object to the TestPartResultArray
|
// Appends the TestPartResult object to the TestPartResultArray
|
||||||
// received in the constructor.
|
// received in the constructor.
|
||||||
//
|
//
|
||||||
// This method is from the TestPartResultReporterInterface
|
// This method is from the TestPartResultReporterInterface
|
||||||
// interface.
|
// interface.
|
||||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
virtual void ReportTestPartResult(const TestPartResult& result);
|
||||||
private:
|
private:
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
const InterceptMode intercept_mode_;
|
const InterceptMode intercept_mode_;
|
||||||
TestPartResultReporterInterface* old_reporter_;
|
TestPartResultReporterInterface* old_reporter_;
|
||||||
TestPartResultArray* const result_;
|
TestPartResultArray* const result_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// A helper class for implementing EXPECT_FATAL_FAILURE() and
|
// A helper class for implementing EXPECT_FATAL_FAILURE() and
|
||||||
// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
|
// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
|
||||||
// TestPartResultArray contains exactly one failure that has the given
|
// TestPartResultArray contains exactly one failure that has the given
|
||||||
// type and contains the given substring. If that's not the case, a
|
// type and contains the given substring. If that's not the case, a
|
||||||
// non-fatal failure will be generated.
|
// non-fatal failure will be generated.
|
||||||
class GTEST_API_ SingleFailureChecker {
|
class GTEST_API_ SingleFailureChecker {
|
||||||
public:
|
public:
|
||||||
// The constructor remembers the arguments.
|
// The constructor remembers the arguments.
|
||||||
SingleFailureChecker(const TestPartResultArray* results,
|
SingleFailureChecker(const TestPartResultArray* results,
|
||||||
TestPartResult::Type type,
|
TestPartResult::Type type,
|
||||||
const string& substr);
|
const string& substr);
|
||||||
~SingleFailureChecker();
|
~SingleFailureChecker();
|
||||||
private:
|
private:
|
||||||
const TestPartResultArray* const results_;
|
const TestPartResultArray* const results_;
|
||||||
const TestPartResult::Type type_;
|
const TestPartResult::Type type_;
|
||||||
const string substr_;
|
const string substr_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
// A set of macros for testing Google Test assertions or code that's expected
|
// A set of macros for testing Google Test assertions or code that's expected
|
||||||
// to generate Google Test fatal failures. It verifies that the given
|
// to generate Google Test fatal failures. It verifies that the given
|
||||||
// statement will cause exactly one fatal Google Test failure with 'substr'
|
// statement will cause exactly one fatal Google Test failure with 'substr'
|
||||||
// being part of the failure message.
|
// being part of the failure message.
|
||||||
//
|
//
|
||||||
// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
|
// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
|
||||||
// affects and considers failures generated in the current thread and
|
// affects and considers failures generated in the current thread and
|
||||||
// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
|
// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
|
||||||
//
|
//
|
||||||
// The verification of the assertion is done correctly even when the statement
|
// The verification of the assertion is done correctly even when the statement
|
||||||
// throws an exception or aborts the current function.
|
// throws an exception or aborts the current function.
|
||||||
//
|
//
|
||||||
// Known restrictions:
|
// Known restrictions:
|
||||||
// - 'statement' cannot reference local non-static variables or
|
// - 'statement' cannot reference local non-static variables or
|
||||||
// non-static members of the current object.
|
// non-static members of the current object.
|
||||||
// - 'statement' cannot return a value.
|
// - 'statement' cannot return a value.
|
||||||
// - You cannot stream a failure message to this macro.
|
// - You cannot stream a failure message to this macro.
|
||||||
//
|
//
|
||||||
// Note that even though the implementations of the following two
|
// Note that even though the implementations of the following two
|
||||||
// macros are much alike, we cannot refactor them to use a common
|
// macros are much alike, we cannot refactor them to use a common
|
||||||
// helper macro, due to some peculiarity in how the preprocessor
|
// helper macro, due to some peculiarity in how the preprocessor
|
||||||
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
|
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
|
||||||
// gtest_unittest.cc will fail to compile if we do that.
|
// gtest_unittest.cc will fail to compile if we do that.
|
||||||
#define EXPECT_FATAL_FAILURE(statement, substr) \
|
#define EXPECT_FATAL_FAILURE(statement, substr) \
|
||||||
do { \
|
do { \
|
||||||
class GTestExpectFatalFailureHelper {\
|
class GTestExpectFatalFailureHelper {\
|
||||||
public:\
|
public:\
|
||||||
static void Execute() { statement; }\
|
static void Execute() { statement; }\
|
||||||
};\
|
};\
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
||||||
{\
|
{\
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
::testing::ScopedFakeTestPartResultReporter:: \
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
||||||
GTestExpectFatalFailureHelper::Execute();\
|
GTestExpectFatalFailureHelper::Execute();\
|
||||||
}\
|
}\
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||||
do { \
|
do { \
|
||||||
class GTestExpectFatalFailureHelper {\
|
class GTestExpectFatalFailureHelper {\
|
||||||
public:\
|
public:\
|
||||||
static void Execute() { statement; }\
|
static void Execute() { statement; }\
|
||||||
};\
|
};\
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
>est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
|
||||||
{\
|
{\
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
::testing::ScopedFakeTestPartResultReporter:: \
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
INTERCEPT_ALL_THREADS, >est_failures);\
|
INTERCEPT_ALL_THREADS, >est_failures);\
|
||||||
GTestExpectFatalFailureHelper::Execute();\
|
GTestExpectFatalFailureHelper::Execute();\
|
||||||
}\
|
}\
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
// A macro for testing Google Test assertions or code that's expected to
|
// A macro for testing Google Test assertions or code that's expected to
|
||||||
// generate Google Test non-fatal failures. It asserts that the given
|
// generate Google Test non-fatal failures. It asserts that the given
|
||||||
// statement will cause exactly one non-fatal Google Test failure with 'substr'
|
// statement will cause exactly one non-fatal Google Test failure with 'substr'
|
||||||
// being part of the failure message.
|
// being part of the failure message.
|
||||||
//
|
//
|
||||||
// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
|
// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
|
||||||
// affects and considers failures generated in the current thread and
|
// affects and considers failures generated in the current thread and
|
||||||
// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
|
// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
|
||||||
//
|
//
|
||||||
// 'statement' is allowed to reference local variables and members of
|
// 'statement' is allowed to reference local variables and members of
|
||||||
// the current object.
|
// the current object.
|
||||||
//
|
//
|
||||||
// The verification of the assertion is done correctly even when the statement
|
// The verification of the assertion is done correctly even when the statement
|
||||||
// throws an exception or aborts the current function.
|
// throws an exception or aborts the current function.
|
||||||
//
|
//
|
||||||
// Known restrictions:
|
// Known restrictions:
|
||||||
// - You cannot stream a failure message to this macro.
|
// - You cannot stream a failure message to this macro.
|
||||||
//
|
//
|
||||||
// Note that even though the implementations of the following two
|
// Note that even though the implementations of the following two
|
||||||
// macros are much alike, we cannot refactor them to use a common
|
// macros are much alike, we cannot refactor them to use a common
|
||||||
// helper macro, due to some peculiarity in how the preprocessor
|
// helper macro, due to some peculiarity in how the preprocessor
|
||||||
// works. If we do that, the code won't compile when the user gives
|
// works. If we do that, the code won't compile when the user gives
|
||||||
// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
|
// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
|
||||||
// expands to code containing an unprotected comma. The
|
// expands to code containing an unprotected comma. The
|
||||||
// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
|
// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
|
||||||
// catches that.
|
// catches that.
|
||||||
//
|
//
|
||||||
// For the same reason, we have to write
|
// For the same reason, we have to write
|
||||||
// if (::testing::internal::AlwaysTrue()) { statement; }
|
// if (::testing::internal::AlwaysTrue()) { statement; }
|
||||||
// instead of
|
// instead of
|
||||||
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
||||||
// to avoid an MSVC warning on unreachable code.
|
// to avoid an MSVC warning on unreachable code.
|
||||||
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
|
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
|
||||||
do {\
|
do {\
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||||
(substr));\
|
(substr));\
|
||||||
{\
|
{\
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
::testing::ScopedFakeTestPartResultReporter:: \
|
::testing::ScopedFakeTestPartResultReporter:: \
|
||||||
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
|
||||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||||
}\
|
}\
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
|
||||||
do {\
|
do {\
|
||||||
::testing::TestPartResultArray gtest_failures;\
|
::testing::TestPartResultArray gtest_failures;\
|
||||||
::testing::internal::SingleFailureChecker gtest_checker(\
|
::testing::internal::SingleFailureChecker gtest_checker(\
|
||||||
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
>est_failures, ::testing::TestPartResult::kNonFatalFailure, \
|
||||||
(substr));\
|
(substr));\
|
||||||
{\
|
{\
|
||||||
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
|
||||||
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
|
||||||
>est_failures);\
|
>est_failures);\
|
||||||
if (::testing::internal::AlwaysTrue()) { statement; }\
|
if (::testing::internal::AlwaysTrue()) { statement; }\
|
||||||
}\
|
}\
|
||||||
} while (::testing::internal::AlwaysFalse())
|
} while (::testing::internal::AlwaysFalse())
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
|
||||||
@@ -1,179 +1,179 @@
|
|||||||
// Copyright 2008, Google Inc.
|
// Copyright 2008, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: mheule@google.com (Markus Heule)
|
// Author: mheule@google.com (Markus Heule)
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-string.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// A copyable object representing the result of a test part (i.e. an
|
// A copyable object representing the result of a test part (i.e. an
|
||||||
// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
|
// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
|
||||||
//
|
//
|
||||||
// Don't inherit from TestPartResult as its destructor is not virtual.
|
// Don't inherit from TestPartResult as its destructor is not virtual.
|
||||||
class GTEST_API_ TestPartResult {
|
class GTEST_API_ TestPartResult {
|
||||||
public:
|
public:
|
||||||
// The possible outcomes of a test part (i.e. an assertion or an
|
// The possible outcomes of a test part (i.e. an assertion or an
|
||||||
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
|
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
|
||||||
enum Type {
|
enum Type {
|
||||||
kSuccess, // Succeeded.
|
kSuccess, // Succeeded.
|
||||||
kNonFatalFailure, // Failed but the test can continue.
|
kNonFatalFailure, // Failed but the test can continue.
|
||||||
kFatalFailure // Failed and the test should be terminated.
|
kFatalFailure // Failed and the test should be terminated.
|
||||||
};
|
};
|
||||||
|
|
||||||
// C'tor. TestPartResult does NOT have a default constructor.
|
// C'tor. TestPartResult does NOT have a default constructor.
|
||||||
// Always use this constructor (with parameters) to create a
|
// Always use this constructor (with parameters) to create a
|
||||||
// TestPartResult object.
|
// TestPartResult object.
|
||||||
TestPartResult(Type a_type,
|
TestPartResult(Type a_type,
|
||||||
const char* a_file_name,
|
const char* a_file_name,
|
||||||
int a_line_number,
|
int a_line_number,
|
||||||
const char* a_message)
|
const char* a_message)
|
||||||
: type_(a_type),
|
: type_(a_type),
|
||||||
file_name_(a_file_name == NULL ? "" : a_file_name),
|
file_name_(a_file_name == NULL ? "" : a_file_name),
|
||||||
line_number_(a_line_number),
|
line_number_(a_line_number),
|
||||||
summary_(ExtractSummary(a_message)),
|
summary_(ExtractSummary(a_message)),
|
||||||
message_(a_message) {
|
message_(a_message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the outcome of the test part.
|
// Gets the outcome of the test part.
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
|
|
||||||
// Gets the name of the source file where the test part took place, or
|
// Gets the name of the source file where the test part took place, or
|
||||||
// NULL if it's unknown.
|
// NULL if it's unknown.
|
||||||
const char* file_name() const {
|
const char* file_name() const {
|
||||||
return file_name_.empty() ? NULL : file_name_.c_str();
|
return file_name_.empty() ? NULL : file_name_.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the line in the source file where the test part took place,
|
// Gets the line in the source file where the test part took place,
|
||||||
// or -1 if it's unknown.
|
// or -1 if it's unknown.
|
||||||
int line_number() const { return line_number_; }
|
int line_number() const { return line_number_; }
|
||||||
|
|
||||||
// Gets the summary of the failure message.
|
// Gets the summary of the failure message.
|
||||||
const char* summary() const { return summary_.c_str(); }
|
const char* summary() const { return summary_.c_str(); }
|
||||||
|
|
||||||
// Gets the message associated with the test part.
|
// Gets the message associated with the test part.
|
||||||
const char* message() const { return message_.c_str(); }
|
const char* message() const { return message_.c_str(); }
|
||||||
|
|
||||||
// Returns true iff the test part passed.
|
// Returns true iff the test part passed.
|
||||||
bool passed() const { return type_ == kSuccess; }
|
bool passed() const { return type_ == kSuccess; }
|
||||||
|
|
||||||
// Returns true iff the test part failed.
|
// Returns true iff the test part failed.
|
||||||
bool failed() const { return type_ != kSuccess; }
|
bool failed() const { return type_ != kSuccess; }
|
||||||
|
|
||||||
// Returns true iff the test part non-fatally failed.
|
// Returns true iff the test part non-fatally failed.
|
||||||
bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
|
bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
|
||||||
|
|
||||||
// Returns true iff the test part fatally failed.
|
// Returns true iff the test part fatally failed.
|
||||||
bool fatally_failed() const { return type_ == kFatalFailure; }
|
bool fatally_failed() const { return type_ == kFatalFailure; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
|
|
||||||
// Gets the summary of the failure message by omitting the stack
|
// Gets the summary of the failure message by omitting the stack
|
||||||
// trace in it.
|
// trace in it.
|
||||||
static std::string ExtractSummary(const char* message);
|
static std::string ExtractSummary(const char* message);
|
||||||
|
|
||||||
// The name of the source file where the test part took place, or
|
// The name of the source file where the test part took place, or
|
||||||
// "" if the source file is unknown.
|
// "" if the source file is unknown.
|
||||||
std::string file_name_;
|
std::string file_name_;
|
||||||
// The line in the source file where the test part took place, or -1
|
// The line in the source file where the test part took place, or -1
|
||||||
// if the line number is unknown.
|
// if the line number is unknown.
|
||||||
int line_number_;
|
int line_number_;
|
||||||
std::string summary_; // The test failure summary.
|
std::string summary_; // The test failure summary.
|
||||||
std::string message_; // The test failure message.
|
std::string message_; // The test failure message.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prints a TestPartResult object.
|
// Prints a TestPartResult object.
|
||||||
std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
|
std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
|
||||||
|
|
||||||
// An array of TestPartResult objects.
|
// An array of TestPartResult objects.
|
||||||
//
|
//
|
||||||
// Don't inherit from TestPartResultArray as its destructor is not
|
// Don't inherit from TestPartResultArray as its destructor is not
|
||||||
// virtual.
|
// virtual.
|
||||||
class GTEST_API_ TestPartResultArray {
|
class GTEST_API_ TestPartResultArray {
|
||||||
public:
|
public:
|
||||||
TestPartResultArray() {}
|
TestPartResultArray() {}
|
||||||
|
|
||||||
// Appends the given TestPartResult to the array.
|
// Appends the given TestPartResult to the array.
|
||||||
void Append(const TestPartResult& result);
|
void Append(const TestPartResult& result);
|
||||||
|
|
||||||
// Returns the TestPartResult at the given index (0-based).
|
// Returns the TestPartResult at the given index (0-based).
|
||||||
const TestPartResult& GetTestPartResult(int index) const;
|
const TestPartResult& GetTestPartResult(int index) const;
|
||||||
|
|
||||||
// Returns the number of TestPartResult objects in the array.
|
// Returns the number of TestPartResult objects in the array.
|
||||||
int size() const;
|
int size() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<TestPartResult> array_;
|
std::vector<TestPartResult> array_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
|
||||||
};
|
};
|
||||||
|
|
||||||
// This interface knows how to report a test part result.
|
// This interface knows how to report a test part result.
|
||||||
class TestPartResultReporterInterface {
|
class TestPartResultReporterInterface {
|
||||||
public:
|
public:
|
||||||
virtual ~TestPartResultReporterInterface() {}
|
virtual ~TestPartResultReporterInterface() {}
|
||||||
|
|
||||||
virtual void ReportTestPartResult(const TestPartResult& result) = 0;
|
virtual void ReportTestPartResult(const TestPartResult& result) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
|
// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
|
||||||
// statement generates new fatal failures. To do so it registers itself as the
|
// statement generates new fatal failures. To do so it registers itself as the
|
||||||
// current test part result reporter. Besides checking if fatal failures were
|
// current test part result reporter. Besides checking if fatal failures were
|
||||||
// reported, it only delegates the reporting to the former result reporter.
|
// reported, it only delegates the reporting to the former result reporter.
|
||||||
// The original result reporter is restored in the destructor.
|
// The original result reporter is restored in the destructor.
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
class GTEST_API_ HasNewFatalFailureHelper
|
class GTEST_API_ HasNewFatalFailureHelper
|
||||||
: public TestPartResultReporterInterface {
|
: public TestPartResultReporterInterface {
|
||||||
public:
|
public:
|
||||||
HasNewFatalFailureHelper();
|
HasNewFatalFailureHelper();
|
||||||
virtual ~HasNewFatalFailureHelper();
|
virtual ~HasNewFatalFailureHelper();
|
||||||
virtual void ReportTestPartResult(const TestPartResult& result);
|
virtual void ReportTestPartResult(const TestPartResult& result);
|
||||||
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
|
||||||
private:
|
private:
|
||||||
bool has_new_fatal_failure_;
|
bool has_new_fatal_failure_;
|
||||||
TestPartResultReporterInterface* original_reporter_;
|
TestPartResultReporterInterface* original_reporter_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
|
||||||
@@ -1,259 +1,259 @@
|
|||||||
// Copyright 2008 Google Inc.
|
// Copyright 2008 Google Inc.
|
||||||
// All Rights Reserved.
|
// All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||||
|
|
||||||
// This header implements typed tests and type-parameterized tests.
|
// This header implements typed tests and type-parameterized tests.
|
||||||
|
|
||||||
// Typed (aka type-driven) tests repeat the same test for types in a
|
// Typed (aka type-driven) tests repeat the same test for types in a
|
||||||
// list. You must know which types you want to test with when writing
|
// list. You must know which types you want to test with when writing
|
||||||
// typed tests. Here's how you do it:
|
// typed tests. Here's how you do it:
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
// First, define a fixture class template. It should be parameterized
|
// First, define a fixture class template. It should be parameterized
|
||||||
// by a type. Remember to derive it from testing::Test.
|
// by a type. Remember to derive it from testing::Test.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class FooTest : public testing::Test {
|
class FooTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
...
|
...
|
||||||
typedef std::list<T> List;
|
typedef std::list<T> List;
|
||||||
static T shared_;
|
static T shared_;
|
||||||
T value_;
|
T value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Next, associate a list of types with the test case, which will be
|
// Next, associate a list of types with the test case, which will be
|
||||||
// repeated for each type in the list. The typedef is necessary for
|
// repeated for each type in the list. The typedef is necessary for
|
||||||
// the macro to parse correctly.
|
// the macro to parse correctly.
|
||||||
typedef testing::Types<char, int, unsigned int> MyTypes;
|
typedef testing::Types<char, int, unsigned int> MyTypes;
|
||||||
TYPED_TEST_CASE(FooTest, MyTypes);
|
TYPED_TEST_CASE(FooTest, MyTypes);
|
||||||
|
|
||||||
// If the type list contains only one type, you can write that type
|
// If the type list contains only one type, you can write that type
|
||||||
// directly without Types<...>:
|
// directly without Types<...>:
|
||||||
// TYPED_TEST_CASE(FooTest, int);
|
// TYPED_TEST_CASE(FooTest, int);
|
||||||
|
|
||||||
// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
|
// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
|
||||||
// tests for this test case as you want.
|
// tests for this test case as you want.
|
||||||
TYPED_TEST(FooTest, DoesBlah) {
|
TYPED_TEST(FooTest, DoesBlah) {
|
||||||
// Inside a test, refer to TypeParam to get the type parameter.
|
// Inside a test, refer to TypeParam to get the type parameter.
|
||||||
// Since we are inside a derived class template, C++ requires use to
|
// Since we are inside a derived class template, C++ requires use to
|
||||||
// visit the members of FooTest via 'this'.
|
// visit the members of FooTest via 'this'.
|
||||||
TypeParam n = this->value_;
|
TypeParam n = this->value_;
|
||||||
|
|
||||||
// To visit static members of the fixture, add the TestFixture::
|
// To visit static members of the fixture, add the TestFixture::
|
||||||
// prefix.
|
// prefix.
|
||||||
n += TestFixture::shared_;
|
n += TestFixture::shared_;
|
||||||
|
|
||||||
// To refer to typedefs in the fixture, add the "typename
|
// To refer to typedefs in the fixture, add the "typename
|
||||||
// TestFixture::" prefix.
|
// TestFixture::" prefix.
|
||||||
typename TestFixture::List values;
|
typename TestFixture::List values;
|
||||||
values.push_back(n);
|
values.push_back(n);
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST(FooTest, HasPropertyA) { ... }
|
TYPED_TEST(FooTest, HasPropertyA) { ... }
|
||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
// Type-parameterized tests are abstract test patterns parameterized
|
// Type-parameterized tests are abstract test patterns parameterized
|
||||||
// by a type. Compared with typed tests, type-parameterized tests
|
// by a type. Compared with typed tests, type-parameterized tests
|
||||||
// allow you to define the test pattern without knowing what the type
|
// allow you to define the test pattern without knowing what the type
|
||||||
// parameters are. The defined pattern can be instantiated with
|
// parameters are. The defined pattern can be instantiated with
|
||||||
// different types any number of times, in any number of translation
|
// different types any number of times, in any number of translation
|
||||||
// units.
|
// units.
|
||||||
//
|
//
|
||||||
// If you are designing an interface or concept, you can define a
|
// If you are designing an interface or concept, you can define a
|
||||||
// suite of type-parameterized tests to verify properties that any
|
// suite of type-parameterized tests to verify properties that any
|
||||||
// valid implementation of the interface/concept should have. Then,
|
// valid implementation of the interface/concept should have. Then,
|
||||||
// each implementation can easily instantiate the test suite to verify
|
// each implementation can easily instantiate the test suite to verify
|
||||||
// that it conforms to the requirements, without having to write
|
// that it conforms to the requirements, without having to write
|
||||||
// similar tests repeatedly. Here's an example:
|
// similar tests repeatedly. Here's an example:
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
// First, define a fixture class template. It should be parameterized
|
// First, define a fixture class template. It should be parameterized
|
||||||
// by a type. Remember to derive it from testing::Test.
|
// by a type. Remember to derive it from testing::Test.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class FooTest : public testing::Test {
|
class FooTest : public testing::Test {
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
|
||||||
// Next, declare that you will define a type-parameterized test case
|
// Next, declare that you will define a type-parameterized test case
|
||||||
// (the _P suffix is for "parameterized" or "pattern", whichever you
|
// (the _P suffix is for "parameterized" or "pattern", whichever you
|
||||||
// prefer):
|
// prefer):
|
||||||
TYPED_TEST_CASE_P(FooTest);
|
TYPED_TEST_CASE_P(FooTest);
|
||||||
|
|
||||||
// Then, use TYPED_TEST_P() to define as many type-parameterized tests
|
// Then, use TYPED_TEST_P() to define as many type-parameterized tests
|
||||||
// for this type-parameterized test case as you want.
|
// for this type-parameterized test case as you want.
|
||||||
TYPED_TEST_P(FooTest, DoesBlah) {
|
TYPED_TEST_P(FooTest, DoesBlah) {
|
||||||
// Inside a test, refer to TypeParam to get the type parameter.
|
// Inside a test, refer to TypeParam to get the type parameter.
|
||||||
TypeParam n = 0;
|
TypeParam n = 0;
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(FooTest, HasPropertyA) { ... }
|
TYPED_TEST_P(FooTest, HasPropertyA) { ... }
|
||||||
|
|
||||||
// Now the tricky part: you need to register all test patterns before
|
// Now the tricky part: you need to register all test patterns before
|
||||||
// you can instantiate them. The first argument of the macro is the
|
// you can instantiate them. The first argument of the macro is the
|
||||||
// test case name; the rest are the names of the tests in this test
|
// test case name; the rest are the names of the tests in this test
|
||||||
// case.
|
// case.
|
||||||
REGISTER_TYPED_TEST_CASE_P(FooTest,
|
REGISTER_TYPED_TEST_CASE_P(FooTest,
|
||||||
DoesBlah, HasPropertyA);
|
DoesBlah, HasPropertyA);
|
||||||
|
|
||||||
// Finally, you are free to instantiate the pattern with the types you
|
// Finally, you are free to instantiate the pattern with the types you
|
||||||
// want. If you put the above code in a header file, you can #include
|
// want. If you put the above code in a header file, you can #include
|
||||||
// it in multiple C++ source files and instantiate it multiple times.
|
// it in multiple C++ source files and instantiate it multiple times.
|
||||||
//
|
//
|
||||||
// To distinguish different instances of the pattern, the first
|
// To distinguish different instances of the pattern, the first
|
||||||
// argument to the INSTANTIATE_* macro is a prefix that will be added
|
// argument to the INSTANTIATE_* macro is a prefix that will be added
|
||||||
// to the actual test case name. Remember to pick unique prefixes for
|
// to the actual test case name. Remember to pick unique prefixes for
|
||||||
// different instances.
|
// different instances.
|
||||||
typedef testing::Types<char, int, unsigned int> MyTypes;
|
typedef testing::Types<char, int, unsigned int> MyTypes;
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
|
||||||
|
|
||||||
// If the type list contains only one type, you can write that type
|
// If the type list contains only one type, you can write that type
|
||||||
// directly without Types<...>:
|
// directly without Types<...>:
|
||||||
// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
|
// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
|
||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/internal/gtest-type-util.h"
|
#include "gtest/internal/gtest-type-util.h"
|
||||||
|
|
||||||
// Implements typed tests.
|
// Implements typed tests.
|
||||||
|
|
||||||
#if GTEST_HAS_TYPED_TEST
|
#if GTEST_HAS_TYPED_TEST
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Expands to the name of the typedef for the type parameters of the
|
// Expands to the name of the typedef for the type parameters of the
|
||||||
// given test case.
|
// given test case.
|
||||||
# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
|
# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
|
||||||
|
|
||||||
// The 'Types' template argument below must have spaces around it
|
// The 'Types' template argument below must have spaces around it
|
||||||
// since some compilers may choke on '>>' when passing a template
|
// since some compilers may choke on '>>' when passing a template
|
||||||
// instance (e.g. Types<int>)
|
// instance (e.g. Types<int>)
|
||||||
# define TYPED_TEST_CASE(CaseName, Types) \
|
# define TYPED_TEST_CASE(CaseName, Types) \
|
||||||
typedef ::testing::internal::TypeList< Types >::type \
|
typedef ::testing::internal::TypeList< Types >::type \
|
||||||
GTEST_TYPE_PARAMS_(CaseName)
|
GTEST_TYPE_PARAMS_(CaseName)
|
||||||
|
|
||||||
# define TYPED_TEST(CaseName, TestName) \
|
# define TYPED_TEST(CaseName, TestName) \
|
||||||
template <typename gtest_TypeParam_> \
|
template <typename gtest_TypeParam_> \
|
||||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||||
: public CaseName<gtest_TypeParam_> { \
|
: public CaseName<gtest_TypeParam_> { \
|
||||||
private: \
|
private: \
|
||||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||||
typedef gtest_TypeParam_ TypeParam; \
|
typedef gtest_TypeParam_ TypeParam; \
|
||||||
virtual void TestBody(); \
|
virtual void TestBody(); \
|
||||||
}; \
|
}; \
|
||||||
bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
|
bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
|
||||||
::testing::internal::TypeParameterizedTest< \
|
::testing::internal::TypeParameterizedTest< \
|
||||||
CaseName, \
|
CaseName, \
|
||||||
::testing::internal::TemplateSel< \
|
::testing::internal::TemplateSel< \
|
||||||
GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
|
GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
|
||||||
GTEST_TYPE_PARAMS_(CaseName)>::Register(\
|
GTEST_TYPE_PARAMS_(CaseName)>::Register(\
|
||||||
"", #CaseName, #TestName, 0); \
|
"", #CaseName, #TestName, 0); \
|
||||||
template <typename gtest_TypeParam_> \
|
template <typename gtest_TypeParam_> \
|
||||||
void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
|
void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
|
||||||
|
|
||||||
#endif // GTEST_HAS_TYPED_TEST
|
#endif // GTEST_HAS_TYPED_TEST
|
||||||
|
|
||||||
// Implements type-parameterized tests.
|
// Implements type-parameterized tests.
|
||||||
|
|
||||||
#if GTEST_HAS_TYPED_TEST_P
|
#if GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Expands to the namespace name that the type-parameterized tests for
|
// Expands to the namespace name that the type-parameterized tests for
|
||||||
// the given type-parameterized test case are defined in. The exact
|
// the given type-parameterized test case are defined in. The exact
|
||||||
// name of the namespace is subject to change without notice.
|
// name of the namespace is subject to change without notice.
|
||||||
# define GTEST_CASE_NAMESPACE_(TestCaseName) \
|
# define GTEST_CASE_NAMESPACE_(TestCaseName) \
|
||||||
gtest_case_##TestCaseName##_
|
gtest_case_##TestCaseName##_
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Expands to the name of the variable used to remember the names of
|
// Expands to the name of the variable used to remember the names of
|
||||||
// the defined tests in the given test case.
|
// the defined tests in the given test case.
|
||||||
# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
|
# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
|
||||||
gtest_typed_test_case_p_state_##TestCaseName##_
|
gtest_typed_test_case_p_state_##TestCaseName##_
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
|
||||||
//
|
//
|
||||||
// Expands to the name of the variable used to remember the names of
|
// Expands to the name of the variable used to remember the names of
|
||||||
// the registered tests in the given test case.
|
// the registered tests in the given test case.
|
||||||
# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
|
# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
|
||||||
gtest_registered_test_names_##TestCaseName##_
|
gtest_registered_test_names_##TestCaseName##_
|
||||||
|
|
||||||
// The variables defined in the type-parameterized test macros are
|
// The variables defined in the type-parameterized test macros are
|
||||||
// static as typically these macros are used in a .h file that can be
|
// static as typically these macros are used in a .h file that can be
|
||||||
// #included in multiple translation units linked together.
|
// #included in multiple translation units linked together.
|
||||||
# define TYPED_TEST_CASE_P(CaseName) \
|
# define TYPED_TEST_CASE_P(CaseName) \
|
||||||
static ::testing::internal::TypedTestCasePState \
|
static ::testing::internal::TypedTestCasePState \
|
||||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
|
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
|
||||||
|
|
||||||
# define TYPED_TEST_P(CaseName, TestName) \
|
# define TYPED_TEST_P(CaseName, TestName) \
|
||||||
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
||||||
template <typename gtest_TypeParam_> \
|
template <typename gtest_TypeParam_> \
|
||||||
class TestName : public CaseName<gtest_TypeParam_> { \
|
class TestName : public CaseName<gtest_TypeParam_> { \
|
||||||
private: \
|
private: \
|
||||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||||
typedef gtest_TypeParam_ TypeParam; \
|
typedef gtest_TypeParam_ TypeParam; \
|
||||||
virtual void TestBody(); \
|
virtual void TestBody(); \
|
||||||
}; \
|
}; \
|
||||||
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
|
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
|
||||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
|
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
|
||||||
__FILE__, __LINE__, #CaseName, #TestName); \
|
__FILE__, __LINE__, #CaseName, #TestName); \
|
||||||
} \
|
} \
|
||||||
template <typename gtest_TypeParam_> \
|
template <typename gtest_TypeParam_> \
|
||||||
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
|
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
|
||||||
|
|
||||||
# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
|
# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
|
||||||
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
|
||||||
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
|
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
|
||||||
} \
|
} \
|
||||||
static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
|
static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
|
||||||
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
|
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
|
||||||
__FILE__, __LINE__, #__VA_ARGS__)
|
__FILE__, __LINE__, #__VA_ARGS__)
|
||||||
|
|
||||||
// The 'Types' template argument below must have spaces around it
|
// The 'Types' template argument below must have spaces around it
|
||||||
// since some compilers may choke on '>>' when passing a template
|
// since some compilers may choke on '>>' when passing a template
|
||||||
// instance (e.g. Types<int>)
|
// instance (e.g. Types<int>)
|
||||||
# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
|
# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
|
||||||
bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
|
bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
|
||||||
::testing::internal::TypeParameterizedTestCase<CaseName, \
|
::testing::internal::TypeParameterizedTestCase<CaseName, \
|
||||||
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
|
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
|
||||||
::testing::internal::TypeList< Types >::type>::Register(\
|
::testing::internal::TypeList< Types >::type>::Register(\
|
||||||
#Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
|
#Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
|
||||||
|
|
||||||
#endif // GTEST_HAS_TYPED_TEST_P
|
#endif // GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,358 +1,358 @@
|
|||||||
// Copyright 2006, Google Inc.
|
// Copyright 2006, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
|
// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
|
||||||
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
|
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
|
||||||
//
|
//
|
||||||
// Implements a family of generic predicate assertion macros.
|
// Implements a family of generic predicate assertion macros.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
|
|
||||||
// Makes sure this header is not included before gtest.h.
|
// Makes sure this header is not included before gtest.h.
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
|
||||||
# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
|
# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
|
||||||
|
|
||||||
// This header implements a family of generic predicate assertion
|
// This header implements a family of generic predicate assertion
|
||||||
// macros:
|
// macros:
|
||||||
//
|
//
|
||||||
// ASSERT_PRED_FORMAT1(pred_format, v1)
|
// ASSERT_PRED_FORMAT1(pred_format, v1)
|
||||||
// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
|
// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
|
||||||
// ...
|
// ...
|
||||||
//
|
//
|
||||||
// where pred_format is a function or functor that takes n (in the
|
// where pred_format is a function or functor that takes n (in the
|
||||||
// case of ASSERT_PRED_FORMATn) values and their source expression
|
// case of ASSERT_PRED_FORMATn) values and their source expression
|
||||||
// text, and returns a testing::AssertionResult. See the definition
|
// text, and returns a testing::AssertionResult. See the definition
|
||||||
// of ASSERT_EQ in gtest.h for an example.
|
// of ASSERT_EQ in gtest.h for an example.
|
||||||
//
|
//
|
||||||
// If you don't care about formatting, you can use the more
|
// If you don't care about formatting, you can use the more
|
||||||
// restrictive version:
|
// restrictive version:
|
||||||
//
|
//
|
||||||
// ASSERT_PRED1(pred, v1)
|
// ASSERT_PRED1(pred, v1)
|
||||||
// ASSERT_PRED2(pred, v1, v2)
|
// ASSERT_PRED2(pred, v1, v2)
|
||||||
// ...
|
// ...
|
||||||
//
|
//
|
||||||
// where pred is an n-ary function or functor that returns bool,
|
// where pred is an n-ary function or functor that returns bool,
|
||||||
// and the values v1, v2, ..., must support the << operator for
|
// and the values v1, v2, ..., must support the << operator for
|
||||||
// streaming to std::ostream.
|
// streaming to std::ostream.
|
||||||
//
|
//
|
||||||
// We also define the EXPECT_* variations.
|
// We also define the EXPECT_* variations.
|
||||||
//
|
//
|
||||||
// For now we only support predicates whose arity is at most 5.
|
// For now we only support predicates whose arity is at most 5.
|
||||||
// Please email googletestframework@googlegroups.com if you need
|
// Please email googletestframework@googlegroups.com if you need
|
||||||
// support for higher arities.
|
// support for higher arities.
|
||||||
|
|
||||||
// GTEST_ASSERT_ is the basic statement to which all of the assertions
|
// GTEST_ASSERT_ is the basic statement to which all of the assertions
|
||||||
// in this file reduce. Don't use this in your code.
|
// in this file reduce. Don't use this in your code.
|
||||||
|
|
||||||
#define GTEST_ASSERT_(expression, on_failure) \
|
#define GTEST_ASSERT_(expression, on_failure) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
if (const ::testing::AssertionResult gtest_ar = (expression)) \
|
if (const ::testing::AssertionResult gtest_ar = (expression)) \
|
||||||
; \
|
; \
|
||||||
else \
|
else \
|
||||||
on_failure(gtest_ar.failure_message())
|
on_failure(gtest_ar.failure_message())
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred,
|
||||||
typename T1>
|
typename T1>
|
||||||
AssertionResult AssertPred1Helper(const char* pred_text,
|
AssertionResult AssertPred1Helper(const char* pred_text,
|
||||||
const char* e1,
|
const char* e1,
|
||||||
Pred pred,
|
Pred pred,
|
||||||
const T1& v1) {
|
const T1& v1) {
|
||||||
if (pred(v1)) return AssertionSuccess();
|
if (pred(v1)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure() << pred_text << "("
|
||||||
<< e1 << ") evaluates to false, where"
|
<< e1 << ") evaluates to false, where"
|
||||||
<< "\n" << e1 << " evaluates to " << v1;
|
<< "\n" << e1 << " evaluates to " << v1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
|
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
|
||||||
GTEST_ASSERT_(pred_format(#v1, v1), \
|
GTEST_ASSERT_(pred_format(#v1, v1), \
|
||||||
on_failure)
|
on_failure)
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED1_(pred, v1, on_failure)\
|
#define GTEST_PRED1_(pred, v1, on_failure)\
|
||||||
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
|
||||||
#v1, \
|
#v1, \
|
||||||
pred, \
|
pred, \
|
||||||
v1), on_failure)
|
v1), on_failure)
|
||||||
|
|
||||||
// Unary predicate assertion macros.
|
// Unary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
|
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
|
||||||
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
|
||||||
#define EXPECT_PRED1(pred, v1) \
|
#define EXPECT_PRED1(pred, v1) \
|
||||||
GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
|
||||||
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
|
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
|
||||||
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
|
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
|
||||||
#define ASSERT_PRED1(pred, v1) \
|
#define ASSERT_PRED1(pred, v1) \
|
||||||
GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
|
GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred,
|
||||||
typename T1,
|
typename T1,
|
||||||
typename T2>
|
typename T2>
|
||||||
AssertionResult AssertPred2Helper(const char* pred_text,
|
AssertionResult AssertPred2Helper(const char* pred_text,
|
||||||
const char* e1,
|
const char* e1,
|
||||||
const char* e2,
|
const char* e2,
|
||||||
Pred pred,
|
Pred pred,
|
||||||
const T1& v1,
|
const T1& v1,
|
||||||
const T2& v2) {
|
const T2& v2) {
|
||||||
if (pred(v1, v2)) return AssertionSuccess();
|
if (pred(v1, v2)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure() << pred_text << "("
|
||||||
<< e1 << ", "
|
<< e1 << ", "
|
||||||
<< e2 << ") evaluates to false, where"
|
<< e2 << ") evaluates to false, where"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< "\n" << e1 << " evaluates to " << v1
|
||||||
<< "\n" << e2 << " evaluates to " << v2;
|
<< "\n" << e2 << " evaluates to " << v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
|
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
|
||||||
on_failure)
|
on_failure)
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED2_(pred, v1, v2, on_failure)\
|
#define GTEST_PRED2_(pred, v1, v2, on_failure)\
|
||||||
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
|
||||||
#v1, \
|
#v1, \
|
||||||
#v2, \
|
#v2, \
|
||||||
pred, \
|
pred, \
|
||||||
v1, \
|
v1, \
|
||||||
v2), on_failure)
|
v2), on_failure)
|
||||||
|
|
||||||
// Binary predicate assertion macros.
|
// Binary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
|
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
|
||||||
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
|
||||||
#define EXPECT_PRED2(pred, v1, v2) \
|
#define EXPECT_PRED2(pred, v1, v2) \
|
||||||
GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
|
||||||
#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
|
#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
|
||||||
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
|
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
|
||||||
#define ASSERT_PRED2(pred, v1, v2) \
|
#define ASSERT_PRED2(pred, v1, v2) \
|
||||||
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
|
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred,
|
||||||
typename T1,
|
typename T1,
|
||||||
typename T2,
|
typename T2,
|
||||||
typename T3>
|
typename T3>
|
||||||
AssertionResult AssertPred3Helper(const char* pred_text,
|
AssertionResult AssertPred3Helper(const char* pred_text,
|
||||||
const char* e1,
|
const char* e1,
|
||||||
const char* e2,
|
const char* e2,
|
||||||
const char* e3,
|
const char* e3,
|
||||||
Pred pred,
|
Pred pred,
|
||||||
const T1& v1,
|
const T1& v1,
|
||||||
const T2& v2,
|
const T2& v2,
|
||||||
const T3& v3) {
|
const T3& v3) {
|
||||||
if (pred(v1, v2, v3)) return AssertionSuccess();
|
if (pred(v1, v2, v3)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure() << pred_text << "("
|
||||||
<< e1 << ", "
|
<< e1 << ", "
|
||||||
<< e2 << ", "
|
<< e2 << ", "
|
||||||
<< e3 << ") evaluates to false, where"
|
<< e3 << ") evaluates to false, where"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< "\n" << e1 << " evaluates to " << v1
|
||||||
<< "\n" << e2 << " evaluates to " << v2
|
<< "\n" << e2 << " evaluates to " << v2
|
||||||
<< "\n" << e3 << " evaluates to " << v3;
|
<< "\n" << e3 << " evaluates to " << v3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
|
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
|
||||||
on_failure)
|
on_failure)
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
|
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
|
||||||
GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
|
||||||
#v1, \
|
#v1, \
|
||||||
#v2, \
|
#v2, \
|
||||||
#v3, \
|
#v3, \
|
||||||
pred, \
|
pred, \
|
||||||
v1, \
|
v1, \
|
||||||
v2, \
|
v2, \
|
||||||
v3), on_failure)
|
v3), on_failure)
|
||||||
|
|
||||||
// Ternary predicate assertion macros.
|
// Ternary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
||||||
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
|
||||||
#define EXPECT_PRED3(pred, v1, v2, v3) \
|
#define EXPECT_PRED3(pred, v1, v2, v3) \
|
||||||
GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
|
||||||
#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
|
||||||
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
||||||
#define ASSERT_PRED3(pred, v1, v2, v3) \
|
#define ASSERT_PRED3(pred, v1, v2, v3) \
|
||||||
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred,
|
||||||
typename T1,
|
typename T1,
|
||||||
typename T2,
|
typename T2,
|
||||||
typename T3,
|
typename T3,
|
||||||
typename T4>
|
typename T4>
|
||||||
AssertionResult AssertPred4Helper(const char* pred_text,
|
AssertionResult AssertPred4Helper(const char* pred_text,
|
||||||
const char* e1,
|
const char* e1,
|
||||||
const char* e2,
|
const char* e2,
|
||||||
const char* e3,
|
const char* e3,
|
||||||
const char* e4,
|
const char* e4,
|
||||||
Pred pred,
|
Pred pred,
|
||||||
const T1& v1,
|
const T1& v1,
|
||||||
const T2& v2,
|
const T2& v2,
|
||||||
const T3& v3,
|
const T3& v3,
|
||||||
const T4& v4) {
|
const T4& v4) {
|
||||||
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure() << pred_text << "("
|
||||||
<< e1 << ", "
|
<< e1 << ", "
|
||||||
<< e2 << ", "
|
<< e2 << ", "
|
||||||
<< e3 << ", "
|
<< e3 << ", "
|
||||||
<< e4 << ") evaluates to false, where"
|
<< e4 << ") evaluates to false, where"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< "\n" << e1 << " evaluates to " << v1
|
||||||
<< "\n" << e2 << " evaluates to " << v2
|
<< "\n" << e2 << " evaluates to " << v2
|
||||||
<< "\n" << e3 << " evaluates to " << v3
|
<< "\n" << e3 << " evaluates to " << v3
|
||||||
<< "\n" << e4 << " evaluates to " << v4;
|
<< "\n" << e4 << " evaluates to " << v4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
|
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
|
||||||
on_failure)
|
on_failure)
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
|
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
|
||||||
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
|
||||||
#v1, \
|
#v1, \
|
||||||
#v2, \
|
#v2, \
|
||||||
#v3, \
|
#v3, \
|
||||||
#v4, \
|
#v4, \
|
||||||
pred, \
|
pred, \
|
||||||
v1, \
|
v1, \
|
||||||
v2, \
|
v2, \
|
||||||
v3, \
|
v3, \
|
||||||
v4), on_failure)
|
v4), on_failure)
|
||||||
|
|
||||||
// 4-ary predicate assertion macros.
|
// 4-ary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
||||||
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
|
||||||
#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
|
#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
|
||||||
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
|
||||||
#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
|
||||||
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
||||||
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
|
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
|
||||||
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
template <typename Pred,
|
template <typename Pred,
|
||||||
typename T1,
|
typename T1,
|
||||||
typename T2,
|
typename T2,
|
||||||
typename T3,
|
typename T3,
|
||||||
typename T4,
|
typename T4,
|
||||||
typename T5>
|
typename T5>
|
||||||
AssertionResult AssertPred5Helper(const char* pred_text,
|
AssertionResult AssertPred5Helper(const char* pred_text,
|
||||||
const char* e1,
|
const char* e1,
|
||||||
const char* e2,
|
const char* e2,
|
||||||
const char* e3,
|
const char* e3,
|
||||||
const char* e4,
|
const char* e4,
|
||||||
const char* e5,
|
const char* e5,
|
||||||
Pred pred,
|
Pred pred,
|
||||||
const T1& v1,
|
const T1& v1,
|
||||||
const T2& v2,
|
const T2& v2,
|
||||||
const T3& v3,
|
const T3& v3,
|
||||||
const T4& v4,
|
const T4& v4,
|
||||||
const T5& v5) {
|
const T5& v5) {
|
||||||
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
|
||||||
|
|
||||||
return AssertionFailure() << pred_text << "("
|
return AssertionFailure() << pred_text << "("
|
||||||
<< e1 << ", "
|
<< e1 << ", "
|
||||||
<< e2 << ", "
|
<< e2 << ", "
|
||||||
<< e3 << ", "
|
<< e3 << ", "
|
||||||
<< e4 << ", "
|
<< e4 << ", "
|
||||||
<< e5 << ") evaluates to false, where"
|
<< e5 << ") evaluates to false, where"
|
||||||
<< "\n" << e1 << " evaluates to " << v1
|
<< "\n" << e1 << " evaluates to " << v1
|
||||||
<< "\n" << e2 << " evaluates to " << v2
|
<< "\n" << e2 << " evaluates to " << v2
|
||||||
<< "\n" << e3 << " evaluates to " << v3
|
<< "\n" << e3 << " evaluates to " << v3
|
||||||
<< "\n" << e4 << " evaluates to " << v4
|
<< "\n" << e4 << " evaluates to " << v4
|
||||||
<< "\n" << e5 << " evaluates to " << v5;
|
<< "\n" << e5 << " evaluates to " << v5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
|
||||||
// Don't use this in your code.
|
// Don't use this in your code.
|
||||||
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
|
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
|
||||||
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
|
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
|
||||||
on_failure)
|
on_failure)
|
||||||
|
|
||||||
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
|
||||||
// this in your code.
|
// this in your code.
|
||||||
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
|
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
|
||||||
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
|
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
|
||||||
#v1, \
|
#v1, \
|
||||||
#v2, \
|
#v2, \
|
||||||
#v3, \
|
#v3, \
|
||||||
#v4, \
|
#v4, \
|
||||||
#v5, \
|
#v5, \
|
||||||
pred, \
|
pred, \
|
||||||
v1, \
|
v1, \
|
||||||
v2, \
|
v2, \
|
||||||
v3, \
|
v3, \
|
||||||
v4, \
|
v4, \
|
||||||
v5), on_failure)
|
v5), on_failure)
|
||||||
|
|
||||||
// 5-ary predicate assertion macros.
|
// 5-ary predicate assertion macros.
|
||||||
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
||||||
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
|
||||||
#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
|
#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
|
||||||
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
|
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
|
||||||
#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
|
||||||
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
||||||
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
|
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
|
||||||
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
|
||||||
@@ -1,58 +1,58 @@
|
|||||||
// Copyright 2006, Google Inc.
|
// Copyright 2006, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
//
|
//
|
||||||
// Google C++ Testing Framework definitions useful in production code.
|
// Google C++ Testing Framework definitions useful in production code.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||||
#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||||
|
|
||||||
// When you need to test the private or protected members of a class,
|
// When you need to test the private or protected members of a class,
|
||||||
// use the FRIEND_TEST macro to declare your tests as friends of the
|
// use the FRIEND_TEST macro to declare your tests as friends of the
|
||||||
// class. For example:
|
// class. For example:
|
||||||
//
|
//
|
||||||
// class MyClass {
|
// class MyClass {
|
||||||
// private:
|
// private:
|
||||||
// void MyMethod();
|
// void MyMethod();
|
||||||
// FRIEND_TEST(MyClassTest, MyMethod);
|
// FRIEND_TEST(MyClassTest, MyMethod);
|
||||||
// };
|
// };
|
||||||
//
|
//
|
||||||
// class MyClassTest : public testing::Test {
|
// class MyClassTest : public testing::Test {
|
||||||
// // ...
|
// // ...
|
||||||
// };
|
// };
|
||||||
//
|
//
|
||||||
// TEST_F(MyClassTest, MyMethod) {
|
// TEST_F(MyClassTest, MyMethod) {
|
||||||
// // Can call MyClass::MyMethod() here.
|
// // Can call MyClass::MyMethod() here.
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#define FRIEND_TEST(test_case_name, test_name)\
|
#define FRIEND_TEST(test_case_name, test_name)\
|
||||||
friend class test_case_name##_##test_name##_Test
|
friend class test_case_name##_##test_name##_Test
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
|
||||||
@@ -1,319 +1,319 @@
|
|||||||
// Copyright 2005, Google Inc.
|
// Copyright 2005, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
|
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
|
||||||
//
|
//
|
||||||
// The Google C++ Testing Framework (Google Test)
|
// The Google C++ Testing Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file defines internal utilities needed for implementing
|
// This header file defines internal utilities needed for implementing
|
||||||
// death tests. They are subject to change without notice.
|
// death tests. They are subject to change without notice.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
|
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
GTEST_DECLARE_string_(internal_run_death_test);
|
GTEST_DECLARE_string_(internal_run_death_test);
|
||||||
|
|
||||||
// Names of the flags (needed for parsing Google Test flags).
|
// Names of the flags (needed for parsing Google Test flags).
|
||||||
const char kDeathTestStyleFlag[] = "death_test_style";
|
const char kDeathTestStyleFlag[] = "death_test_style";
|
||||||
const char kDeathTestUseFork[] = "death_test_use_fork";
|
const char kDeathTestUseFork[] = "death_test_use_fork";
|
||||||
const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
|
const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
// DeathTest is a class that hides much of the complexity of the
|
// DeathTest is a class that hides much of the complexity of the
|
||||||
// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
|
// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
|
||||||
// returns a concrete class that depends on the prevailing death test
|
// returns a concrete class that depends on the prevailing death test
|
||||||
// style, as defined by the --gtest_death_test_style and/or
|
// style, as defined by the --gtest_death_test_style and/or
|
||||||
// --gtest_internal_run_death_test flags.
|
// --gtest_internal_run_death_test flags.
|
||||||
|
|
||||||
// In describing the results of death tests, these terms are used with
|
// In describing the results of death tests, these terms are used with
|
||||||
// the corresponding definitions:
|
// the corresponding definitions:
|
||||||
//
|
//
|
||||||
// exit status: The integer exit information in the format specified
|
// exit status: The integer exit information in the format specified
|
||||||
// by wait(2)
|
// by wait(2)
|
||||||
// exit code: The integer code passed to exit(3), _exit(2), or
|
// exit code: The integer code passed to exit(3), _exit(2), or
|
||||||
// returned from main()
|
// returned from main()
|
||||||
class GTEST_API_ DeathTest {
|
class GTEST_API_ DeathTest {
|
||||||
public:
|
public:
|
||||||
// Create returns false if there was an error determining the
|
// Create returns false if there was an error determining the
|
||||||
// appropriate action to take for the current death test; for example,
|
// appropriate action to take for the current death test; for example,
|
||||||
// if the gtest_death_test_style flag is set to an invalid value.
|
// if the gtest_death_test_style flag is set to an invalid value.
|
||||||
// The LastMessage method will return a more detailed message in that
|
// The LastMessage method will return a more detailed message in that
|
||||||
// case. Otherwise, the DeathTest pointer pointed to by the "test"
|
// case. Otherwise, the DeathTest pointer pointed to by the "test"
|
||||||
// argument is set. If the death test should be skipped, the pointer
|
// argument is set. If the death test should be skipped, the pointer
|
||||||
// is set to NULL; otherwise, it is set to the address of a new concrete
|
// is set to NULL; otherwise, it is set to the address of a new concrete
|
||||||
// DeathTest object that controls the execution of the current test.
|
// DeathTest object that controls the execution of the current test.
|
||||||
static bool Create(const char* statement, const RE* regex,
|
static bool Create(const char* statement, const RE* regex,
|
||||||
const char* file, int line, DeathTest** test);
|
const char* file, int line, DeathTest** test);
|
||||||
DeathTest();
|
DeathTest();
|
||||||
virtual ~DeathTest() { }
|
virtual ~DeathTest() { }
|
||||||
|
|
||||||
// A helper class that aborts a death test when it's deleted.
|
// A helper class that aborts a death test when it's deleted.
|
||||||
class ReturnSentinel {
|
class ReturnSentinel {
|
||||||
public:
|
public:
|
||||||
explicit ReturnSentinel(DeathTest* test) : test_(test) { }
|
explicit ReturnSentinel(DeathTest* test) : test_(test) { }
|
||||||
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
|
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
|
||||||
private:
|
private:
|
||||||
DeathTest* const test_;
|
DeathTest* const test_;
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
|
||||||
} GTEST_ATTRIBUTE_UNUSED_;
|
} GTEST_ATTRIBUTE_UNUSED_;
|
||||||
|
|
||||||
// An enumeration of possible roles that may be taken when a death
|
// An enumeration of possible roles that may be taken when a death
|
||||||
// test is encountered. EXECUTE means that the death test logic should
|
// test is encountered. EXECUTE means that the death test logic should
|
||||||
// be executed immediately. OVERSEE means that the program should prepare
|
// be executed immediately. OVERSEE means that the program should prepare
|
||||||
// the appropriate environment for a child process to execute the death
|
// the appropriate environment for a child process to execute the death
|
||||||
// test, then wait for it to complete.
|
// test, then wait for it to complete.
|
||||||
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
|
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
|
||||||
|
|
||||||
// An enumeration of the three reasons that a test might be aborted.
|
// An enumeration of the three reasons that a test might be aborted.
|
||||||
enum AbortReason {
|
enum AbortReason {
|
||||||
TEST_ENCOUNTERED_RETURN_STATEMENT,
|
TEST_ENCOUNTERED_RETURN_STATEMENT,
|
||||||
TEST_THREW_EXCEPTION,
|
TEST_THREW_EXCEPTION,
|
||||||
TEST_DID_NOT_DIE
|
TEST_DID_NOT_DIE
|
||||||
};
|
};
|
||||||
|
|
||||||
// Assumes one of the above roles.
|
// Assumes one of the above roles.
|
||||||
virtual TestRole AssumeRole() = 0;
|
virtual TestRole AssumeRole() = 0;
|
||||||
|
|
||||||
// Waits for the death test to finish and returns its status.
|
// Waits for the death test to finish and returns its status.
|
||||||
virtual int Wait() = 0;
|
virtual int Wait() = 0;
|
||||||
|
|
||||||
// Returns true if the death test passed; that is, the test process
|
// Returns true if the death test passed; that is, the test process
|
||||||
// exited during the test, its exit status matches a user-supplied
|
// exited during the test, its exit status matches a user-supplied
|
||||||
// predicate, and its stderr output matches a user-supplied regular
|
// predicate, and its stderr output matches a user-supplied regular
|
||||||
// expression.
|
// expression.
|
||||||
// The user-supplied predicate may be a macro expression rather
|
// The user-supplied predicate may be a macro expression rather
|
||||||
// than a function pointer or functor, or else Wait and Passed could
|
// than a function pointer or functor, or else Wait and Passed could
|
||||||
// be combined.
|
// be combined.
|
||||||
virtual bool Passed(bool exit_status_ok) = 0;
|
virtual bool Passed(bool exit_status_ok) = 0;
|
||||||
|
|
||||||
// Signals that the death test did not die as expected.
|
// Signals that the death test did not die as expected.
|
||||||
virtual void Abort(AbortReason reason) = 0;
|
virtual void Abort(AbortReason reason) = 0;
|
||||||
|
|
||||||
// Returns a human-readable outcome message regarding the outcome of
|
// Returns a human-readable outcome message regarding the outcome of
|
||||||
// the last death test.
|
// the last death test.
|
||||||
static const char* LastMessage();
|
static const char* LastMessage();
|
||||||
|
|
||||||
static void set_last_death_test_message(const std::string& message);
|
static void set_last_death_test_message(const std::string& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// A string containing a description of the outcome of the last death test.
|
// A string containing a description of the outcome of the last death test.
|
||||||
static std::string last_death_test_message_;
|
static std::string last_death_test_message_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Factory interface for death tests. May be mocked out for testing.
|
// Factory interface for death tests. May be mocked out for testing.
|
||||||
class DeathTestFactory {
|
class DeathTestFactory {
|
||||||
public:
|
public:
|
||||||
virtual ~DeathTestFactory() { }
|
virtual ~DeathTestFactory() { }
|
||||||
virtual bool Create(const char* statement, const RE* regex,
|
virtual bool Create(const char* statement, const RE* regex,
|
||||||
const char* file, int line, DeathTest** test) = 0;
|
const char* file, int line, DeathTest** test) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A concrete DeathTestFactory implementation for normal use.
|
// A concrete DeathTestFactory implementation for normal use.
|
||||||
class DefaultDeathTestFactory : public DeathTestFactory {
|
class DefaultDeathTestFactory : public DeathTestFactory {
|
||||||
public:
|
public:
|
||||||
virtual bool Create(const char* statement, const RE* regex,
|
virtual bool Create(const char* statement, const RE* regex,
|
||||||
const char* file, int line, DeathTest** test);
|
const char* file, int line, DeathTest** test);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns true if exit_status describes a process that was terminated
|
// Returns true if exit_status describes a process that was terminated
|
||||||
// by a signal, or exited normally with a nonzero exit code.
|
// by a signal, or exited normally with a nonzero exit code.
|
||||||
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||||
|
|
||||||
// Traps C++ exceptions escaping statement and reports them as test
|
// Traps C++ exceptions escaping statement and reports them as test
|
||||||
// failures. Note that trapping SEH exceptions is not implemented here.
|
// failures. Note that trapping SEH exceptions is not implemented here.
|
||||||
# if GTEST_HAS_EXCEPTIONS
|
# if GTEST_HAS_EXCEPTIONS
|
||||||
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||||
try { \
|
try { \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
} catch (const ::std::exception& gtest_exception) { \
|
} catch (const ::std::exception& gtest_exception) { \
|
||||||
fprintf(\
|
fprintf(\
|
||||||
stderr, \
|
stderr, \
|
||||||
"\n%s: Caught std::exception-derived exception escaping the " \
|
"\n%s: Caught std::exception-derived exception escaping the " \
|
||||||
"death test statement. Exception message: %s\n", \
|
"death test statement. Exception message: %s\n", \
|
||||||
::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
|
::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
|
||||||
gtest_exception.what()); \
|
gtest_exception.what()); \
|
||||||
fflush(stderr); \
|
fflush(stderr); \
|
||||||
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
||||||
} catch (...) { \
|
} catch (...) { \
|
||||||
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
|
||||||
}
|
}
|
||||||
|
|
||||||
# else
|
# else
|
||||||
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
|
||||||
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
// ASSERT_EXIT*, and EXPECT_EXIT*.
|
||||||
# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
|
# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
if (::testing::internal::AlwaysTrue()) { \
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
const ::testing::internal::RE& gtest_regex = (regex); \
|
const ::testing::internal::RE& gtest_regex = (regex); \
|
||||||
::testing::internal::DeathTest* gtest_dt; \
|
::testing::internal::DeathTest* gtest_dt; \
|
||||||
if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \
|
if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \
|
||||||
__FILE__, __LINE__, >est_dt)) { \
|
__FILE__, __LINE__, >est_dt)) { \
|
||||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||||
} \
|
} \
|
||||||
if (gtest_dt != NULL) { \
|
if (gtest_dt != NULL) { \
|
||||||
::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
|
::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
|
||||||
gtest_dt_ptr(gtest_dt); \
|
gtest_dt_ptr(gtest_dt); \
|
||||||
switch (gtest_dt->AssumeRole()) { \
|
switch (gtest_dt->AssumeRole()) { \
|
||||||
case ::testing::internal::DeathTest::OVERSEE_TEST: \
|
case ::testing::internal::DeathTest::OVERSEE_TEST: \
|
||||||
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
|
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
|
||||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||||
} \
|
} \
|
||||||
break; \
|
break; \
|
||||||
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
|
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
|
||||||
::testing::internal::DeathTest::ReturnSentinel \
|
::testing::internal::DeathTest::ReturnSentinel \
|
||||||
gtest_sentinel(gtest_dt); \
|
gtest_sentinel(gtest_dt); \
|
||||||
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
|
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
|
||||||
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
default: \
|
default: \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} else \
|
} else \
|
||||||
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
|
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
|
||||||
fail(::testing::internal::DeathTest::LastMessage())
|
fail(::testing::internal::DeathTest::LastMessage())
|
||||||
// The symbol "fail" here expands to something into which a message
|
// The symbol "fail" here expands to something into which a message
|
||||||
// can be streamed.
|
// can be streamed.
|
||||||
|
|
||||||
// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
|
// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
|
||||||
// NDEBUG mode. In this case we need the statements to be executed, the regex is
|
// NDEBUG mode. In this case we need the statements to be executed, the regex is
|
||||||
// ignored, and the macro must accept a streamed message even though the message
|
// ignored, and the macro must accept a streamed message even though the message
|
||||||
// is never printed.
|
// is never printed.
|
||||||
# define GTEST_EXECUTE_STATEMENT_(statement, regex) \
|
# define GTEST_EXECUTE_STATEMENT_(statement, regex) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
if (::testing::internal::AlwaysTrue()) { \
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
} else \
|
} else \
|
||||||
::testing::Message()
|
::testing::Message()
|
||||||
|
|
||||||
// A class representing the parsed contents of the
|
// A class representing the parsed contents of the
|
||||||
// --gtest_internal_run_death_test flag, as it existed when
|
// --gtest_internal_run_death_test flag, as it existed when
|
||||||
// RUN_ALL_TESTS was called.
|
// RUN_ALL_TESTS was called.
|
||||||
class InternalRunDeathTestFlag {
|
class InternalRunDeathTestFlag {
|
||||||
public:
|
public:
|
||||||
InternalRunDeathTestFlag(const std::string& a_file,
|
InternalRunDeathTestFlag(const std::string& a_file,
|
||||||
int a_line,
|
int a_line,
|
||||||
int an_index,
|
int an_index,
|
||||||
int a_write_fd)
|
int a_write_fd)
|
||||||
: file_(a_file), line_(a_line), index_(an_index),
|
: file_(a_file), line_(a_line), index_(an_index),
|
||||||
write_fd_(a_write_fd) {}
|
write_fd_(a_write_fd) {}
|
||||||
|
|
||||||
~InternalRunDeathTestFlag() {
|
~InternalRunDeathTestFlag() {
|
||||||
if (write_fd_ >= 0)
|
if (write_fd_ >= 0)
|
||||||
posix::Close(write_fd_);
|
posix::Close(write_fd_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& file() const { return file_; }
|
const std::string& file() const { return file_; }
|
||||||
int line() const { return line_; }
|
int line() const { return line_; }
|
||||||
int index() const { return index_; }
|
int index() const { return index_; }
|
||||||
int write_fd() const { return write_fd_; }
|
int write_fd() const { return write_fd_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string file_;
|
std::string file_;
|
||||||
int line_;
|
int line_;
|
||||||
int index_;
|
int index_;
|
||||||
int write_fd_;
|
int write_fd_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a newly created InternalRunDeathTestFlag object with fields
|
// Returns a newly created InternalRunDeathTestFlag object with fields
|
||||||
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
|
||||||
// the flag is specified; otherwise returns NULL.
|
// the flag is specified; otherwise returns NULL.
|
||||||
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
|
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
|
||||||
|
|
||||||
#else // GTEST_HAS_DEATH_TEST
|
#else // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
// This macro is used for implementing macros such as
|
// This macro is used for implementing macros such as
|
||||||
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
|
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
|
||||||
// death tests are not supported. Those macros must compile on such systems
|
// death tests are not supported. Those macros must compile on such systems
|
||||||
// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
|
// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
|
||||||
// systems that support death tests. This allows one to write such a macro
|
// systems that support death tests. This allows one to write such a macro
|
||||||
// on a system that does not support death tests and be sure that it will
|
// on a system that does not support death tests and be sure that it will
|
||||||
// compile on a death-test supporting system.
|
// compile on a death-test supporting system.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// statement - A statement that a macro such as EXPECT_DEATH would test
|
// statement - A statement that a macro such as EXPECT_DEATH would test
|
||||||
// for program termination. This macro has to make sure this
|
// for program termination. This macro has to make sure this
|
||||||
// statement is compiled but not executed, to ensure that
|
// statement is compiled but not executed, to ensure that
|
||||||
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
|
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
|
||||||
// parameter iff EXPECT_DEATH compiles with it.
|
// parameter iff EXPECT_DEATH compiles with it.
|
||||||
// regex - A regex that a macro such as EXPECT_DEATH would use to test
|
// regex - A regex that a macro such as EXPECT_DEATH would use to test
|
||||||
// the output of statement. This parameter has to be
|
// the output of statement. This parameter has to be
|
||||||
// compiled but not evaluated by this macro, to ensure that
|
// compiled but not evaluated by this macro, to ensure that
|
||||||
// this macro only accepts expressions that a macro such as
|
// this macro only accepts expressions that a macro such as
|
||||||
// EXPECT_DEATH would accept.
|
// EXPECT_DEATH would accept.
|
||||||
// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
|
// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
|
||||||
// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
|
// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
|
||||||
// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
|
// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
|
||||||
// compile inside functions where ASSERT_DEATH doesn't
|
// compile inside functions where ASSERT_DEATH doesn't
|
||||||
// compile.
|
// compile.
|
||||||
//
|
//
|
||||||
// The branch that has an always false condition is used to ensure that
|
// The branch that has an always false condition is used to ensure that
|
||||||
// statement and regex are compiled (and thus syntactically correct) but
|
// statement and regex are compiled (and thus syntactically correct) but
|
||||||
// never executed. The unreachable code macro protects the terminator
|
// never executed. The unreachable code macro protects the terminator
|
||||||
// statement from generating an 'unreachable code' warning in case
|
// statement from generating an 'unreachable code' warning in case
|
||||||
// statement unconditionally returns or throws. The Message constructor at
|
// statement unconditionally returns or throws. The Message constructor at
|
||||||
// the end allows the syntax of streaming additional messages into the
|
// the end allows the syntax of streaming additional messages into the
|
||||||
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
|
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
|
||||||
# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
|
# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
|
||||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||||
if (::testing::internal::AlwaysTrue()) { \
|
if (::testing::internal::AlwaysTrue()) { \
|
||||||
GTEST_LOG_(WARNING) \
|
GTEST_LOG_(WARNING) \
|
||||||
<< "Death tests are not supported on this platform.\n" \
|
<< "Death tests are not supported on this platform.\n" \
|
||||||
<< "Statement '" #statement "' cannot be verified."; \
|
<< "Statement '" #statement "' cannot be verified."; \
|
||||||
} else if (::testing::internal::AlwaysFalse()) { \
|
} else if (::testing::internal::AlwaysFalse()) { \
|
||||||
::testing::internal::RE::PartialMatch(".*", (regex)); \
|
::testing::internal::RE::PartialMatch(".*", (regex)); \
|
||||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||||
terminator; \
|
terminator; \
|
||||||
} else \
|
} else \
|
||||||
::testing::Message()
|
::testing::Message()
|
||||||
|
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
|
||||||
@@ -1,206 +1,206 @@
|
|||||||
// Copyright 2008, Google Inc.
|
// Copyright 2008, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: keith.ray@gmail.com (Keith Ray)
|
// Author: keith.ray@gmail.com (Keith Ray)
|
||||||
//
|
//
|
||||||
// Google Test filepath utilities
|
// Google Test filepath utilities
|
||||||
//
|
//
|
||||||
// This header file declares classes and functions used internally by
|
// This header file declares classes and functions used internally by
|
||||||
// Google Test. They are subject to change without notice.
|
// Google Test. They are subject to change without notice.
|
||||||
//
|
//
|
||||||
// This file is #included in <gtest/internal/gtest-internal.h>.
|
// This file is #included in <gtest/internal/gtest-internal.h>.
|
||||||
// Do not include this header file separately!
|
// Do not include this header file separately!
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||||
|
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-string.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// FilePath - a class for file and directory pathname manipulation which
|
// FilePath - a class for file and directory pathname manipulation which
|
||||||
// handles platform-specific conventions (like the pathname separator).
|
// handles platform-specific conventions (like the pathname separator).
|
||||||
// Used for helper functions for naming files in a directory for xml output.
|
// Used for helper functions for naming files in a directory for xml output.
|
||||||
// Except for Set methods, all methods are const or static, which provides an
|
// Except for Set methods, all methods are const or static, which provides an
|
||||||
// "immutable value object" -- useful for peace of mind.
|
// "immutable value object" -- useful for peace of mind.
|
||||||
// A FilePath with a value ending in a path separator ("like/this/") represents
|
// A FilePath with a value ending in a path separator ("like/this/") represents
|
||||||
// a directory, otherwise it is assumed to represent a file. In either case,
|
// a directory, otherwise it is assumed to represent a file. In either case,
|
||||||
// it may or may not represent an actual file or directory in the file system.
|
// it may or may not represent an actual file or directory in the file system.
|
||||||
// Names are NOT checked for syntax correctness -- no checking for illegal
|
// Names are NOT checked for syntax correctness -- no checking for illegal
|
||||||
// characters, malformed paths, etc.
|
// characters, malformed paths, etc.
|
||||||
|
|
||||||
class GTEST_API_ FilePath {
|
class GTEST_API_ FilePath {
|
||||||
public:
|
public:
|
||||||
FilePath() : pathname_("") { }
|
FilePath() : pathname_("") { }
|
||||||
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
|
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
|
||||||
|
|
||||||
explicit FilePath(const std::string& pathname) : pathname_(pathname) {
|
explicit FilePath(const std::string& pathname) : pathname_(pathname) {
|
||||||
Normalize();
|
Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath& operator=(const FilePath& rhs) {
|
FilePath& operator=(const FilePath& rhs) {
|
||||||
Set(rhs);
|
Set(rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Set(const FilePath& rhs) {
|
void Set(const FilePath& rhs) {
|
||||||
pathname_ = rhs.pathname_;
|
pathname_ = rhs.pathname_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& string() const { return pathname_; }
|
const std::string& string() const { return pathname_; }
|
||||||
const char* c_str() const { return pathname_.c_str(); }
|
const char* c_str() const { return pathname_.c_str(); }
|
||||||
|
|
||||||
// Returns the current working directory, or "" if unsuccessful.
|
// Returns the current working directory, or "" if unsuccessful.
|
||||||
static FilePath GetCurrentDir();
|
static FilePath GetCurrentDir();
|
||||||
|
|
||||||
// Given directory = "dir", base_name = "test", number = 0,
|
// Given directory = "dir", base_name = "test", number = 0,
|
||||||
// extension = "xml", returns "dir/test.xml". If number is greater
|
// extension = "xml", returns "dir/test.xml". If number is greater
|
||||||
// than zero (e.g., 12), returns "dir/test_12.xml".
|
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||||
// On Windows platform, uses \ as the separator rather than /.
|
// On Windows platform, uses \ as the separator rather than /.
|
||||||
static FilePath MakeFileName(const FilePath& directory,
|
static FilePath MakeFileName(const FilePath& directory,
|
||||||
const FilePath& base_name,
|
const FilePath& base_name,
|
||||||
int number,
|
int number,
|
||||||
const char* extension);
|
const char* extension);
|
||||||
|
|
||||||
// Given directory = "dir", relative_path = "test.xml",
|
// Given directory = "dir", relative_path = "test.xml",
|
||||||
// returns "dir/test.xml".
|
// returns "dir/test.xml".
|
||||||
// On Windows, uses \ as the separator rather than /.
|
// On Windows, uses \ as the separator rather than /.
|
||||||
static FilePath ConcatPaths(const FilePath& directory,
|
static FilePath ConcatPaths(const FilePath& directory,
|
||||||
const FilePath& relative_path);
|
const FilePath& relative_path);
|
||||||
|
|
||||||
// Returns a pathname for a file that does not currently exist. The pathname
|
// Returns a pathname for a file that does not currently exist. The pathname
|
||||||
// will be directory/base_name.extension or
|
// will be directory/base_name.extension or
|
||||||
// directory/base_name_<number>.extension if directory/base_name.extension
|
// directory/base_name_<number>.extension if directory/base_name.extension
|
||||||
// already exists. The number will be incremented until a pathname is found
|
// already exists. The number will be incremented until a pathname is found
|
||||||
// that does not already exist.
|
// that does not already exist.
|
||||||
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
|
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
|
||||||
// There could be a race condition if two or more processes are calling this
|
// There could be a race condition if two or more processes are calling this
|
||||||
// function at the same time -- they could both pick the same filename.
|
// function at the same time -- they could both pick the same filename.
|
||||||
static FilePath GenerateUniqueFileName(const FilePath& directory,
|
static FilePath GenerateUniqueFileName(const FilePath& directory,
|
||||||
const FilePath& base_name,
|
const FilePath& base_name,
|
||||||
const char* extension);
|
const char* extension);
|
||||||
|
|
||||||
// Returns true iff the path is "".
|
// Returns true iff the path is "".
|
||||||
bool IsEmpty() const { return pathname_.empty(); }
|
bool IsEmpty() const { return pathname_.empty(); }
|
||||||
|
|
||||||
// If input name has a trailing separator character, removes it and returns
|
// If input name has a trailing separator character, removes it and returns
|
||||||
// the name, otherwise return the name string unmodified.
|
// the name, otherwise return the name string unmodified.
|
||||||
// On Windows platform, uses \ as the separator, other platforms use /.
|
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||||
FilePath RemoveTrailingPathSeparator() const;
|
FilePath RemoveTrailingPathSeparator() const;
|
||||||
|
|
||||||
// Returns a copy of the FilePath with the directory part removed.
|
// Returns a copy of the FilePath with the directory part removed.
|
||||||
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
||||||
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
||||||
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
|
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
|
||||||
// returns an empty FilePath ("").
|
// returns an empty FilePath ("").
|
||||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
FilePath RemoveDirectoryName() const;
|
FilePath RemoveDirectoryName() const;
|
||||||
|
|
||||||
// RemoveFileName returns the directory path with the filename removed.
|
// RemoveFileName returns the directory path with the filename removed.
|
||||||
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
|
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
|
||||||
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
|
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
|
||||||
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
|
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
|
||||||
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
||||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
FilePath RemoveFileName() const;
|
FilePath RemoveFileName() const;
|
||||||
|
|
||||||
// Returns a copy of the FilePath with the case-insensitive extension removed.
|
// Returns a copy of the FilePath with the case-insensitive extension removed.
|
||||||
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
|
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
|
||||||
// FilePath("dir/file"). If a case-insensitive extension is not
|
// FilePath("dir/file"). If a case-insensitive extension is not
|
||||||
// found, returns a copy of the original FilePath.
|
// found, returns a copy of the original FilePath.
|
||||||
FilePath RemoveExtension(const char* extension) const;
|
FilePath RemoveExtension(const char* extension) const;
|
||||||
|
|
||||||
// Creates directories so that path exists. Returns true if successful or if
|
// Creates directories so that path exists. Returns true if successful or if
|
||||||
// the directories already exist; returns false if unable to create
|
// the directories already exist; returns false if unable to create
|
||||||
// directories for any reason. Will also return false if the FilePath does
|
// directories for any reason. Will also return false if the FilePath does
|
||||||
// not represent a directory (that is, it doesn't end with a path separator).
|
// not represent a directory (that is, it doesn't end with a path separator).
|
||||||
bool CreateDirectoriesRecursively() const;
|
bool CreateDirectoriesRecursively() const;
|
||||||
|
|
||||||
// Create the directory so that path exists. Returns true if successful or
|
// Create the directory so that path exists. Returns true if successful or
|
||||||
// if the directory already exists; returns false if unable to create the
|
// if the directory already exists; returns false if unable to create the
|
||||||
// directory for any reason, including if the parent directory does not
|
// directory for any reason, including if the parent directory does not
|
||||||
// exist. Not named "CreateDirectory" because that's a macro on Windows.
|
// exist. Not named "CreateDirectory" because that's a macro on Windows.
|
||||||
bool CreateFolder() const;
|
bool CreateFolder() const;
|
||||||
|
|
||||||
// Returns true if FilePath describes something in the file-system,
|
// Returns true if FilePath describes something in the file-system,
|
||||||
// either a file, directory, or whatever, and that something exists.
|
// either a file, directory, or whatever, and that something exists.
|
||||||
bool FileOrDirectoryExists() const;
|
bool FileOrDirectoryExists() const;
|
||||||
|
|
||||||
// Returns true if pathname describes a directory in the file-system
|
// Returns true if pathname describes a directory in the file-system
|
||||||
// that exists.
|
// that exists.
|
||||||
bool DirectoryExists() const;
|
bool DirectoryExists() const;
|
||||||
|
|
||||||
// Returns true if FilePath ends with a path separator, which indicates that
|
// Returns true if FilePath ends with a path separator, which indicates that
|
||||||
// it is intended to represent a directory. Returns false otherwise.
|
// it is intended to represent a directory. Returns false otherwise.
|
||||||
// This does NOT check that a directory (or file) actually exists.
|
// This does NOT check that a directory (or file) actually exists.
|
||||||
bool IsDirectory() const;
|
bool IsDirectory() const;
|
||||||
|
|
||||||
// Returns true if pathname describes a root directory. (Windows has one
|
// Returns true if pathname describes a root directory. (Windows has one
|
||||||
// root directory per disk drive.)
|
// root directory per disk drive.)
|
||||||
bool IsRootDirectory() const;
|
bool IsRootDirectory() const;
|
||||||
|
|
||||||
// Returns true if pathname describes an absolute path.
|
// Returns true if pathname describes an absolute path.
|
||||||
bool IsAbsolutePath() const;
|
bool IsAbsolutePath() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Replaces multiple consecutive separators with a single separator.
|
// Replaces multiple consecutive separators with a single separator.
|
||||||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||||
// redundancies that might be in a pathname involving "." or "..".
|
// redundancies that might be in a pathname involving "." or "..".
|
||||||
//
|
//
|
||||||
// A pathname with multiple consecutive separators may occur either through
|
// A pathname with multiple consecutive separators may occur either through
|
||||||
// user error or as a result of some scripts or APIs that generate a pathname
|
// user error or as a result of some scripts or APIs that generate a pathname
|
||||||
// with a trailing separator. On other platforms the same API or script
|
// with a trailing separator. On other platforms the same API or script
|
||||||
// may NOT generate a pathname with a trailing "/". Then elsewhere that
|
// may NOT generate a pathname with a trailing "/". Then elsewhere that
|
||||||
// pathname may have another "/" and pathname components added to it,
|
// pathname may have another "/" and pathname components added to it,
|
||||||
// without checking for the separator already being there.
|
// without checking for the separator already being there.
|
||||||
// The script language and operating system may allow paths like "foo//bar"
|
// The script language and operating system may allow paths like "foo//bar"
|
||||||
// but some of the functions in FilePath will not handle that correctly. In
|
// but some of the functions in FilePath will not handle that correctly. In
|
||||||
// particular, RemoveTrailingPathSeparator() only removes one separator, and
|
// particular, RemoveTrailingPathSeparator() only removes one separator, and
|
||||||
// it is called in CreateDirectoriesRecursively() assuming that it will change
|
// it is called in CreateDirectoriesRecursively() assuming that it will change
|
||||||
// a pathname from directory syntax (trailing separator) to filename syntax.
|
// a pathname from directory syntax (trailing separator) to filename syntax.
|
||||||
//
|
//
|
||||||
// On Windows this method also replaces the alternate path separator '/' with
|
// On Windows this method also replaces the alternate path separator '/' with
|
||||||
// the primary path separator '\\', so that for example "bar\\/\\foo" becomes
|
// the primary path separator '\\', so that for example "bar\\/\\foo" becomes
|
||||||
// "bar\\foo".
|
// "bar\\foo".
|
||||||
|
|
||||||
void Normalize();
|
void Normalize();
|
||||||
|
|
||||||
// Returns a pointer to the last occurence of a valid path separator in
|
// Returns a pointer to the last occurence of a valid path separator in
|
||||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||||
// separators. Returns NULL if no path separator was found.
|
// separators. Returns NULL if no path separator was found.
|
||||||
const char* FindLastPathSeparator() const;
|
const char* FindLastPathSeparator() const;
|
||||||
|
|
||||||
std::string pathname_;
|
std::string pathname_;
|
||||||
}; // class FilePath
|
}; // class FilePath
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,233 +1,233 @@
|
|||||||
// Copyright 2003 Google Inc.
|
// Copyright 2003 Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Authors: Dan Egnor (egnor@google.com)
|
// Authors: Dan Egnor (egnor@google.com)
|
||||||
//
|
//
|
||||||
// A "smart" pointer type with reference tracking. Every pointer to a
|
// A "smart" pointer type with reference tracking. Every pointer to a
|
||||||
// particular object is kept on a circular linked list. When the last pointer
|
// particular object is kept on a circular linked list. When the last pointer
|
||||||
// to an object is destroyed or reassigned, the object is deleted.
|
// to an object is destroyed or reassigned, the object is deleted.
|
||||||
//
|
//
|
||||||
// Used properly, this deletes the object when the last reference goes away.
|
// Used properly, this deletes the object when the last reference goes away.
|
||||||
// There are several caveats:
|
// There are several caveats:
|
||||||
// - Like all reference counting schemes, cycles lead to leaks.
|
// - Like all reference counting schemes, cycles lead to leaks.
|
||||||
// - Each smart pointer is actually two pointers (8 bytes instead of 4).
|
// - Each smart pointer is actually two pointers (8 bytes instead of 4).
|
||||||
// - Every time a pointer is assigned, the entire list of pointers to that
|
// - Every time a pointer is assigned, the entire list of pointers to that
|
||||||
// object is traversed. This class is therefore NOT SUITABLE when there
|
// object is traversed. This class is therefore NOT SUITABLE when there
|
||||||
// will often be more than two or three pointers to a particular object.
|
// will often be more than two or three pointers to a particular object.
|
||||||
// - References are only tracked as long as linked_ptr<> objects are copied.
|
// - References are only tracked as long as linked_ptr<> objects are copied.
|
||||||
// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
|
// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
|
||||||
// will happen (double deletion).
|
// will happen (double deletion).
|
||||||
//
|
//
|
||||||
// A good use of this class is storing object references in STL containers.
|
// A good use of this class is storing object references in STL containers.
|
||||||
// You can safely put linked_ptr<> in a vector<>.
|
// You can safely put linked_ptr<> in a vector<>.
|
||||||
// Other uses may not be as good.
|
// Other uses may not be as good.
|
||||||
//
|
//
|
||||||
// Note: If you use an incomplete type with linked_ptr<>, the class
|
// Note: If you use an incomplete type with linked_ptr<>, the class
|
||||||
// *containing* linked_ptr<> must have a constructor and destructor (even
|
// *containing* linked_ptr<> must have a constructor and destructor (even
|
||||||
// if they do nothing!).
|
// if they do nothing!).
|
||||||
//
|
//
|
||||||
// Bill Gibbons suggested we use something like this.
|
// Bill Gibbons suggested we use something like this.
|
||||||
//
|
//
|
||||||
// Thread Safety:
|
// Thread Safety:
|
||||||
// Unlike other linked_ptr implementations, in this implementation
|
// Unlike other linked_ptr implementations, in this implementation
|
||||||
// a linked_ptr object is thread-safe in the sense that:
|
// a linked_ptr object is thread-safe in the sense that:
|
||||||
// - it's safe to copy linked_ptr objects concurrently,
|
// - it's safe to copy linked_ptr objects concurrently,
|
||||||
// - it's safe to copy *from* a linked_ptr and read its underlying
|
// - it's safe to copy *from* a linked_ptr and read its underlying
|
||||||
// raw pointer (e.g. via get()) concurrently, and
|
// raw pointer (e.g. via get()) concurrently, and
|
||||||
// - it's safe to write to two linked_ptrs that point to the same
|
// - it's safe to write to two linked_ptrs that point to the same
|
||||||
// shared object concurrently.
|
// shared object concurrently.
|
||||||
// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
|
// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
|
||||||
// confusion with normal linked_ptr.
|
// confusion with normal linked_ptr.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Protects copying of all linked_ptr objects.
|
// Protects copying of all linked_ptr objects.
|
||||||
GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
|
||||||
|
|
||||||
// This is used internally by all instances of linked_ptr<>. It needs to be
|
// This is used internally by all instances of linked_ptr<>. It needs to be
|
||||||
// a non-template class because different types of linked_ptr<> can refer to
|
// a non-template class because different types of linked_ptr<> can refer to
|
||||||
// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
|
// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
|
||||||
// So, it needs to be possible for different types of linked_ptr to participate
|
// So, it needs to be possible for different types of linked_ptr to participate
|
||||||
// in the same circular linked list, so we need a single class type here.
|
// in the same circular linked list, so we need a single class type here.
|
||||||
//
|
//
|
||||||
// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>.
|
// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>.
|
||||||
class linked_ptr_internal {
|
class linked_ptr_internal {
|
||||||
public:
|
public:
|
||||||
// Create a new circle that includes only this instance.
|
// Create a new circle that includes only this instance.
|
||||||
void join_new() {
|
void join_new() {
|
||||||
next_ = this;
|
next_ = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Many linked_ptr operations may change p.link_ for some linked_ptr
|
// Many linked_ptr operations may change p.link_ for some linked_ptr
|
||||||
// variable p in the same circle as this object. Therefore we need
|
// variable p in the same circle as this object. Therefore we need
|
||||||
// to prevent two such operations from occurring concurrently.
|
// to prevent two such operations from occurring concurrently.
|
||||||
//
|
//
|
||||||
// Note that different types of linked_ptr objects can coexist in a
|
// Note that different types of linked_ptr objects can coexist in a
|
||||||
// circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
|
// circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
|
||||||
// linked_ptr<Derived2>). Therefore we must use a single mutex to
|
// linked_ptr<Derived2>). Therefore we must use a single mutex to
|
||||||
// protect all linked_ptr objects. This can create serious
|
// protect all linked_ptr objects. This can create serious
|
||||||
// contention in production code, but is acceptable in a testing
|
// contention in production code, but is acceptable in a testing
|
||||||
// framework.
|
// framework.
|
||||||
|
|
||||||
// Join an existing circle.
|
// Join an existing circle.
|
||||||
void join(linked_ptr_internal const* ptr)
|
void join(linked_ptr_internal const* ptr)
|
||||||
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
|
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
|
||||||
MutexLock lock(&g_linked_ptr_mutex);
|
MutexLock lock(&g_linked_ptr_mutex);
|
||||||
|
|
||||||
linked_ptr_internal const* p = ptr;
|
linked_ptr_internal const* p = ptr;
|
||||||
while (p->next_ != ptr) p = p->next_;
|
while (p->next_ != ptr) p = p->next_;
|
||||||
p->next_ = this;
|
p->next_ = this;
|
||||||
next_ = ptr;
|
next_ = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Leave whatever circle we're part of. Returns true if we were the
|
// Leave whatever circle we're part of. Returns true if we were the
|
||||||
// last member of the circle. Once this is done, you can join() another.
|
// last member of the circle. Once this is done, you can join() another.
|
||||||
bool depart()
|
bool depart()
|
||||||
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
|
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
|
||||||
MutexLock lock(&g_linked_ptr_mutex);
|
MutexLock lock(&g_linked_ptr_mutex);
|
||||||
|
|
||||||
if (next_ == this) return true;
|
if (next_ == this) return true;
|
||||||
linked_ptr_internal const* p = next_;
|
linked_ptr_internal const* p = next_;
|
||||||
while (p->next_ != this) p = p->next_;
|
while (p->next_ != this) p = p->next_;
|
||||||
p->next_ = next_;
|
p->next_ = next_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable linked_ptr_internal const* next_;
|
mutable linked_ptr_internal const* next_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class linked_ptr {
|
class linked_ptr {
|
||||||
public:
|
public:
|
||||||
typedef T element_type;
|
typedef T element_type;
|
||||||
|
|
||||||
// Take over ownership of a raw pointer. This should happen as soon as
|
// Take over ownership of a raw pointer. This should happen as soon as
|
||||||
// possible after the object is created.
|
// possible after the object is created.
|
||||||
explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
|
explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
|
||||||
~linked_ptr() { depart(); }
|
~linked_ptr() { depart(); }
|
||||||
|
|
||||||
// Copy an existing linked_ptr<>, adding ourselves to the list of references.
|
// Copy an existing linked_ptr<>, adding ourselves to the list of references.
|
||||||
template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
|
template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
|
||||||
linked_ptr(linked_ptr const& ptr) { // NOLINT
|
linked_ptr(linked_ptr const& ptr) { // NOLINT
|
||||||
assert(&ptr != this);
|
assert(&ptr != this);
|
||||||
copy(&ptr);
|
copy(&ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assignment releases the old value and acquires the new.
|
// Assignment releases the old value and acquires the new.
|
||||||
template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
|
template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
|
||||||
depart();
|
depart();
|
||||||
copy(&ptr);
|
copy(&ptr);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
linked_ptr& operator=(linked_ptr const& ptr) {
|
linked_ptr& operator=(linked_ptr const& ptr) {
|
||||||
if (&ptr != this) {
|
if (&ptr != this) {
|
||||||
depart();
|
depart();
|
||||||
copy(&ptr);
|
copy(&ptr);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Smart pointer members.
|
// Smart pointer members.
|
||||||
void reset(T* ptr = NULL) {
|
void reset(T* ptr = NULL) {
|
||||||
depart();
|
depart();
|
||||||
capture(ptr);
|
capture(ptr);
|
||||||
}
|
}
|
||||||
T* get() const { return value_; }
|
T* get() const { return value_; }
|
||||||
T* operator->() const { return value_; }
|
T* operator->() const { return value_; }
|
||||||
T& operator*() const { return *value_; }
|
T& operator*() const { return *value_; }
|
||||||
|
|
||||||
bool operator==(T* p) const { return value_ == p; }
|
bool operator==(T* p) const { return value_ == p; }
|
||||||
bool operator!=(T* p) const { return value_ != p; }
|
bool operator!=(T* p) const { return value_ != p; }
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator==(linked_ptr<U> const& ptr) const {
|
bool operator==(linked_ptr<U> const& ptr) const {
|
||||||
return value_ == ptr.get();
|
return value_ == ptr.get();
|
||||||
}
|
}
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator!=(linked_ptr<U> const& ptr) const {
|
bool operator!=(linked_ptr<U> const& ptr) const {
|
||||||
return value_ != ptr.get();
|
return value_ != ptr.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename U>
|
template <typename U>
|
||||||
friend class linked_ptr;
|
friend class linked_ptr;
|
||||||
|
|
||||||
T* value_;
|
T* value_;
|
||||||
linked_ptr_internal link_;
|
linked_ptr_internal link_;
|
||||||
|
|
||||||
void depart() {
|
void depart() {
|
||||||
if (link_.depart()) delete value_;
|
if (link_.depart()) delete value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void capture(T* ptr) {
|
void capture(T* ptr) {
|
||||||
value_ = ptr;
|
value_ = ptr;
|
||||||
link_.join_new();
|
link_.join_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U> void copy(linked_ptr<U> const* ptr) {
|
template <typename U> void copy(linked_ptr<U> const* ptr) {
|
||||||
value_ = ptr->get();
|
value_ = ptr->get();
|
||||||
if (value_)
|
if (value_)
|
||||||
link_.join(&ptr->link_);
|
link_.join(&ptr->link_);
|
||||||
else
|
else
|
||||||
link_.join_new();
|
link_.join_new();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> inline
|
template<typename T> inline
|
||||||
bool operator==(T* ptr, const linked_ptr<T>& x) {
|
bool operator==(T* ptr, const linked_ptr<T>& x) {
|
||||||
return ptr == x.get();
|
return ptr == x.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline
|
template<typename T> inline
|
||||||
bool operator!=(T* ptr, const linked_ptr<T>& x) {
|
bool operator!=(T* ptr, const linked_ptr<T>& x) {
|
||||||
return ptr != x.get();
|
return ptr != x.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// A function to convert T* into linked_ptr<T>
|
// A function to convert T* into linked_ptr<T>
|
||||||
// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
|
// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
|
||||||
// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
|
// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
|
||||||
template <typename T>
|
template <typename T>
|
||||||
linked_ptr<T> make_linked_ptr(T* ptr) {
|
linked_ptr<T> make_linked_ptr(T* ptr) {
|
||||||
return linked_ptr<T>(ptr);
|
return linked_ptr<T>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,301 +1,301 @@
|
|||||||
$$ -*- mode: c++; -*-
|
$$ -*- mode: c++; -*-
|
||||||
$var n = 50 $$ Maximum length of Values arguments we want to support.
|
$var n = 50 $$ Maximum length of Values arguments we want to support.
|
||||||
$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
|
$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
|
||||||
// Copyright 2008 Google Inc.
|
// Copyright 2008 Google Inc.
|
||||||
// All Rights Reserved.
|
// All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: vladl@google.com (Vlad Losev)
|
// Author: vladl@google.com (Vlad Losev)
|
||||||
|
|
||||||
// Type and function utilities for implementing parameterized tests.
|
// Type and function utilities for implementing parameterized tests.
|
||||||
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||||
//
|
//
|
||||||
// Currently Google Test supports at most $n arguments in Values,
|
// Currently Google Test supports at most $n arguments in Values,
|
||||||
// and at most $maxtuple arguments in Combine. Please contact
|
// and at most $maxtuple arguments in Combine. Please contact
|
||||||
// googletestframework@googlegroups.com if you need more.
|
// googletestframework@googlegroups.com if you need more.
|
||||||
// Please note that the number of arguments to Combine is limited
|
// Please note that the number of arguments to Combine is limited
|
||||||
// by the maximum arity of the implementation of tuple which is
|
// by the maximum arity of the implementation of tr1::tuple which is
|
||||||
// currently set at $maxtuple.
|
// currently set at $maxtuple.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||||
|
|
||||||
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
// scripts/fuse_gtest.py depends on gtest's own header being #included
|
||||||
// *unconditionally*. Therefore these #includes cannot be moved
|
// *unconditionally*. Therefore these #includes cannot be moved
|
||||||
// inside #if GTEST_HAS_PARAM_TEST.
|
// inside #if GTEST_HAS_PARAM_TEST.
|
||||||
#include "gtest/internal/gtest-param-util.h"
|
#include "gtest/internal/gtest-param-util.h"
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#if GTEST_HAS_PARAM_TEST
|
#if GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// Forward declarations of ValuesIn(), which is implemented in
|
// Forward declarations of ValuesIn(), which is implemented in
|
||||||
// include/gtest/gtest-param-test.h.
|
// include/gtest/gtest-param-test.h.
|
||||||
template <typename ForwardIterator>
|
template <typename ForwardIterator>
|
||||||
internal::ParamGenerator<
|
internal::ParamGenerator<
|
||||||
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
|
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
|
||||||
ValuesIn(ForwardIterator begin, ForwardIterator end);
|
ValuesIn(ForwardIterator begin, ForwardIterator end);
|
||||||
|
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
|
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
|
||||||
|
|
||||||
template <class Container>
|
template <class Container>
|
||||||
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
internal::ParamGenerator<typename Container::value_type> ValuesIn(
|
||||||
const Container& container);
|
const Container& container);
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Used in the Values() function to provide polymorphic capabilities.
|
// Used in the Values() function to provide polymorphic capabilities.
|
||||||
template <typename T1>
|
template <typename T1>
|
||||||
class ValueArray1 {
|
class ValueArray1 {
|
||||||
public:
|
public:
|
||||||
explicit ValueArray1(T1 v1) : v1_(v1) {}
|
explicit ValueArray1(T1 v1) : v1_(v1) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
|
operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
void operator=(const ValueArray1& other);
|
void operator=(const ValueArray1& other);
|
||||||
|
|
||||||
const T1 v1_;
|
const T1 v1_;
|
||||||
};
|
};
|
||||||
|
|
||||||
$range i 2..n
|
$range i 2..n
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
template <$for j, [[typename T$j]]>
|
||||||
class ValueArray$i {
|
class ValueArray$i {
|
||||||
public:
|
public:
|
||||||
ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
|
ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
operator ParamGenerator<T>() const {
|
operator ParamGenerator<T>() const {
|
||||||
const T array[] = {$for j, [[static_cast<T>(v$(j)_)]]};
|
const T array[] = {$for j, [[static_cast<T>(v$(j)_)]]};
|
||||||
return ValuesIn(array);
|
return ValuesIn(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
void operator=(const ValueArray$i& other);
|
void operator=(const ValueArray$i& other);
|
||||||
|
|
||||||
$for j [[
|
$for j [[
|
||||||
|
|
||||||
const T$j v$(j)_;
|
const T$j v$(j)_;
|
||||||
]]
|
]]
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
# if GTEST_HAS_COMBINE
|
# if GTEST_HAS_COMBINE
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Generates values from the Cartesian product of values produced
|
// Generates values from the Cartesian product of values produced
|
||||||
// by the argument generators.
|
// by the argument generators.
|
||||||
//
|
//
|
||||||
$range i 2..maxtuple
|
$range i 2..maxtuple
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
$range k 2..i
|
$range k 2..i
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
template <$for j, [[typename T$j]]>
|
||||||
class CartesianProductGenerator$i
|
class CartesianProductGenerator$i
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > {
|
: public ParamGeneratorInterface< ::std::tr1::tuple<$for j, [[T$j]]> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<$for j, [[T$j]]> ParamType;
|
typedef ::std::tr1::tuple<$for j, [[T$j]]> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
|
CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
|
||||||
: $for j, [[g$(j)_(g$j)]] {}
|
: $for j, [[g$(j)_(g$j)]] {}
|
||||||
virtual ~CartesianProductGenerator$i() {}
|
virtual ~CartesianProductGenerator$i() {}
|
||||||
|
|
||||||
virtual ParamIteratorInterface<ParamType>* Begin() const {
|
virtual ParamIteratorInterface<ParamType>* Begin() const {
|
||||||
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
|
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
|
||||||
}
|
}
|
||||||
virtual ParamIteratorInterface<ParamType>* End() const {
|
virtual ParamIteratorInterface<ParamType>* End() const {
|
||||||
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
|
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Iterator : public ParamIteratorInterface<ParamType> {
|
class Iterator : public ParamIteratorInterface<ParamType> {
|
||||||
public:
|
public:
|
||||||
Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
|
Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
|
||||||
|
|
||||||
const ParamGenerator<T$j>& g$j,
|
const ParamGenerator<T$j>& g$j,
|
||||||
const typename ParamGenerator<T$j>::iterator& current$(j)]])
|
const typename ParamGenerator<T$j>::iterator& current$(j)]])
|
||||||
: base_(base),
|
: base_(base),
|
||||||
$for j, [[
|
$for j, [[
|
||||||
|
|
||||||
begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
|
begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
|
||||||
]] {
|
]] {
|
||||||
ComputeCurrentValue();
|
ComputeCurrentValue();
|
||||||
}
|
}
|
||||||
virtual ~Iterator() {}
|
virtual ~Iterator() {}
|
||||||
|
|
||||||
virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
|
virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
|
||||||
return base_;
|
return base_;
|
||||||
}
|
}
|
||||||
// Advance should not be called on beyond-of-range iterators
|
// Advance should not be called on beyond-of-range iterators
|
||||||
// so no component iterators must be beyond end of range, either.
|
// so no component iterators must be beyond end of range, either.
|
||||||
virtual void Advance() {
|
virtual void Advance() {
|
||||||
assert(!AtEnd());
|
assert(!AtEnd());
|
||||||
++current$(i)_;
|
++current$(i)_;
|
||||||
|
|
||||||
$for k [[
|
$for k [[
|
||||||
if (current$(i+2-k)_ == end$(i+2-k)_) {
|
if (current$(i+2-k)_ == end$(i+2-k)_) {
|
||||||
current$(i+2-k)_ = begin$(i+2-k)_;
|
current$(i+2-k)_ = begin$(i+2-k)_;
|
||||||
++current$(i+2-k-1)_;
|
++current$(i+2-k-1)_;
|
||||||
}
|
}
|
||||||
|
|
||||||
]]
|
]]
|
||||||
ComputeCurrentValue();
|
ComputeCurrentValue();
|
||||||
}
|
}
|
||||||
virtual ParamIteratorInterface<ParamType>* Clone() const {
|
virtual ParamIteratorInterface<ParamType>* Clone() const {
|
||||||
return new Iterator(*this);
|
return new Iterator(*this);
|
||||||
}
|
}
|
||||||
virtual const ParamType* Current() const { return ¤t_value_; }
|
virtual const ParamType* Current() const { return ¤t_value_; }
|
||||||
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
|
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
|
||||||
// Having the same base generator guarantees that the other
|
// Having the same base generator guarantees that the other
|
||||||
// iterator is of the same type and we can downcast.
|
// iterator is of the same type and we can downcast.
|
||||||
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
|
||||||
<< "The program attempted to compare iterators "
|
<< "The program attempted to compare iterators "
|
||||||
<< "from different generators." << std::endl;
|
<< "from different generators." << std::endl;
|
||||||
const Iterator* typed_other =
|
const Iterator* typed_other =
|
||||||
CheckedDowncastToActualType<const Iterator>(&other);
|
CheckedDowncastToActualType<const Iterator>(&other);
|
||||||
// We must report iterators equal if they both point beyond their
|
// We must report iterators equal if they both point beyond their
|
||||||
// respective ranges. That can happen in a variety of fashions,
|
// respective ranges. That can happen in a variety of fashions,
|
||||||
// so we have to consult AtEnd().
|
// so we have to consult AtEnd().
|
||||||
return (AtEnd() && typed_other->AtEnd()) ||
|
return (AtEnd() && typed_other->AtEnd()) ||
|
||||||
($for j && [[
|
($for j && [[
|
||||||
|
|
||||||
current$(j)_ == typed_other->current$(j)_
|
current$(j)_ == typed_other->current$(j)_
|
||||||
]]);
|
]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Iterator(const Iterator& other)
|
Iterator(const Iterator& other)
|
||||||
: base_(other.base_), $for j, [[
|
: base_(other.base_), $for j, [[
|
||||||
|
|
||||||
begin$(j)_(other.begin$(j)_),
|
begin$(j)_(other.begin$(j)_),
|
||||||
end$(j)_(other.end$(j)_),
|
end$(j)_(other.end$(j)_),
|
||||||
current$(j)_(other.current$(j)_)
|
current$(j)_(other.current$(j)_)
|
||||||
]] {
|
]] {
|
||||||
ComputeCurrentValue();
|
ComputeCurrentValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComputeCurrentValue() {
|
void ComputeCurrentValue() {
|
||||||
if (!AtEnd())
|
if (!AtEnd())
|
||||||
current_value_ = ParamType($for j, [[*current$(j)_]]);
|
current_value_ = ParamType($for j, [[*current$(j)_]]);
|
||||||
}
|
}
|
||||||
bool AtEnd() const {
|
bool AtEnd() const {
|
||||||
// We must report iterator past the end of the range when either of the
|
// We must report iterator past the end of the range when either of the
|
||||||
// component iterators has reached the end of its range.
|
// component iterators has reached the end of its range.
|
||||||
return
|
return
|
||||||
$for j || [[
|
$for j || [[
|
||||||
|
|
||||||
current$(j)_ == end$(j)_
|
current$(j)_ == end$(j)_
|
||||||
]];
|
]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
void operator=(const Iterator& other);
|
void operator=(const Iterator& other);
|
||||||
|
|
||||||
const ParamGeneratorInterface<ParamType>* const base_;
|
const ParamGeneratorInterface<ParamType>* const base_;
|
||||||
// begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
|
// begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
|
||||||
// current[i]_ is the actual traversing iterator.
|
// current[i]_ is the actual traversing iterator.
|
||||||
$for j [[
|
$for j [[
|
||||||
|
|
||||||
const typename ParamGenerator<T$j>::iterator begin$(j)_;
|
const typename ParamGenerator<T$j>::iterator begin$(j)_;
|
||||||
const typename ParamGenerator<T$j>::iterator end$(j)_;
|
const typename ParamGenerator<T$j>::iterator end$(j)_;
|
||||||
typename ParamGenerator<T$j>::iterator current$(j)_;
|
typename ParamGenerator<T$j>::iterator current$(j)_;
|
||||||
]]
|
]]
|
||||||
|
|
||||||
ParamType current_value_;
|
ParamType current_value_;
|
||||||
}; // class CartesianProductGenerator$i::Iterator
|
}; // class CartesianProductGenerator$i::Iterator
|
||||||
|
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
void operator=(const CartesianProductGenerator$i& other);
|
void operator=(const CartesianProductGenerator$i& other);
|
||||||
|
|
||||||
|
|
||||||
$for j [[
|
$for j [[
|
||||||
const ParamGenerator<T$j> g$(j)_;
|
const ParamGenerator<T$j> g$(j)_;
|
||||||
|
|
||||||
]]
|
]]
|
||||||
}; // class CartesianProductGenerator$i
|
}; // class CartesianProductGenerator$i
|
||||||
|
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
//
|
//
|
||||||
// Helper classes providing Combine() with polymorphic features. They allow
|
// Helper classes providing Combine() with polymorphic features. They allow
|
||||||
// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
|
// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
|
||||||
// convertible to U.
|
// convertible to U.
|
||||||
//
|
//
|
||||||
$range i 2..maxtuple
|
$range i 2..maxtuple
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
|
|
||||||
template <$for j, [[class Generator$j]]>
|
template <$for j, [[class Generator$j]]>
|
||||||
class CartesianProductHolder$i {
|
class CartesianProductHolder$i {
|
||||||
public:
|
public:
|
||||||
CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
|
CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
|
||||||
: $for j, [[g$(j)_(g$j)]] {}
|
: $for j, [[g$(j)_(g$j)]] {}
|
||||||
template <$for j, [[typename T$j]]>
|
template <$for j, [[typename T$j]]>
|
||||||
operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const {
|
operator ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >(
|
return ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >(
|
||||||
new CartesianProductGenerator$i<$for j, [[T$j]]>(
|
new CartesianProductGenerator$i<$for j, [[T$j]]>(
|
||||||
$for j,[[
|
$for j,[[
|
||||||
|
|
||||||
static_cast<ParamGenerator<T$j> >(g$(j)_)
|
static_cast<ParamGenerator<T$j> >(g$(j)_)
|
||||||
]]));
|
]]));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// No implementation - assignment is unsupported.
|
// No implementation - assignment is unsupported.
|
||||||
void operator=(const CartesianProductHolder$i& other);
|
void operator=(const CartesianProductHolder$i& other);
|
||||||
|
|
||||||
|
|
||||||
$for j [[
|
$for j [[
|
||||||
const Generator$j g$(j)_;
|
const Generator$j g$(j)_;
|
||||||
|
|
||||||
]]
|
]]
|
||||||
}; // class CartesianProductHolder$i
|
}; // class CartesianProductHolder$i
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
# endif // GTEST_HAS_COMBINE
|
# endif // GTEST_HAS_COMBINE
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_HAS_PARAM_TEST
|
#endif // GTEST_HAS_PARAM_TEST
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,167 +1,167 @@
|
|||||||
// Copyright 2005, Google Inc.
|
// Copyright 2005, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
|
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
|
||||||
//
|
//
|
||||||
// The Google C++ Testing Framework (Google Test)
|
// The Google C++ Testing Framework (Google Test)
|
||||||
//
|
//
|
||||||
// This header file declares the String class and functions used internally by
|
// This header file declares the String class and functions used internally by
|
||||||
// Google Test. They are subject to change without notice. They should not used
|
// Google Test. They are subject to change without notice. They should not used
|
||||||
// by code external to Google Test.
|
// by code external to Google Test.
|
||||||
//
|
//
|
||||||
// This header file is #included by <gtest/internal/gtest-internal.h>.
|
// This header file is #included by <gtest/internal/gtest-internal.h>.
|
||||||
// It should not be #included by other files.
|
// It should not be #included by other files.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
// string.h is not guaranteed to provide strcpy on C++ Builder.
|
||||||
# include <mem.h>
|
# include <mem.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// String - an abstract class holding static string utilities.
|
// String - an abstract class holding static string utilities.
|
||||||
class GTEST_API_ String {
|
class GTEST_API_ String {
|
||||||
public:
|
public:
|
||||||
// Static utility methods
|
// Static utility methods
|
||||||
|
|
||||||
// Clones a 0-terminated C string, allocating memory using new. The
|
// Clones a 0-terminated C string, allocating memory using new. The
|
||||||
// caller is responsible for deleting the return value using
|
// caller is responsible for deleting the return value using
|
||||||
// delete[]. Returns the cloned string, or NULL if the input is
|
// delete[]. Returns the cloned string, or NULL if the input is
|
||||||
// NULL.
|
// NULL.
|
||||||
//
|
//
|
||||||
// This is different from strdup() in string.h, which allocates
|
// This is different from strdup() in string.h, which allocates
|
||||||
// memory using malloc().
|
// memory using malloc().
|
||||||
static const char* CloneCString(const char* c_str);
|
static const char* CloneCString(const char* c_str);
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
// Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
|
// Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
|
||||||
// able to pass strings to Win32 APIs on CE we need to convert them
|
// able to pass strings to Win32 APIs on CE we need to convert them
|
||||||
// to 'Unicode', UTF-16.
|
// to 'Unicode', UTF-16.
|
||||||
|
|
||||||
// Creates a UTF-16 wide string from the given ANSI string, allocating
|
// Creates a UTF-16 wide string from the given ANSI string, allocating
|
||||||
// memory using new. The caller is responsible for deleting the return
|
// memory using new. The caller is responsible for deleting the return
|
||||||
// value using delete[]. Returns the wide string, or NULL if the
|
// value using delete[]. Returns the wide string, or NULL if the
|
||||||
// input is NULL.
|
// input is NULL.
|
||||||
//
|
//
|
||||||
// The wide string is created using the ANSI codepage (CP_ACP) to
|
// The wide string is created using the ANSI codepage (CP_ACP) to
|
||||||
// match the behaviour of the ANSI versions of Win32 calls and the
|
// match the behaviour of the ANSI versions of Win32 calls and the
|
||||||
// C runtime.
|
// C runtime.
|
||||||
static LPCWSTR AnsiToUtf16(const char* c_str);
|
static LPCWSTR AnsiToUtf16(const char* c_str);
|
||||||
|
|
||||||
// Creates an ANSI string from the given wide string, allocating
|
// Creates an ANSI string from the given wide string, allocating
|
||||||
// memory using new. The caller is responsible for deleting the return
|
// memory using new. The caller is responsible for deleting the return
|
||||||
// value using delete[]. Returns the ANSI string, or NULL if the
|
// value using delete[]. Returns the ANSI string, or NULL if the
|
||||||
// input is NULL.
|
// input is NULL.
|
||||||
//
|
//
|
||||||
// The returned string is created using the ANSI codepage (CP_ACP) to
|
// The returned string is created using the ANSI codepage (CP_ACP) to
|
||||||
// match the behaviour of the ANSI versions of Win32 calls and the
|
// match the behaviour of the ANSI versions of Win32 calls and the
|
||||||
// C runtime.
|
// C runtime.
|
||||||
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
|
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compares two C strings. Returns true iff they have the same content.
|
// Compares two C strings. Returns true iff they have the same content.
|
||||||
//
|
//
|
||||||
// Unlike strcmp(), this function can handle NULL argument(s). A
|
// Unlike strcmp(), this function can handle NULL argument(s). A
|
||||||
// NULL C string is considered different to any non-NULL C string,
|
// NULL C string is considered different to any non-NULL C string,
|
||||||
// including the empty string.
|
// including the empty string.
|
||||||
static bool CStringEquals(const char* lhs, const char* rhs);
|
static bool CStringEquals(const char* lhs, const char* rhs);
|
||||||
|
|
||||||
// Converts a wide C string to a String using the UTF-8 encoding.
|
// Converts a wide C string to a String using the UTF-8 encoding.
|
||||||
// NULL will be converted to "(null)". If an error occurred during
|
// NULL will be converted to "(null)". If an error occurred during
|
||||||
// the conversion, "(failed to convert from wide string)" is
|
// the conversion, "(failed to convert from wide string)" is
|
||||||
// returned.
|
// returned.
|
||||||
static std::string ShowWideCString(const wchar_t* wide_c_str);
|
static std::string ShowWideCString(const wchar_t* wide_c_str);
|
||||||
|
|
||||||
// Compares two wide C strings. Returns true iff they have the same
|
// Compares two wide C strings. Returns true iff they have the same
|
||||||
// content.
|
// content.
|
||||||
//
|
//
|
||||||
// Unlike wcscmp(), this function can handle NULL argument(s). A
|
// Unlike wcscmp(), this function can handle NULL argument(s). A
|
||||||
// NULL C string is considered different to any non-NULL C string,
|
// NULL C string is considered different to any non-NULL C string,
|
||||||
// including the empty string.
|
// including the empty string.
|
||||||
static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
|
static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
|
||||||
|
|
||||||
// Compares two C strings, ignoring case. Returns true iff they
|
// Compares two C strings, ignoring case. Returns true iff they
|
||||||
// have the same content.
|
// have the same content.
|
||||||
//
|
//
|
||||||
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
// Unlike strcasecmp(), this function can handle NULL argument(s).
|
||||||
// A NULL C string is considered different to any non-NULL C string,
|
// A NULL C string is considered different to any non-NULL C string,
|
||||||
// including the empty string.
|
// including the empty string.
|
||||||
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
static bool CaseInsensitiveCStringEquals(const char* lhs,
|
||||||
const char* rhs);
|
const char* rhs);
|
||||||
|
|
||||||
// Compares two wide C strings, ignoring case. Returns true iff they
|
// Compares two wide C strings, ignoring case. Returns true iff they
|
||||||
// have the same content.
|
// have the same content.
|
||||||
//
|
//
|
||||||
// Unlike wcscasecmp(), this function can handle NULL argument(s).
|
// Unlike wcscasecmp(), this function can handle NULL argument(s).
|
||||||
// A NULL C string is considered different to any non-NULL wide C string,
|
// A NULL C string is considered different to any non-NULL wide C string,
|
||||||
// including the empty string.
|
// including the empty string.
|
||||||
// NB: The implementations on different platforms slightly differ.
|
// NB: The implementations on different platforms slightly differ.
|
||||||
// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
|
// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
|
||||||
// environment variable. On GNU platform this method uses wcscasecmp
|
// environment variable. On GNU platform this method uses wcscasecmp
|
||||||
// which compares according to LC_CTYPE category of the current locale.
|
// which compares according to LC_CTYPE category of the current locale.
|
||||||
// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
|
// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
|
||||||
// current locale.
|
// current locale.
|
||||||
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
|
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
|
||||||
const wchar_t* rhs);
|
const wchar_t* rhs);
|
||||||
|
|
||||||
// Returns true iff the given string ends with the given suffix, ignoring
|
// Returns true iff the given string ends with the given suffix, ignoring
|
||||||
// case. Any string is considered to end with an empty suffix.
|
// case. Any string is considered to end with an empty suffix.
|
||||||
static bool EndsWithCaseInsensitive(
|
static bool EndsWithCaseInsensitive(
|
||||||
const std::string& str, const std::string& suffix);
|
const std::string& str, const std::string& suffix);
|
||||||
|
|
||||||
// Formats an int value as "%02d".
|
// Formats an int value as "%02d".
|
||||||
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
|
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
|
||||||
|
|
||||||
// Formats an int value as "%X".
|
// Formats an int value as "%X".
|
||||||
static std::string FormatHexInt(int value);
|
static std::string FormatHexInt(int value);
|
||||||
|
|
||||||
// Formats a byte as "%02X".
|
// Formats a byte as "%02X".
|
||||||
static std::string FormatByte(unsigned char value);
|
static std::string FormatByte(unsigned char value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String(); // Not meant to be instantiated.
|
String(); // Not meant to be instantiated.
|
||||||
}; // class String
|
}; // class String
|
||||||
|
|
||||||
// Gets the content of the stringstream's buffer as an std::string. Each '\0'
|
// Gets the content of the stringstream's buffer as an std::string. Each '\0'
|
||||||
// character in the buffer is replaced with "\\0".
|
// character in the buffer is replaced with "\\0".
|
||||||
GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
|
GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,347 +1,339 @@
|
|||||||
$$ -*- mode: c++; -*-
|
$$ -*- mode: c++; -*-
|
||||||
$var n = 10 $$ Maximum number of tuple fields we want to support.
|
$var n = 10 $$ Maximum number of tuple fields we want to support.
|
||||||
$$ This meta comment fixes auto-indentation in Emacs. }}
|
$$ This meta comment fixes auto-indentation in Emacs. }}
|
||||||
// Copyright 2009 Google Inc.
|
// Copyright 2009 Google Inc.
|
||||||
// All Rights Reserved.
|
// All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
|
// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
||||||
|
|
||||||
#include <utility> // For ::std::pair.
|
#include <utility> // For ::std::pair.
|
||||||
|
|
||||||
// The compiler used in Symbian has a bug that prevents us from declaring the
|
// The compiler used in Symbian has a bug that prevents us from declaring the
|
||||||
// tuple template as a friend (it complains that tuple is redefined). This
|
// tuple template as a friend (it complains that tuple is redefined). This
|
||||||
// hack bypasses the bug by declaring the members that should otherwise be
|
// hack bypasses the bug by declaring the members that should otherwise be
|
||||||
// private as public.
|
// private as public.
|
||||||
// Sun Studio versions < 12 also have the above bug.
|
// Sun Studio versions < 12 also have the above bug.
|
||||||
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
|
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
|
||||||
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
|
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
|
||||||
#else
|
#else
|
||||||
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
|
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
|
||||||
template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
|
template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
|
||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict
|
|
||||||
// with our own definitions. Therefore using our own tuple does not work on
|
$range i 0..n-1
|
||||||
// those compilers.
|
$range j 0..n
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */
|
$range k 1..n
|
||||||
# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \
|
// GTEST_n_TUPLE_(T) is the type of an n-tuple.
|
||||||
GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers."
|
#define GTEST_0_TUPLE_(T) tuple<>
|
||||||
#endif
|
|
||||||
|
$for k [[
|
||||||
|
$range m 0..k-1
|
||||||
$range i 0..n-1
|
$range m2 k..n-1
|
||||||
$range j 0..n
|
#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
|
||||||
$range k 1..n
|
|
||||||
// GTEST_n_TUPLE_(T) is the type of an n-tuple.
|
]]
|
||||||
#define GTEST_0_TUPLE_(T) tuple<>
|
|
||||||
|
// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
|
||||||
$for k [[
|
|
||||||
$range m 0..k-1
|
$for j [[
|
||||||
$range m2 k..n-1
|
$range m 0..j-1
|
||||||
#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
|
#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
|
||||||
|
|
||||||
]]
|
|
||||||
|
]]
|
||||||
// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
|
|
||||||
|
// In theory, defining stuff in the ::std namespace is undefined
|
||||||
$for j [[
|
// behavior. We can do this as we are playing the role of a standard
|
||||||
$range m 0..j-1
|
// library vendor.
|
||||||
#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
|
namespace std {
|
||||||
|
namespace tr1 {
|
||||||
|
|
||||||
]]
|
template <$for i, [[typename T$i = void]]>
|
||||||
|
class tuple;
|
||||||
// In theory, defining stuff in the ::std namespace is undefined
|
|
||||||
// behavior. We can do this as we are playing the role of a standard
|
// Anything in namespace gtest_internal is Google Test's INTERNAL
|
||||||
// library vendor.
|
// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
|
||||||
namespace std {
|
namespace gtest_internal {
|
||||||
namespace tr1 {
|
|
||||||
|
// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
|
||||||
template <$for i, [[typename T$i = void]]>
|
template <typename T>
|
||||||
class tuple;
|
struct ByRef { typedef const T& type; }; // NOLINT
|
||||||
|
template <typename T>
|
||||||
// Anything in namespace gtest_internal is Google Test's INTERNAL
|
struct ByRef<T&> { typedef T& type; }; // NOLINT
|
||||||
// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
|
|
||||||
namespace gtest_internal {
|
// A handy wrapper for ByRef.
|
||||||
|
#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
|
||||||
// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
|
|
||||||
template <typename T>
|
// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
|
||||||
struct ByRef { typedef const T& type; }; // NOLINT
|
// is the same as tr1::add_reference<T>::type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct ByRef<T&> { typedef T& type; }; // NOLINT
|
struct AddRef { typedef T& type; }; // NOLINT
|
||||||
|
template <typename T>
|
||||||
// A handy wrapper for ByRef.
|
struct AddRef<T&> { typedef T& type; }; // NOLINT
|
||||||
#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
|
|
||||||
|
// A handy wrapper for AddRef.
|
||||||
// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
|
#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
|
||||||
// is the same as tr1::add_reference<T>::type.
|
|
||||||
template <typename T>
|
// A helper for implementing get<k>().
|
||||||
struct AddRef { typedef T& type; }; // NOLINT
|
template <int k> class Get;
|
||||||
template <typename T>
|
|
||||||
struct AddRef<T&> { typedef T& type; }; // NOLINT
|
// A helper for implementing tuple_element<k, T>. kIndexValid is true
|
||||||
|
// iff k < the number of fields in tuple type T.
|
||||||
// A handy wrapper for AddRef.
|
template <bool kIndexValid, int kIndex, class Tuple>
|
||||||
#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
|
struct TupleElement;
|
||||||
|
|
||||||
// A helper for implementing get<k>().
|
|
||||||
template <int k> class Get;
|
$for i [[
|
||||||
|
template <GTEST_$(n)_TYPENAMES_(T)>
|
||||||
// A helper for implementing tuple_element<k, T>. kIndexValid is true
|
struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
|
||||||
// iff k < the number of fields in tuple type T.
|
typedef T$i type;
|
||||||
template <bool kIndexValid, int kIndex, class Tuple>
|
};
|
||||||
struct TupleElement;
|
|
||||||
|
|
||||||
|
]]
|
||||||
$for i [[
|
} // namespace gtest_internal
|
||||||
template <GTEST_$(n)_TYPENAMES_(T)>
|
|
||||||
struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
|
template <>
|
||||||
typedef T$i type;
|
class tuple<> {
|
||||||
};
|
public:
|
||||||
|
tuple() {}
|
||||||
|
tuple(const tuple& /* t */) {}
|
||||||
]]
|
tuple& operator=(const tuple& /* t */) { return *this; }
|
||||||
} // namespace gtest_internal
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
class tuple<> {
|
$for k [[
|
||||||
public:
|
$range m 0..k-1
|
||||||
tuple() {}
|
template <GTEST_$(k)_TYPENAMES_(T)>
|
||||||
tuple(const tuple& /* t */) {}
|
class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
|
||||||
tuple& operator=(const tuple& /* t */) { return *this; }
|
public:
|
||||||
};
|
template <int k> friend class gtest_internal::Get;
|
||||||
|
|
||||||
|
tuple() : $for m, [[f$(m)_()]] {}
|
||||||
$for k [[
|
|
||||||
$range m 0..k-1
|
explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
|
||||||
template <GTEST_$(k)_TYPENAMES_(T)>
|
$for m, [[f$(m)_(f$m)]] {}
|
||||||
class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
|
|
||||||
public:
|
tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
|
||||||
template <int k> friend class gtest_internal::Get;
|
|
||||||
|
template <GTEST_$(k)_TYPENAMES_(U)>
|
||||||
tuple() : $for m, [[f$(m)_()]] {}
|
tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
|
||||||
|
|
||||||
explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
|
$if k == 2 [[
|
||||||
$for m, [[f$(m)_(f$m)]] {}
|
template <typename U0, typename U1>
|
||||||
|
tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
|
||||||
tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
|
|
||||||
|
]]
|
||||||
template <GTEST_$(k)_TYPENAMES_(U)>
|
|
||||||
tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
|
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
||||||
|
|
||||||
$if k == 2 [[
|
template <GTEST_$(k)_TYPENAMES_(U)>
|
||||||
template <typename U0, typename U1>
|
tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
|
||||||
tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
|
return CopyFrom(t);
|
||||||
|
}
|
||||||
]]
|
|
||||||
|
$if k == 2 [[
|
||||||
tuple& operator=(const tuple& t) { return CopyFrom(t); }
|
template <typename U0, typename U1>
|
||||||
|
tuple& operator=(const ::std::pair<U0, U1>& p) {
|
||||||
template <GTEST_$(k)_TYPENAMES_(U)>
|
f0_ = p.first;
|
||||||
tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
|
f1_ = p.second;
|
||||||
return CopyFrom(t);
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
$if k == 2 [[
|
]]
|
||||||
template <typename U0, typename U1>
|
|
||||||
tuple& operator=(const ::std::pair<U0, U1>& p) {
|
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
f0_ = p.first;
|
|
||||||
f1_ = p.second;
|
template <GTEST_$(k)_TYPENAMES_(U)>
|
||||||
return *this;
|
tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
|
||||||
}
|
|
||||||
|
$for m [[
|
||||||
]]
|
f$(m)_ = t.f$(m)_;
|
||||||
|
|
||||||
GTEST_DECLARE_TUPLE_AS_FRIEND_
|
]]
|
||||||
|
return *this;
|
||||||
template <GTEST_$(k)_TYPENAMES_(U)>
|
}
|
||||||
tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
|
|
||||||
|
|
||||||
$for m [[
|
$for m [[
|
||||||
f$(m)_ = t.f$(m)_;
|
T$m f$(m)_;
|
||||||
|
|
||||||
]]
|
]]
|
||||||
return *this;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
]]
|
||||||
$for m [[
|
// 6.1.3.2 Tuple creation functions.
|
||||||
T$m f$(m)_;
|
|
||||||
|
// Known limitations: we don't support passing an
|
||||||
]]
|
// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
|
||||||
};
|
// implement tie().
|
||||||
|
|
||||||
|
inline tuple<> make_tuple() { return tuple<>(); }
|
||||||
]]
|
|
||||||
// 6.1.3.2 Tuple creation functions.
|
$for k [[
|
||||||
|
$range m 0..k-1
|
||||||
// Known limitations: we don't support passing an
|
|
||||||
// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
|
template <GTEST_$(k)_TYPENAMES_(T)>
|
||||||
// implement tie().
|
inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
|
||||||
|
return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
|
||||||
inline tuple<> make_tuple() { return tuple<>(); }
|
}
|
||||||
|
|
||||||
$for k [[
|
]]
|
||||||
$range m 0..k-1
|
|
||||||
|
// 6.1.3.3 Tuple helper classes.
|
||||||
template <GTEST_$(k)_TYPENAMES_(T)>
|
|
||||||
inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
|
template <typename Tuple> struct tuple_size;
|
||||||
return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
|
|
||||||
}
|
|
||||||
|
$for j [[
|
||||||
]]
|
template <GTEST_$(j)_TYPENAMES_(T)>
|
||||||
|
struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
|
||||||
// 6.1.3.3 Tuple helper classes.
|
static const int value = $j;
|
||||||
|
};
|
||||||
template <typename Tuple> struct tuple_size;
|
|
||||||
|
|
||||||
|
]]
|
||||||
$for j [[
|
template <int k, class Tuple>
|
||||||
template <GTEST_$(j)_TYPENAMES_(T)>
|
struct tuple_element {
|
||||||
struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
|
typedef typename gtest_internal::TupleElement<
|
||||||
static const int value = $j;
|
k < (tuple_size<Tuple>::value), k, Tuple>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
|
||||||
]]
|
|
||||||
template <int k, class Tuple>
|
// 6.1.3.4 Element access.
|
||||||
struct tuple_element {
|
|
||||||
typedef typename gtest_internal::TupleElement<
|
namespace gtest_internal {
|
||||||
k < (tuple_size<Tuple>::value), k, Tuple>::type type;
|
|
||||||
};
|
|
||||||
|
$for i [[
|
||||||
#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
|
template <>
|
||||||
|
class Get<$i> {
|
||||||
// 6.1.3.4 Element access.
|
public:
|
||||||
|
template <class Tuple>
|
||||||
namespace gtest_internal {
|
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
|
||||||
|
Field(Tuple& t) { return t.f$(i)_; } // NOLINT
|
||||||
|
|
||||||
$for i [[
|
template <class Tuple>
|
||||||
template <>
|
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
|
||||||
class Get<$i> {
|
ConstField(const Tuple& t) { return t.f$(i)_; }
|
||||||
public:
|
};
|
||||||
template <class Tuple>
|
|
||||||
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
|
|
||||||
Field(Tuple& t) { return t.f$(i)_; } // NOLINT
|
]]
|
||||||
|
} // namespace gtest_internal
|
||||||
template <class Tuple>
|
|
||||||
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
|
template <int k, GTEST_$(n)_TYPENAMES_(T)>
|
||||||
ConstField(const Tuple& t) { return t.f$(i)_; }
|
GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
|
||||||
};
|
get(GTEST_$(n)_TUPLE_(T)& t) {
|
||||||
|
return gtest_internal::Get<k>::Field(t);
|
||||||
|
}
|
||||||
]]
|
|
||||||
} // namespace gtest_internal
|
template <int k, GTEST_$(n)_TYPENAMES_(T)>
|
||||||
|
GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
|
||||||
template <int k, GTEST_$(n)_TYPENAMES_(T)>
|
get(const GTEST_$(n)_TUPLE_(T)& t) {
|
||||||
GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
|
return gtest_internal::Get<k>::ConstField(t);
|
||||||
get(GTEST_$(n)_TUPLE_(T)& t) {
|
}
|
||||||
return gtest_internal::Get<k>::Field(t);
|
|
||||||
}
|
// 6.1.3.5 Relational operators
|
||||||
|
|
||||||
template <int k, GTEST_$(n)_TYPENAMES_(T)>
|
// We only implement == and !=, as we don't have a need for the rest yet.
|
||||||
GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
|
|
||||||
get(const GTEST_$(n)_TUPLE_(T)& t) {
|
namespace gtest_internal {
|
||||||
return gtest_internal::Get<k>::ConstField(t);
|
|
||||||
}
|
// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
|
||||||
|
// first k fields of t1 equals the first k fields of t2.
|
||||||
// 6.1.3.5 Relational operators
|
// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
|
||||||
|
// k1 != k2.
|
||||||
// We only implement == and !=, as we don't have a need for the rest yet.
|
template <int kSize1, int kSize2>
|
||||||
|
struct SameSizeTuplePrefixComparator;
|
||||||
namespace gtest_internal {
|
|
||||||
|
template <>
|
||||||
// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
|
struct SameSizeTuplePrefixComparator<0, 0> {
|
||||||
// first k fields of t1 equals the first k fields of t2.
|
template <class Tuple1, class Tuple2>
|
||||||
// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
|
static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
|
||||||
// k1 != k2.
|
return true;
|
||||||
template <int kSize1, int kSize2>
|
}
|
||||||
struct SameSizeTuplePrefixComparator;
|
};
|
||||||
|
|
||||||
template <>
|
template <int k>
|
||||||
struct SameSizeTuplePrefixComparator<0, 0> {
|
struct SameSizeTuplePrefixComparator<k, k> {
|
||||||
template <class Tuple1, class Tuple2>
|
template <class Tuple1, class Tuple2>
|
||||||
static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
|
static bool Eq(const Tuple1& t1, const Tuple2& t2) {
|
||||||
return true;
|
return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
|
||||||
}
|
::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
|
||||||
};
|
}
|
||||||
|
};
|
||||||
template <int k>
|
|
||||||
struct SameSizeTuplePrefixComparator<k, k> {
|
} // namespace gtest_internal
|
||||||
template <class Tuple1, class Tuple2>
|
|
||||||
static bool Eq(const Tuple1& t1, const Tuple2& t2) {
|
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
|
||||||
return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
|
inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
|
||||||
::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
|
const GTEST_$(n)_TUPLE_(U)& u) {
|
||||||
}
|
return gtest_internal::SameSizeTuplePrefixComparator<
|
||||||
};
|
tuple_size<GTEST_$(n)_TUPLE_(T) >::value,
|
||||||
|
tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u);
|
||||||
} // namespace gtest_internal
|
}
|
||||||
|
|
||||||
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
|
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
|
||||||
inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
|
inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
|
||||||
const GTEST_$(n)_TUPLE_(U)& u) {
|
const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
|
||||||
return gtest_internal::SameSizeTuplePrefixComparator<
|
|
||||||
tuple_size<GTEST_$(n)_TUPLE_(T) >::value,
|
// 6.1.4 Pairs.
|
||||||
tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u);
|
// Unimplemented.
|
||||||
}
|
|
||||||
|
} // namespace tr1
|
||||||
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
|
} // namespace std
|
||||||
inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
|
|
||||||
const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
|
|
||||||
|
$for j [[
|
||||||
// 6.1.4 Pairs.
|
#undef GTEST_$(j)_TUPLE_
|
||||||
// Unimplemented.
|
|
||||||
|
]]
|
||||||
} // namespace tr1
|
|
||||||
} // namespace std
|
|
||||||
|
$for j [[
|
||||||
|
#undef GTEST_$(j)_TYPENAMES_
|
||||||
$for j [[
|
|
||||||
#undef GTEST_$(j)_TUPLE_
|
]]
|
||||||
|
|
||||||
]]
|
#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
|
||||||
|
#undef GTEST_BY_REF_
|
||||||
|
#undef GTEST_ADD_REF_
|
||||||
$for j [[
|
#undef GTEST_TUPLE_ELEMENT_
|
||||||
#undef GTEST_$(j)_TYPENAMES_
|
|
||||||
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
||||||
]]
|
|
||||||
|
|
||||||
#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
|
|
||||||
#undef GTEST_BY_REF_
|
|
||||||
#undef GTEST_ADD_REF_
|
|
||||||
#undef GTEST_TUPLE_ELEMENT_
|
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,297 +1,297 @@
|
|||||||
$$ -*- mode: c++; -*-
|
$$ -*- mode: c++; -*-
|
||||||
$var n = 50 $$ Maximum length of type lists we want to support.
|
$var n = 50 $$ Maximum length of type lists we want to support.
|
||||||
// Copyright 2008 Google Inc.
|
// Copyright 2008 Google Inc.
|
||||||
// All Rights Reserved.
|
// All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
// Type utilities needed for implementing typed and type-parameterized
|
// Type utilities needed for implementing typed and type-parameterized
|
||||||
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||||
//
|
//
|
||||||
// Currently we support at most $n types in a list, and at most $n
|
// Currently we support at most $n types in a list, and at most $n
|
||||||
// type-parameterized tests in one type-parameterized test case.
|
// type-parameterized tests in one type-parameterized test case.
|
||||||
// Please contact googletestframework@googlegroups.com if you need
|
// Please contact googletestframework@googlegroups.com if you need
|
||||||
// more.
|
// more.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||||
// libstdc++ (which is where cxxabi.h comes from).
|
// libstdc++ (which is where cxxabi.h comes from).
|
||||||
# if GTEST_HAS_CXXABI_H_
|
# if GTEST_HAS_CXXABI_H_
|
||||||
# include <cxxabi.h>
|
# include <cxxabi.h>
|
||||||
# elif defined(__HP_aCC)
|
# elif defined(__HP_aCC)
|
||||||
# include <acxx_demangle.h>
|
# include <acxx_demangle.h>
|
||||||
# endif // GTEST_HASH_CXXABI_H_
|
# endif // GTEST_HASH_CXXABI_H_
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// GetTypeName<T>() returns a human-readable name of type T.
|
// GetTypeName<T>() returns a human-readable name of type T.
|
||||||
// NB: This function is also used in Google Mock, so don't move it inside of
|
// NB: This function is also used in Google Mock, so don't move it inside of
|
||||||
// the typed-test-only section below.
|
// the typed-test-only section below.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string GetTypeName() {
|
std::string GetTypeName() {
|
||||||
# if GTEST_HAS_RTTI
|
# if GTEST_HAS_RTTI
|
||||||
|
|
||||||
const char* const name = typeid(T).name();
|
const char* const name = typeid(T).name();
|
||||||
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
|
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
|
||||||
int status = 0;
|
int status = 0;
|
||||||
// gcc's implementation of typeid(T).name() mangles the type name,
|
// gcc's implementation of typeid(T).name() mangles the type name,
|
||||||
// so we have to demangle it.
|
// so we have to demangle it.
|
||||||
# if GTEST_HAS_CXXABI_H_
|
# if GTEST_HAS_CXXABI_H_
|
||||||
using abi::__cxa_demangle;
|
using abi::__cxa_demangle;
|
||||||
# endif // GTEST_HAS_CXXABI_H_
|
# endif // GTEST_HAS_CXXABI_H_
|
||||||
char* const readable_name = __cxa_demangle(name, 0, 0, &status);
|
char* const readable_name = __cxa_demangle(name, 0, 0, &status);
|
||||||
const std::string name_str(status == 0 ? readable_name : name);
|
const std::string name_str(status == 0 ? readable_name : name);
|
||||||
free(readable_name);
|
free(readable_name);
|
||||||
return name_str;
|
return name_str;
|
||||||
# else
|
# else
|
||||||
return name;
|
return name;
|
||||||
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
|
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
|
||||||
|
|
||||||
# else
|
# else
|
||||||
|
|
||||||
return "<type>";
|
return "<type>";
|
||||||
|
|
||||||
# endif // GTEST_HAS_RTTI
|
# endif // GTEST_HAS_RTTI
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
|
// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
|
||||||
// type. This can be used as a compile-time assertion to ensure that
|
// type. This can be used as a compile-time assertion to ensure that
|
||||||
// two types are equal.
|
// two types are equal.
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
struct AssertTypeEq;
|
struct AssertTypeEq;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct AssertTypeEq<T, T> {
|
struct AssertTypeEq<T, T> {
|
||||||
typedef bool type;
|
typedef bool type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A unique type used as the default value for the arguments of class
|
// A unique type used as the default value for the arguments of class
|
||||||
// template Types. This allows us to simulate variadic templates
|
// template Types. This allows us to simulate variadic templates
|
||||||
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
||||||
// support directly.
|
// support directly.
|
||||||
struct None {};
|
struct None {};
|
||||||
|
|
||||||
// The following family of struct and struct templates are used to
|
// The following family of struct and struct templates are used to
|
||||||
// represent type lists. In particular, TypesN<T1, T2, ..., TN>
|
// represent type lists. In particular, TypesN<T1, T2, ..., TN>
|
||||||
// represents a type list with N types (T1, T2, ..., and TN) in it.
|
// represents a type list with N types (T1, T2, ..., and TN) in it.
|
||||||
// Except for Types0, every struct in the family has two member types:
|
// Except for Types0, every struct in the family has two member types:
|
||||||
// Head for the first type in the list, and Tail for the rest of the
|
// Head for the first type in the list, and Tail for the rest of the
|
||||||
// list.
|
// list.
|
||||||
|
|
||||||
// The empty type list.
|
// The empty type list.
|
||||||
struct Types0 {};
|
struct Types0 {};
|
||||||
|
|
||||||
// Type lists of length 1, 2, 3, and so on.
|
// Type lists of length 1, 2, 3, and so on.
|
||||||
|
|
||||||
template <typename T1>
|
template <typename T1>
|
||||||
struct Types1 {
|
struct Types1 {
|
||||||
typedef T1 Head;
|
typedef T1 Head;
|
||||||
typedef Types0 Tail;
|
typedef Types0 Tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
$range i 2..n
|
$range i 2..n
|
||||||
|
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
$range k 2..i
|
$range k 2..i
|
||||||
template <$for j, [[typename T$j]]>
|
template <$for j, [[typename T$j]]>
|
||||||
struct Types$i {
|
struct Types$i {
|
||||||
typedef T1 Head;
|
typedef T1 Head;
|
||||||
typedef Types$(i-1)<$for k, [[T$k]]> Tail;
|
typedef Types$(i-1)<$for k, [[T$k]]> Tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// We don't want to require the users to write TypesN<...> directly,
|
// We don't want to require the users to write TypesN<...> directly,
|
||||||
// as that would require them to count the length. Types<...> is much
|
// as that would require them to count the length. Types<...> is much
|
||||||
// easier to write, but generates horrible messages when there is a
|
// easier to write, but generates horrible messages when there is a
|
||||||
// compiler error, as gcc insists on printing out each template
|
// compiler error, as gcc insists on printing out each template
|
||||||
// argument, even if it has the default value (this means Types<int>
|
// argument, even if it has the default value (this means Types<int>
|
||||||
// will appear as Types<int, None, None, ..., None> in the compiler
|
// will appear as Types<int, None, None, ..., None> in the compiler
|
||||||
// errors).
|
// errors).
|
||||||
//
|
//
|
||||||
// Our solution is to combine the best part of the two approaches: a
|
// Our solution is to combine the best part of the two approaches: a
|
||||||
// user would write Types<T1, ..., TN>, and Google Test will translate
|
// user would write Types<T1, ..., TN>, and Google Test will translate
|
||||||
// that to TypesN<T1, ..., TN> internally to make error messages
|
// that to TypesN<T1, ..., TN> internally to make error messages
|
||||||
// readable. The translation is done by the 'type' member of the
|
// readable. The translation is done by the 'type' member of the
|
||||||
// Types template.
|
// Types template.
|
||||||
|
|
||||||
$range i 1..n
|
$range i 1..n
|
||||||
template <$for i, [[typename T$i = internal::None]]>
|
template <$for i, [[typename T$i = internal::None]]>
|
||||||
struct Types {
|
struct Types {
|
||||||
typedef internal::Types$n<$for i, [[T$i]]> type;
|
typedef internal::Types$n<$for i, [[T$i]]> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Types<$for i, [[internal::None]]> {
|
struct Types<$for i, [[internal::None]]> {
|
||||||
typedef internal::Types0 type;
|
typedef internal::Types0 type;
|
||||||
};
|
};
|
||||||
|
|
||||||
$range i 1..n-1
|
$range i 1..n-1
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
$range k i+1..n
|
$range k i+1..n
|
||||||
template <$for j, [[typename T$j]]>
|
template <$for j, [[typename T$j]]>
|
||||||
struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
|
struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
|
||||||
typedef internal::Types$i<$for j, [[T$j]]> type;
|
typedef internal::Types$i<$for j, [[T$j]]> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
# define GTEST_TEMPLATE_ template <typename T> class
|
# define GTEST_TEMPLATE_ template <typename T> class
|
||||||
|
|
||||||
// The template "selector" struct TemplateSel<Tmpl> is used to
|
// The template "selector" struct TemplateSel<Tmpl> is used to
|
||||||
// represent Tmpl, which must be a class template with one type
|
// represent Tmpl, which must be a class template with one type
|
||||||
// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
|
// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
|
||||||
// as the type Tmpl<T>. This allows us to actually instantiate the
|
// as the type Tmpl<T>. This allows us to actually instantiate the
|
||||||
// template "selected" by TemplateSel<Tmpl>.
|
// template "selected" by TemplateSel<Tmpl>.
|
||||||
//
|
//
|
||||||
// This trick is necessary for simulating typedef for class templates,
|
// This trick is necessary for simulating typedef for class templates,
|
||||||
// which C++ doesn't support directly.
|
// which C++ doesn't support directly.
|
||||||
template <GTEST_TEMPLATE_ Tmpl>
|
template <GTEST_TEMPLATE_ Tmpl>
|
||||||
struct TemplateSel {
|
struct TemplateSel {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Bind {
|
struct Bind {
|
||||||
typedef Tmpl<T> type;
|
typedef Tmpl<T> type;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# define GTEST_BIND_(TmplSel, T) \
|
# define GTEST_BIND_(TmplSel, T) \
|
||||||
TmplSel::template Bind<T>::type
|
TmplSel::template Bind<T>::type
|
||||||
|
|
||||||
// A unique struct template used as the default value for the
|
// A unique struct template used as the default value for the
|
||||||
// arguments of class template Templates. This allows us to simulate
|
// arguments of class template Templates. This allows us to simulate
|
||||||
// variadic templates (e.g. Templates<int>, Templates<int, double>,
|
// variadic templates (e.g. Templates<int>, Templates<int, double>,
|
||||||
// and etc), which C++ doesn't support directly.
|
// and etc), which C++ doesn't support directly.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct NoneT {};
|
struct NoneT {};
|
||||||
|
|
||||||
// The following family of struct and struct templates are used to
|
// The following family of struct and struct templates are used to
|
||||||
// represent template lists. In particular, TemplatesN<T1, T2, ...,
|
// represent template lists. In particular, TemplatesN<T1, T2, ...,
|
||||||
// TN> represents a list of N templates (T1, T2, ..., and TN). Except
|
// TN> represents a list of N templates (T1, T2, ..., and TN). Except
|
||||||
// for Templates0, every struct in the family has two member types:
|
// for Templates0, every struct in the family has two member types:
|
||||||
// Head for the selector of the first template in the list, and Tail
|
// Head for the selector of the first template in the list, and Tail
|
||||||
// for the rest of the list.
|
// for the rest of the list.
|
||||||
|
|
||||||
// The empty template list.
|
// The empty template list.
|
||||||
struct Templates0 {};
|
struct Templates0 {};
|
||||||
|
|
||||||
// Template lists of length 1, 2, 3, and so on.
|
// Template lists of length 1, 2, 3, and so on.
|
||||||
|
|
||||||
template <GTEST_TEMPLATE_ T1>
|
template <GTEST_TEMPLATE_ T1>
|
||||||
struct Templates1 {
|
struct Templates1 {
|
||||||
typedef TemplateSel<T1> Head;
|
typedef TemplateSel<T1> Head;
|
||||||
typedef Templates0 Tail;
|
typedef Templates0 Tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
$range i 2..n
|
$range i 2..n
|
||||||
|
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
$range k 2..i
|
$range k 2..i
|
||||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||||
struct Templates$i {
|
struct Templates$i {
|
||||||
typedef TemplateSel<T1> Head;
|
typedef TemplateSel<T1> Head;
|
||||||
typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
|
typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
// We don't want to require the users to write TemplatesN<...> directly,
|
// We don't want to require the users to write TemplatesN<...> directly,
|
||||||
// as that would require them to count the length. Templates<...> is much
|
// as that would require them to count the length. Templates<...> is much
|
||||||
// easier to write, but generates horrible messages when there is a
|
// easier to write, but generates horrible messages when there is a
|
||||||
// compiler error, as gcc insists on printing out each template
|
// compiler error, as gcc insists on printing out each template
|
||||||
// argument, even if it has the default value (this means Templates<list>
|
// argument, even if it has the default value (this means Templates<list>
|
||||||
// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
|
// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
|
||||||
// errors).
|
// errors).
|
||||||
//
|
//
|
||||||
// Our solution is to combine the best part of the two approaches: a
|
// Our solution is to combine the best part of the two approaches: a
|
||||||
// user would write Templates<T1, ..., TN>, and Google Test will translate
|
// user would write Templates<T1, ..., TN>, and Google Test will translate
|
||||||
// that to TemplatesN<T1, ..., TN> internally to make error messages
|
// that to TemplatesN<T1, ..., TN> internally to make error messages
|
||||||
// readable. The translation is done by the 'type' member of the
|
// readable. The translation is done by the 'type' member of the
|
||||||
// Templates template.
|
// Templates template.
|
||||||
|
|
||||||
$range i 1..n
|
$range i 1..n
|
||||||
template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
|
template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
|
||||||
struct Templates {
|
struct Templates {
|
||||||
typedef Templates$n<$for i, [[T$i]]> type;
|
typedef Templates$n<$for i, [[T$i]]> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Templates<$for i, [[NoneT]]> {
|
struct Templates<$for i, [[NoneT]]> {
|
||||||
typedef Templates0 type;
|
typedef Templates0 type;
|
||||||
};
|
};
|
||||||
|
|
||||||
$range i 1..n-1
|
$range i 1..n-1
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
$range k i+1..n
|
$range k i+1..n
|
||||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||||
struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
|
struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
|
||||||
typedef Templates$i<$for j, [[T$j]]> type;
|
typedef Templates$i<$for j, [[T$j]]> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
// The TypeList template makes it possible to use either a single type
|
// The TypeList template makes it possible to use either a single type
|
||||||
// or a Types<...> list in TYPED_TEST_CASE() and
|
// or a Types<...> list in TYPED_TEST_CASE() and
|
||||||
// INSTANTIATE_TYPED_TEST_CASE_P().
|
// INSTANTIATE_TYPED_TEST_CASE_P().
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TypeList {
|
struct TypeList {
|
||||||
typedef Types1<T> type;
|
typedef Types1<T> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
$range i 1..n
|
$range i 1..n
|
||||||
template <$for i, [[typename T$i]]>
|
template <$for i, [[typename T$i]]>
|
||||||
struct TypeList<Types<$for i, [[T$i]]> > {
|
struct TypeList<Types<$for i, [[T$i]]> > {
|
||||||
typedef typename Types<$for i, [[T$i]]>::type type;
|
typedef typename Types<$for i, [[T$i]]>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||||
@@ -1,48 +1,48 @@
|
|||||||
// Copyright 2008, Google Inc.
|
// Copyright 2008, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: mheule@google.com (Markus Heule)
|
// Author: mheule@google.com (Markus Heule)
|
||||||
//
|
//
|
||||||
// Google C++ Testing Framework (Google Test)
|
// Google C++ Testing Framework (Google Test)
|
||||||
//
|
//
|
||||||
// Sometimes it's desirable to build Google Test by compiling a single file.
|
// Sometimes it's desirable to build Google Test by compiling a single file.
|
||||||
// This file serves this purpose.
|
// This file serves this purpose.
|
||||||
|
|
||||||
// This line ensures that gtest.h can be compiled on its own, even
|
// This line ensures that gtest.h can be compiled on its own, even
|
||||||
// when it's fused.
|
// when it's fused.
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
// The following lines pull in the real gtest *.cc files.
|
// The following lines pull in the real gtest *.cc files.
|
||||||
#include "src/gtest.cc"
|
#include "src/gtest.cc"
|
||||||
#include "src/gtest-death-test.cc"
|
#include "src/gtest-death-test.cc"
|
||||||
#include "src/gtest-filepath.cc"
|
#include "src/gtest-filepath.cc"
|
||||||
#include "src/gtest-port.cc"
|
#include "src/gtest-port.cc"
|
||||||
#include "src/gtest-printers.cc"
|
#include "src/gtest-printers.cc"
|
||||||
#include "src/gtest-test-part.cc"
|
#include "src/gtest-test-part.cc"
|
||||||
#include "src/gtest-typed-test.cc"
|
#include "src/gtest-typed-test.cc"
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,380 +1,382 @@
|
|||||||
// Copyright 2008, Google Inc.
|
// Copyright 2008, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Authors: keith.ray@gmail.com (Keith Ray)
|
// Authors: keith.ray@gmail.com (Keith Ray)
|
||||||
|
|
||||||
#include "gtest/gtest-message.h"
|
#include "gtest/gtest-message.h"
|
||||||
#include "gtest/internal/gtest-filepath.h"
|
#include "gtest/internal/gtest-filepath.h"
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#elif GTEST_OS_WINDOWS
|
#elif GTEST_OS_WINDOWS
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
#elif GTEST_OS_SYMBIAN
|
#elif GTEST_OS_SYMBIAN
|
||||||
// Symbian OpenC has PATH_MAX in sys/syslimits.h
|
// Symbian OpenC has PATH_MAX in sys/syslimits.h
|
||||||
# include <sys/syslimits.h>
|
# include <sys/syslimits.h>
|
||||||
#else
|
#else
|
||||||
# include <limits.h>
|
# include <limits.h>
|
||||||
# include <climits> // Some Linux distributions define PATH_MAX here.
|
# include <climits> // Some Linux distributions define PATH_MAX here.
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
# define GTEST_PATH_MAX_ _MAX_PATH
|
# define GTEST_PATH_MAX_ _MAX_PATH
|
||||||
#elif defined(PATH_MAX)
|
#elif defined(PATH_MAX)
|
||||||
# define GTEST_PATH_MAX_ PATH_MAX
|
# define GTEST_PATH_MAX_ PATH_MAX
|
||||||
#elif defined(_XOPEN_PATH_MAX)
|
#elif defined(_XOPEN_PATH_MAX)
|
||||||
# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
|
||||||
#else
|
#else
|
||||||
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
#include "gtest/internal/gtest-string.h"
|
#include "gtest/internal/gtest-string.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS
|
||||||
// On Windows, '\\' is the standard path separator, but many tools and the
|
// On Windows, '\\' is the standard path separator, but many tools and the
|
||||||
// Windows API also accept '/' as an alternate path separator. Unless otherwise
|
// Windows API also accept '/' as an alternate path separator. Unless otherwise
|
||||||
// noted, a file path can contain either kind of path separators, or a mixture
|
// noted, a file path can contain either kind of path separators, or a mixture
|
||||||
// of them.
|
// of them.
|
||||||
const char kPathSeparator = '\\';
|
const char kPathSeparator = '\\';
|
||||||
const char kAlternatePathSeparator = '/';
|
const char kAlternatePathSeparator = '/';
|
||||||
const char kAlternatePathSeparatorString[] = "/";
|
const char kPathSeparatorString[] = "\\";
|
||||||
# if GTEST_OS_WINDOWS_MOBILE
|
const char kAlternatePathSeparatorString[] = "/";
|
||||||
// Windows CE doesn't have a current directory. You should not use
|
# if GTEST_OS_WINDOWS_MOBILE
|
||||||
// the current directory in tests on Windows CE, but this at least
|
// Windows CE doesn't have a current directory. You should not use
|
||||||
// provides a reasonable fallback.
|
// the current directory in tests on Windows CE, but this at least
|
||||||
const char kCurrentDirectoryString[] = "\\";
|
// provides a reasonable fallback.
|
||||||
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
|
const char kCurrentDirectoryString[] = "\\";
|
||||||
const DWORD kInvalidFileAttributes = 0xffffffff;
|
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
|
||||||
# else
|
const DWORD kInvalidFileAttributes = 0xffffffff;
|
||||||
const char kCurrentDirectoryString[] = ".\\";
|
# else
|
||||||
# endif // GTEST_OS_WINDOWS_MOBILE
|
const char kCurrentDirectoryString[] = ".\\";
|
||||||
#else
|
# endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
const char kPathSeparator = '/';
|
#else
|
||||||
const char kCurrentDirectoryString[] = "./";
|
const char kPathSeparator = '/';
|
||||||
#endif // GTEST_OS_WINDOWS
|
const char kPathSeparatorString[] = "/";
|
||||||
|
const char kCurrentDirectoryString[] = "./";
|
||||||
// Returns whether the given character is a valid path separator.
|
#endif // GTEST_OS_WINDOWS
|
||||||
static bool IsPathSeparator(char c) {
|
|
||||||
#if GTEST_HAS_ALT_PATH_SEP_
|
// Returns whether the given character is a valid path separator.
|
||||||
return (c == kPathSeparator) || (c == kAlternatePathSeparator);
|
static bool IsPathSeparator(char c) {
|
||||||
#else
|
#if GTEST_HAS_ALT_PATH_SEP_
|
||||||
return c == kPathSeparator;
|
return (c == kPathSeparator) || (c == kAlternatePathSeparator);
|
||||||
#endif
|
#else
|
||||||
}
|
return c == kPathSeparator;
|
||||||
|
#endif
|
||||||
// Returns the current working directory, or "" if unsuccessful.
|
}
|
||||||
FilePath FilePath::GetCurrentDir() {
|
|
||||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
|
// Returns the current working directory, or "" if unsuccessful.
|
||||||
// Windows CE doesn't have a current directory, so we just return
|
FilePath FilePath::GetCurrentDir() {
|
||||||
// something reasonable.
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
return FilePath(kCurrentDirectoryString);
|
// Windows CE doesn't have a current directory, so we just return
|
||||||
#elif GTEST_OS_WINDOWS
|
// something reasonable.
|
||||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
return FilePath(kCurrentDirectoryString);
|
||||||
return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
|
#elif GTEST_OS_WINDOWS
|
||||||
#else
|
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||||
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
|
||||||
return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
|
#else
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
|
||||||
}
|
return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
// Returns a copy of the FilePath with the case-insensitive extension removed.
|
}
|
||||||
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
|
|
||||||
// FilePath("dir/file"). If a case-insensitive extension is not
|
// Returns a copy of the FilePath with the case-insensitive extension removed.
|
||||||
// found, returns a copy of the original FilePath.
|
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
|
||||||
FilePath FilePath::RemoveExtension(const char* extension) const {
|
// FilePath("dir/file"). If a case-insensitive extension is not
|
||||||
const std::string dot_extension = std::string(".") + extension;
|
// found, returns a copy of the original FilePath.
|
||||||
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
|
FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||||
return FilePath(pathname_.substr(
|
const std::string dot_extension = std::string(".") + extension;
|
||||||
0, pathname_.length() - dot_extension.length()));
|
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
|
||||||
}
|
return FilePath(pathname_.substr(
|
||||||
return *this;
|
0, pathname_.length() - dot_extension.length()));
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
// Returns a pointer to the last occurence of a valid path separator in
|
}
|
||||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
|
||||||
// separators. Returns NULL if no path separator was found.
|
// Returns a pointer to the last occurence of a valid path separator in
|
||||||
const char* FilePath::FindLastPathSeparator() const {
|
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
// separators. Returns NULL if no path separator was found.
|
||||||
#if GTEST_HAS_ALT_PATH_SEP_
|
const char* FilePath::FindLastPathSeparator() const {
|
||||||
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||||
// Comparing two pointers of which only one is NULL is undefined.
|
#if GTEST_HAS_ALT_PATH_SEP_
|
||||||
if (last_alt_sep != NULL &&
|
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
||||||
(last_sep == NULL || last_alt_sep > last_sep)) {
|
// Comparing two pointers of which only one is NULL is undefined.
|
||||||
return last_alt_sep;
|
if (last_alt_sep != NULL &&
|
||||||
}
|
(last_sep == NULL || last_alt_sep > last_sep)) {
|
||||||
#endif
|
return last_alt_sep;
|
||||||
return last_sep;
|
}
|
||||||
}
|
#endif
|
||||||
|
return last_sep;
|
||||||
// Returns a copy of the FilePath with the directory part removed.
|
}
|
||||||
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
|
||||||
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
// Returns a copy of the FilePath with the directory part removed.
|
||||||
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
|
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
||||||
// returns an empty FilePath ("").
|
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
||||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
|
||||||
FilePath FilePath::RemoveDirectoryName() const {
|
// returns an empty FilePath ("").
|
||||||
const char* const last_sep = FindLastPathSeparator();
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
return last_sep ? FilePath(last_sep + 1) : *this;
|
FilePath FilePath::RemoveDirectoryName() const {
|
||||||
}
|
const char* const last_sep = FindLastPathSeparator();
|
||||||
|
return last_sep ? FilePath(last_sep + 1) : *this;
|
||||||
// RemoveFileName returns the directory path with the filename removed.
|
}
|
||||||
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
|
|
||||||
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
|
// RemoveFileName returns the directory path with the filename removed.
|
||||||
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
|
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
|
||||||
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
|
||||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
|
||||||
FilePath FilePath::RemoveFileName() const {
|
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
||||||
const char* const last_sep = FindLastPathSeparator();
|
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||||
std::string dir;
|
FilePath FilePath::RemoveFileName() const {
|
||||||
if (last_sep) {
|
const char* const last_sep = FindLastPathSeparator();
|
||||||
dir = std::string(c_str(), last_sep + 1 - c_str());
|
std::string dir;
|
||||||
} else {
|
if (last_sep) {
|
||||||
dir = kCurrentDirectoryString;
|
dir = std::string(c_str(), last_sep + 1 - c_str());
|
||||||
}
|
} else {
|
||||||
return FilePath(dir);
|
dir = kCurrentDirectoryString;
|
||||||
}
|
}
|
||||||
|
return FilePath(dir);
|
||||||
// Helper functions for naming files in a directory for xml output.
|
}
|
||||||
|
|
||||||
// Given directory = "dir", base_name = "test", number = 0,
|
// Helper functions for naming files in a directory for xml output.
|
||||||
// extension = "xml", returns "dir/test.xml". If number is greater
|
|
||||||
// than zero (e.g., 12), returns "dir/test_12.xml".
|
// Given directory = "dir", base_name = "test", number = 0,
|
||||||
// On Windows platform, uses \ as the separator rather than /.
|
// extension = "xml", returns "dir/test.xml". If number is greater
|
||||||
FilePath FilePath::MakeFileName(const FilePath& directory,
|
// than zero (e.g., 12), returns "dir/test_12.xml".
|
||||||
const FilePath& base_name,
|
// On Windows platform, uses \ as the separator rather than /.
|
||||||
int number,
|
FilePath FilePath::MakeFileName(const FilePath& directory,
|
||||||
const char* extension) {
|
const FilePath& base_name,
|
||||||
std::string file;
|
int number,
|
||||||
if (number == 0) {
|
const char* extension) {
|
||||||
file = base_name.string() + "." + extension;
|
std::string file;
|
||||||
} else {
|
if (number == 0) {
|
||||||
file = base_name.string() + "_" + StreamableToString(number)
|
file = base_name.string() + "." + extension;
|
||||||
+ "." + extension;
|
} else {
|
||||||
}
|
file = base_name.string() + "_" + StreamableToString(number)
|
||||||
return ConcatPaths(directory, FilePath(file));
|
+ "." + extension;
|
||||||
}
|
}
|
||||||
|
return ConcatPaths(directory, FilePath(file));
|
||||||
// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
|
}
|
||||||
// On Windows, uses \ as the separator rather than /.
|
|
||||||
FilePath FilePath::ConcatPaths(const FilePath& directory,
|
// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
|
||||||
const FilePath& relative_path) {
|
// On Windows, uses \ as the separator rather than /.
|
||||||
if (directory.IsEmpty())
|
FilePath FilePath::ConcatPaths(const FilePath& directory,
|
||||||
return relative_path;
|
const FilePath& relative_path) {
|
||||||
const FilePath dir(directory.RemoveTrailingPathSeparator());
|
if (directory.IsEmpty())
|
||||||
return FilePath(dir.string() + kPathSeparator + relative_path.string());
|
return relative_path;
|
||||||
}
|
const FilePath dir(directory.RemoveTrailingPathSeparator());
|
||||||
|
return FilePath(dir.string() + kPathSeparator + relative_path.string());
|
||||||
// Returns true if pathname describes something findable in the file-system,
|
}
|
||||||
// either a file, directory, or whatever.
|
|
||||||
bool FilePath::FileOrDirectoryExists() const {
|
// Returns true if pathname describes something findable in the file-system,
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
// either a file, directory, or whatever.
|
||||||
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
|
bool FilePath::FileOrDirectoryExists() const {
|
||||||
const DWORD attributes = GetFileAttributes(unicode);
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
delete [] unicode;
|
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
|
||||||
return attributes != kInvalidFileAttributes;
|
const DWORD attributes = GetFileAttributes(unicode);
|
||||||
#else
|
delete [] unicode;
|
||||||
posix::StatStruct file_stat;
|
return attributes != kInvalidFileAttributes;
|
||||||
return posix::Stat(pathname_.c_str(), &file_stat) == 0;
|
#else
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
posix::StatStruct file_stat;
|
||||||
}
|
return posix::Stat(pathname_.c_str(), &file_stat) == 0;
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
// Returns true if pathname describes a directory in the file-system
|
}
|
||||||
// that exists.
|
|
||||||
bool FilePath::DirectoryExists() const {
|
// Returns true if pathname describes a directory in the file-system
|
||||||
bool result = false;
|
// that exists.
|
||||||
#if GTEST_OS_WINDOWS
|
bool FilePath::DirectoryExists() const {
|
||||||
// Don't strip off trailing separator if path is a root directory on
|
bool result = false;
|
||||||
// Windows (like "C:\\").
|
#if GTEST_OS_WINDOWS
|
||||||
const FilePath& path(IsRootDirectory() ? *this :
|
// Don't strip off trailing separator if path is a root directory on
|
||||||
RemoveTrailingPathSeparator());
|
// Windows (like "C:\\").
|
||||||
#else
|
const FilePath& path(IsRootDirectory() ? *this :
|
||||||
const FilePath& path(*this);
|
RemoveTrailingPathSeparator());
|
||||||
#endif
|
#else
|
||||||
|
const FilePath& path(*this);
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#endif
|
||||||
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
|
|
||||||
const DWORD attributes = GetFileAttributes(unicode);
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
delete [] unicode;
|
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
|
||||||
if ((attributes != kInvalidFileAttributes) &&
|
const DWORD attributes = GetFileAttributes(unicode);
|
||||||
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
delete [] unicode;
|
||||||
result = true;
|
if ((attributes != kInvalidFileAttributes) &&
|
||||||
}
|
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
#else
|
result = true;
|
||||||
posix::StatStruct file_stat;
|
}
|
||||||
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
|
#else
|
||||||
posix::IsDir(file_stat);
|
posix::StatStruct file_stat;
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
|
||||||
|
posix::IsDir(file_stat);
|
||||||
return result;
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
}
|
|
||||||
|
return result;
|
||||||
// Returns true if pathname describes a root directory. (Windows has one
|
}
|
||||||
// root directory per disk drive.)
|
|
||||||
bool FilePath::IsRootDirectory() const {
|
// Returns true if pathname describes a root directory. (Windows has one
|
||||||
#if GTEST_OS_WINDOWS
|
// root directory per disk drive.)
|
||||||
// TODO(wan@google.com): on Windows a network share like
|
bool FilePath::IsRootDirectory() const {
|
||||||
// \\server\share can be a root directory, although it cannot be the
|
#if GTEST_OS_WINDOWS
|
||||||
// current directory. Handle this properly.
|
// TODO(wan@google.com): on Windows a network share like
|
||||||
return pathname_.length() == 3 && IsAbsolutePath();
|
// \\server\share can be a root directory, although it cannot be the
|
||||||
#else
|
// current directory. Handle this properly.
|
||||||
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
return pathname_.length() == 3 && IsAbsolutePath();
|
||||||
#endif
|
#else
|
||||||
}
|
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
||||||
|
#endif
|
||||||
// Returns true if pathname describes an absolute path.
|
}
|
||||||
bool FilePath::IsAbsolutePath() const {
|
|
||||||
const char* const name = pathname_.c_str();
|
// Returns true if pathname describes an absolute path.
|
||||||
#if GTEST_OS_WINDOWS
|
bool FilePath::IsAbsolutePath() const {
|
||||||
return pathname_.length() >= 3 &&
|
const char* const name = pathname_.c_str();
|
||||||
((name[0] >= 'a' && name[0] <= 'z') ||
|
#if GTEST_OS_WINDOWS
|
||||||
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
return pathname_.length() >= 3 &&
|
||||||
name[1] == ':' &&
|
((name[0] >= 'a' && name[0] <= 'z') ||
|
||||||
IsPathSeparator(name[2]);
|
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||||
#else
|
name[1] == ':' &&
|
||||||
return IsPathSeparator(name[0]);
|
IsPathSeparator(name[2]);
|
||||||
#endif
|
#else
|
||||||
}
|
return IsPathSeparator(name[0]);
|
||||||
|
#endif
|
||||||
// Returns a pathname for a file that does not currently exist. The pathname
|
}
|
||||||
// will be directory/base_name.extension or
|
|
||||||
// directory/base_name_<number>.extension if directory/base_name.extension
|
// Returns a pathname for a file that does not currently exist. The pathname
|
||||||
// already exists. The number will be incremented until a pathname is found
|
// will be directory/base_name.extension or
|
||||||
// that does not already exist.
|
// directory/base_name_<number>.extension if directory/base_name.extension
|
||||||
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
|
// already exists. The number will be incremented until a pathname is found
|
||||||
// There could be a race condition if two or more processes are calling this
|
// that does not already exist.
|
||||||
// function at the same time -- they could both pick the same filename.
|
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
|
||||||
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
// There could be a race condition if two or more processes are calling this
|
||||||
const FilePath& base_name,
|
// function at the same time -- they could both pick the same filename.
|
||||||
const char* extension) {
|
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
||||||
FilePath full_pathname;
|
const FilePath& base_name,
|
||||||
int number = 0;
|
const char* extension) {
|
||||||
do {
|
FilePath full_pathname;
|
||||||
full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
|
int number = 0;
|
||||||
} while (full_pathname.FileOrDirectoryExists());
|
do {
|
||||||
return full_pathname;
|
full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
|
||||||
}
|
} while (full_pathname.FileOrDirectoryExists());
|
||||||
|
return full_pathname;
|
||||||
// Returns true if FilePath ends with a path separator, which indicates that
|
}
|
||||||
// it is intended to represent a directory. Returns false otherwise.
|
|
||||||
// This does NOT check that a directory (or file) actually exists.
|
// Returns true if FilePath ends with a path separator, which indicates that
|
||||||
bool FilePath::IsDirectory() const {
|
// it is intended to represent a directory. Returns false otherwise.
|
||||||
return !pathname_.empty() &&
|
// This does NOT check that a directory (or file) actually exists.
|
||||||
IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
|
bool FilePath::IsDirectory() const {
|
||||||
}
|
return !pathname_.empty() &&
|
||||||
|
IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
|
||||||
// Create directories so that path exists. Returns true if successful or if
|
}
|
||||||
// the directories already exist; returns false if unable to create directories
|
|
||||||
// for any reason.
|
// Create directories so that path exists. Returns true if successful or if
|
||||||
bool FilePath::CreateDirectoriesRecursively() const {
|
// the directories already exist; returns false if unable to create directories
|
||||||
if (!this->IsDirectory()) {
|
// for any reason.
|
||||||
return false;
|
bool FilePath::CreateDirectoriesRecursively() const {
|
||||||
}
|
if (!this->IsDirectory()) {
|
||||||
|
return false;
|
||||||
if (pathname_.length() == 0 || this->DirectoryExists()) {
|
}
|
||||||
return true;
|
|
||||||
}
|
if (pathname_.length() == 0 || this->DirectoryExists()) {
|
||||||
|
return true;
|
||||||
const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
|
}
|
||||||
return parent.CreateDirectoriesRecursively() && this->CreateFolder();
|
|
||||||
}
|
const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
|
||||||
|
return parent.CreateDirectoriesRecursively() && this->CreateFolder();
|
||||||
// Create the directory so that path exists. Returns true if successful or
|
}
|
||||||
// if the directory already exists; returns false if unable to create the
|
|
||||||
// directory for any reason, including if the parent directory does not
|
// Create the directory so that path exists. Returns true if successful or
|
||||||
// exist. Not named "CreateDirectory" because that's a macro on Windows.
|
// if the directory already exists; returns false if unable to create the
|
||||||
bool FilePath::CreateFolder() const {
|
// directory for any reason, including if the parent directory does not
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
// exist. Not named "CreateDirectory" because that's a macro on Windows.
|
||||||
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
bool FilePath::CreateFolder() const {
|
||||||
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
int result = CreateDirectory(unicode, NULL) ? 0 : -1;
|
FilePath removed_sep(this->RemoveTrailingPathSeparator());
|
||||||
delete [] unicode;
|
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
|
||||||
#elif GTEST_OS_WINDOWS
|
int result = CreateDirectory(unicode, NULL) ? 0 : -1;
|
||||||
int result = _mkdir(pathname_.c_str());
|
delete [] unicode;
|
||||||
#else
|
#elif GTEST_OS_WINDOWS
|
||||||
int result = mkdir(pathname_.c_str(), 0777);
|
int result = _mkdir(pathname_.c_str());
|
||||||
#endif // GTEST_OS_WINDOWS_MOBILE
|
#else
|
||||||
|
int result = mkdir(pathname_.c_str(), 0777);
|
||||||
if (result == -1) {
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
return this->DirectoryExists(); // An error is OK if the directory exists.
|
|
||||||
}
|
if (result == -1) {
|
||||||
return true; // No error.
|
return this->DirectoryExists(); // An error is OK if the directory exists.
|
||||||
}
|
}
|
||||||
|
return true; // No error.
|
||||||
// If input name has a trailing separator character, remove it and return the
|
}
|
||||||
// name, otherwise return the name string unmodified.
|
|
||||||
// On Windows platform, uses \ as the separator, other platforms use /.
|
// If input name has a trailing separator character, remove it and return the
|
||||||
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
// name, otherwise return the name string unmodified.
|
||||||
return IsDirectory()
|
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||||
? FilePath(pathname_.substr(0, pathname_.length() - 1))
|
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||||
: *this;
|
return IsDirectory()
|
||||||
}
|
? FilePath(pathname_.substr(0, pathname_.length() - 1))
|
||||||
|
: *this;
|
||||||
// Removes any redundant separators that might be in the pathname.
|
}
|
||||||
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
|
||||||
// redundancies that might be in a pathname involving "." or "..".
|
// Removes any redundant separators that might be in the pathname.
|
||||||
// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
|
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
|
||||||
void FilePath::Normalize() {
|
// redundancies that might be in a pathname involving "." or "..".
|
||||||
if (pathname_.c_str() == NULL) {
|
// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
|
||||||
pathname_ = "";
|
void FilePath::Normalize() {
|
||||||
return;
|
if (pathname_.c_str() == NULL) {
|
||||||
}
|
pathname_ = "";
|
||||||
const char* src = pathname_.c_str();
|
return;
|
||||||
char* const dest = new char[pathname_.length() + 1];
|
}
|
||||||
char* dest_ptr = dest;
|
const char* src = pathname_.c_str();
|
||||||
memset(dest_ptr, 0, pathname_.length() + 1);
|
char* const dest = new char[pathname_.length() + 1];
|
||||||
|
char* dest_ptr = dest;
|
||||||
while (*src != '\0') {
|
memset(dest_ptr, 0, pathname_.length() + 1);
|
||||||
*dest_ptr = *src;
|
|
||||||
if (!IsPathSeparator(*src)) {
|
while (*src != '\0') {
|
||||||
src++;
|
*dest_ptr = *src;
|
||||||
} else {
|
if (!IsPathSeparator(*src)) {
|
||||||
#if GTEST_HAS_ALT_PATH_SEP_
|
src++;
|
||||||
if (*dest_ptr == kAlternatePathSeparator) {
|
} else {
|
||||||
*dest_ptr = kPathSeparator;
|
#if GTEST_HAS_ALT_PATH_SEP_
|
||||||
}
|
if (*dest_ptr == kAlternatePathSeparator) {
|
||||||
#endif
|
*dest_ptr = kPathSeparator;
|
||||||
while (IsPathSeparator(*src))
|
}
|
||||||
src++;
|
#endif
|
||||||
}
|
while (IsPathSeparator(*src))
|
||||||
dest_ptr++;
|
src++;
|
||||||
}
|
}
|
||||||
*dest_ptr = '\0';
|
dest_ptr++;
|
||||||
pathname_ = dest;
|
}
|
||||||
delete[] dest;
|
*dest_ptr = '\0';
|
||||||
}
|
pathname_ = dest;
|
||||||
|
delete[] dest;
|
||||||
} // namespace internal
|
}
|
||||||
} // namespace testing
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,373 +1,363 @@
|
|||||||
// Copyright 2007, Google Inc.
|
// Copyright 2007, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
// Google Test - The Google C++ Testing Framework
|
// Google Test - The Google C++ Testing Framework
|
||||||
//
|
//
|
||||||
// This file implements a universal value printer that can print a
|
// This file implements a universal value printer that can print a
|
||||||
// value of any type T:
|
// value of any type T:
|
||||||
//
|
//
|
||||||
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
|
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
|
||||||
//
|
//
|
||||||
// It uses the << operator when possible, and prints the bytes in the
|
// It uses the << operator when possible, and prints the bytes in the
|
||||||
// object otherwise. A user can override its behavior for a class
|
// object otherwise. A user can override its behavior for a class
|
||||||
// type Foo by defining either operator<<(::std::ostream&, const Foo&)
|
// type Foo by defining either operator<<(::std::ostream&, const Foo&)
|
||||||
// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
|
// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
|
||||||
// defines Foo.
|
// defines Foo.
|
||||||
|
|
||||||
#include "gtest/gtest-printers.h"
|
#include "gtest/gtest-printers.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cwchar>
|
#include <ostream> // NOLINT
|
||||||
#include <ostream> // NOLINT
|
#include <string>
|
||||||
#include <string>
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/internal/gtest-port.h"
|
|
||||||
|
namespace testing {
|
||||||
namespace testing {
|
|
||||||
|
namespace {
|
||||||
namespace {
|
|
||||||
|
using ::std::ostream;
|
||||||
using ::std::ostream;
|
|
||||||
|
// Prints a segment of bytes in the given object.
|
||||||
// Prints a segment of bytes in the given object.
|
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
size_t count, ostream* os) {
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
char text[5] = "";
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
for (size_t i = 0; i != count; i++) {
|
||||||
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
const size_t j = start + i;
|
||||||
size_t count, ostream* os) {
|
if (i != 0) {
|
||||||
char text[5] = "";
|
// Organizes the bytes into groups of 2 for easy parsing by
|
||||||
for (size_t i = 0; i != count; i++) {
|
// human.
|
||||||
const size_t j = start + i;
|
if ((j % 2) == 0)
|
||||||
if (i != 0) {
|
*os << ' ';
|
||||||
// Organizes the bytes into groups of 2 for easy parsing by
|
else
|
||||||
// human.
|
*os << '-';
|
||||||
if ((j % 2) == 0)
|
}
|
||||||
*os << ' ';
|
GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
|
||||||
else
|
*os << text;
|
||||||
*os << '-';
|
}
|
||||||
}
|
}
|
||||||
GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
|
|
||||||
*os << text;
|
// Prints the bytes in the given value to the given ostream.
|
||||||
}
|
void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||||
}
|
ostream* os) {
|
||||||
|
// Tells the user how big the object is.
|
||||||
// Prints the bytes in the given value to the given ostream.
|
*os << count << "-byte object <";
|
||||||
void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
|
||||||
ostream* os) {
|
const size_t kThreshold = 132;
|
||||||
// Tells the user how big the object is.
|
const size_t kChunkSize = 64;
|
||||||
*os << count << "-byte object <";
|
// If the object size is bigger than kThreshold, we'll have to omit
|
||||||
|
// some details by printing only the first and the last kChunkSize
|
||||||
const size_t kThreshold = 132;
|
// bytes.
|
||||||
const size_t kChunkSize = 64;
|
// TODO(wan): let the user control the threshold using a flag.
|
||||||
// If the object size is bigger than kThreshold, we'll have to omit
|
if (count < kThreshold) {
|
||||||
// some details by printing only the first and the last kChunkSize
|
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
||||||
// bytes.
|
} else {
|
||||||
// TODO(wan): let the user control the threshold using a flag.
|
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
|
||||||
if (count < kThreshold) {
|
*os << " ... ";
|
||||||
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
|
// Rounds up to 2-byte boundary.
|
||||||
} else {
|
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
|
||||||
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
|
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
|
||||||
*os << " ... ";
|
}
|
||||||
// Rounds up to 2-byte boundary.
|
*os << ">";
|
||||||
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
|
}
|
||||||
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
|
|
||||||
}
|
} // namespace
|
||||||
*os << ">";
|
|
||||||
}
|
namespace internal2 {
|
||||||
|
|
||||||
} // namespace
|
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
|
||||||
|
// given object. The delegation simplifies the implementation, which
|
||||||
namespace internal2 {
|
// uses the << operator and thus is easier done outside of the
|
||||||
|
// ::testing::internal namespace, which contains a << operator that
|
||||||
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
|
// sometimes conflicts with the one in STL.
|
||||||
// given object. The delegation simplifies the implementation, which
|
void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
|
||||||
// uses the << operator and thus is easier done outside of the
|
ostream* os) {
|
||||||
// ::testing::internal namespace, which contains a << operator that
|
PrintBytesInObjectToImpl(obj_bytes, count, os);
|
||||||
// sometimes conflicts with the one in STL.
|
}
|
||||||
void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
|
|
||||||
ostream* os) {
|
} // namespace internal2
|
||||||
PrintBytesInObjectToImpl(obj_bytes, count, os);
|
|
||||||
}
|
namespace internal {
|
||||||
|
|
||||||
} // namespace internal2
|
// Depending on the value of a char (or wchar_t), we print it in one
|
||||||
|
// of three formats:
|
||||||
namespace internal {
|
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
||||||
|
// - as a hexidecimal escape sequence (e.g. '\x7F'), or
|
||||||
// Depending on the value of a char (or wchar_t), we print it in one
|
// - as a special escape sequence (e.g. '\r', '\n').
|
||||||
// of three formats:
|
enum CharFormat {
|
||||||
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
|
kAsIs,
|
||||||
// - as a hexidecimal escape sequence (e.g. '\x7F'), or
|
kHexEscape,
|
||||||
// - as a special escape sequence (e.g. '\r', '\n').
|
kSpecialEscape
|
||||||
enum CharFormat {
|
};
|
||||||
kAsIs,
|
|
||||||
kHexEscape,
|
// Returns true if c is a printable ASCII character. We test the
|
||||||
kSpecialEscape
|
// value of c directly instead of calling isprint(), which is buggy on
|
||||||
};
|
// Windows Mobile.
|
||||||
|
inline bool IsPrintableAscii(wchar_t c) {
|
||||||
// Returns true if c is a printable ASCII character. We test the
|
return 0x20 <= c && c <= 0x7E;
|
||||||
// value of c directly instead of calling isprint(), which is buggy on
|
}
|
||||||
// Windows Mobile.
|
|
||||||
inline bool IsPrintableAscii(wchar_t c) {
|
// Prints a wide or narrow char c as a character literal without the
|
||||||
return 0x20 <= c && c <= 0x7E;
|
// quotes, escaping it when necessary; returns how c was formatted.
|
||||||
}
|
// The template argument UnsignedChar is the unsigned version of Char,
|
||||||
|
// which is the type of c.
|
||||||
// Prints a wide or narrow char c as a character literal without the
|
template <typename UnsignedChar, typename Char>
|
||||||
// quotes, escaping it when necessary; returns how c was formatted.
|
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
||||||
// The template argument UnsignedChar is the unsigned version of Char,
|
switch (static_cast<wchar_t>(c)) {
|
||||||
// which is the type of c.
|
case L'\0':
|
||||||
template <typename UnsignedChar, typename Char>
|
*os << "\\0";
|
||||||
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
|
break;
|
||||||
switch (static_cast<wchar_t>(c)) {
|
case L'\'':
|
||||||
case L'\0':
|
*os << "\\'";
|
||||||
*os << "\\0";
|
break;
|
||||||
break;
|
case L'\\':
|
||||||
case L'\'':
|
*os << "\\\\";
|
||||||
*os << "\\'";
|
break;
|
||||||
break;
|
case L'\a':
|
||||||
case L'\\':
|
*os << "\\a";
|
||||||
*os << "\\\\";
|
break;
|
||||||
break;
|
case L'\b':
|
||||||
case L'\a':
|
*os << "\\b";
|
||||||
*os << "\\a";
|
break;
|
||||||
break;
|
case L'\f':
|
||||||
case L'\b':
|
*os << "\\f";
|
||||||
*os << "\\b";
|
break;
|
||||||
break;
|
case L'\n':
|
||||||
case L'\f':
|
*os << "\\n";
|
||||||
*os << "\\f";
|
break;
|
||||||
break;
|
case L'\r':
|
||||||
case L'\n':
|
*os << "\\r";
|
||||||
*os << "\\n";
|
break;
|
||||||
break;
|
case L'\t':
|
||||||
case L'\r':
|
*os << "\\t";
|
||||||
*os << "\\r";
|
break;
|
||||||
break;
|
case L'\v':
|
||||||
case L'\t':
|
*os << "\\v";
|
||||||
*os << "\\t";
|
break;
|
||||||
break;
|
default:
|
||||||
case L'\v':
|
if (IsPrintableAscii(c)) {
|
||||||
*os << "\\v";
|
*os << static_cast<char>(c);
|
||||||
break;
|
return kAsIs;
|
||||||
default:
|
} else {
|
||||||
if (IsPrintableAscii(c)) {
|
*os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
|
||||||
*os << static_cast<char>(c);
|
return kHexEscape;
|
||||||
return kAsIs;
|
}
|
||||||
} else {
|
}
|
||||||
*os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
|
return kSpecialEscape;
|
||||||
return kHexEscape;
|
}
|
||||||
}
|
|
||||||
}
|
// Prints a wchar_t c as if it's part of a string literal, escaping it when
|
||||||
return kSpecialEscape;
|
// necessary; returns how c was formatted.
|
||||||
}
|
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
||||||
|
switch (c) {
|
||||||
// Prints a wchar_t c as if it's part of a string literal, escaping it when
|
case L'\'':
|
||||||
// necessary; returns how c was formatted.
|
*os << "'";
|
||||||
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
|
return kAsIs;
|
||||||
switch (c) {
|
case L'"':
|
||||||
case L'\'':
|
*os << "\\\"";
|
||||||
*os << "'";
|
return kSpecialEscape;
|
||||||
return kAsIs;
|
default:
|
||||||
case L'"':
|
return PrintAsCharLiteralTo<wchar_t>(c, os);
|
||||||
*os << "\\\"";
|
}
|
||||||
return kSpecialEscape;
|
}
|
||||||
default:
|
|
||||||
return PrintAsCharLiteralTo<wchar_t>(c, os);
|
// Prints a char c as if it's part of a string literal, escaping it when
|
||||||
}
|
// necessary; returns how c was formatted.
|
||||||
}
|
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
|
||||||
|
return PrintAsStringLiteralTo(
|
||||||
// Prints a char c as if it's part of a string literal, escaping it when
|
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
|
||||||
// necessary; returns how c was formatted.
|
}
|
||||||
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
|
|
||||||
return PrintAsStringLiteralTo(
|
// Prints a wide or narrow character c and its code. '\0' is printed
|
||||||
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
|
// as "'\\0'", other unprintable characters are also properly escaped
|
||||||
}
|
// using the standard C++ escape sequence. The template argument
|
||||||
|
// UnsignedChar is the unsigned version of Char, which is the type of c.
|
||||||
// Prints a wide or narrow character c and its code. '\0' is printed
|
template <typename UnsignedChar, typename Char>
|
||||||
// as "'\\0'", other unprintable characters are also properly escaped
|
void PrintCharAndCodeTo(Char c, ostream* os) {
|
||||||
// using the standard C++ escape sequence. The template argument
|
// First, print c as a literal in the most readable form we can find.
|
||||||
// UnsignedChar is the unsigned version of Char, which is the type of c.
|
*os << ((sizeof(c) > 1) ? "L'" : "'");
|
||||||
template <typename UnsignedChar, typename Char>
|
const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
|
||||||
void PrintCharAndCodeTo(Char c, ostream* os) {
|
*os << "'";
|
||||||
// First, print c as a literal in the most readable form we can find.
|
|
||||||
*os << ((sizeof(c) > 1) ? "L'" : "'");
|
// To aid user debugging, we also print c's code in decimal, unless
|
||||||
const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
|
// it's 0 (in which case c was printed as '\\0', making the code
|
||||||
*os << "'";
|
// obvious).
|
||||||
|
if (c == 0)
|
||||||
// To aid user debugging, we also print c's code in decimal, unless
|
return;
|
||||||
// it's 0 (in which case c was printed as '\\0', making the code
|
*os << " (" << static_cast<int>(c);
|
||||||
// obvious).
|
|
||||||
if (c == 0)
|
// For more convenience, we print c's code again in hexidecimal,
|
||||||
return;
|
// unless c was already printed in the form '\x##' or the code is in
|
||||||
*os << " (" << static_cast<int>(c);
|
// [1, 9].
|
||||||
|
if (format == kHexEscape || (1 <= c && c <= 9)) {
|
||||||
// For more convenience, we print c's code again in hexidecimal,
|
// Do nothing.
|
||||||
// unless c was already printed in the form '\x##' or the code is in
|
} else {
|
||||||
// [1, 9].
|
*os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
|
||||||
if (format == kHexEscape || (1 <= c && c <= 9)) {
|
}
|
||||||
// Do nothing.
|
*os << ")";
|
||||||
} else {
|
}
|
||||||
*os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
|
|
||||||
}
|
void PrintTo(unsigned char c, ::std::ostream* os) {
|
||||||
*os << ")";
|
PrintCharAndCodeTo<unsigned char>(c, os);
|
||||||
}
|
}
|
||||||
|
void PrintTo(signed char c, ::std::ostream* os) {
|
||||||
void PrintTo(unsigned char c, ::std::ostream* os) {
|
PrintCharAndCodeTo<unsigned char>(c, os);
|
||||||
PrintCharAndCodeTo<unsigned char>(c, os);
|
}
|
||||||
}
|
|
||||||
void PrintTo(signed char c, ::std::ostream* os) {
|
// Prints a wchar_t as a symbol if it is printable or as its internal
|
||||||
PrintCharAndCodeTo<unsigned char>(c, os);
|
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
|
||||||
}
|
void PrintTo(wchar_t wc, ostream* os) {
|
||||||
|
PrintCharAndCodeTo<wchar_t>(wc, os);
|
||||||
// Prints a wchar_t as a symbol if it is printable or as its internal
|
}
|
||||||
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
|
|
||||||
void PrintTo(wchar_t wc, ostream* os) {
|
// Prints the given array of characters to the ostream. CharType must be either
|
||||||
PrintCharAndCodeTo<wchar_t>(wc, os);
|
// char or wchar_t.
|
||||||
}
|
// The array starts at begin, the length is len, it may include '\0' characters
|
||||||
|
// and may not be NUL-terminated.
|
||||||
// Prints the given array of characters to the ostream. CharType must be either
|
template <typename CharType>
|
||||||
// char or wchar_t.
|
static void PrintCharsAsStringTo(
|
||||||
// The array starts at begin, the length is len, it may include '\0' characters
|
const CharType* begin, size_t len, ostream* os) {
|
||||||
// and may not be NUL-terminated.
|
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
||||||
template <typename CharType>
|
*os << kQuoteBegin;
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
bool is_previous_hex = false;
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
for (size_t index = 0; index < len; ++index) {
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
const CharType cur = begin[index];
|
||||||
static void PrintCharsAsStringTo(
|
if (is_previous_hex && IsXDigit(cur)) {
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
// Previous character is of '\x..' form and this character can be
|
||||||
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
// interpreted as another hexadecimal digit in its number. Break string to
|
||||||
*os << kQuoteBegin;
|
// disambiguate.
|
||||||
bool is_previous_hex = false;
|
*os << "\" " << kQuoteBegin;
|
||||||
for (size_t index = 0; index < len; ++index) {
|
}
|
||||||
const CharType cur = begin[index];
|
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
||||||
if (is_previous_hex && IsXDigit(cur)) {
|
}
|
||||||
// Previous character is of '\x..' form and this character can be
|
*os << "\"";
|
||||||
// interpreted as another hexadecimal digit in its number. Break string to
|
}
|
||||||
// disambiguate.
|
|
||||||
*os << "\" " << kQuoteBegin;
|
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
||||||
}
|
// 'begin'. CharType must be either char or wchar_t.
|
||||||
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
|
template <typename CharType>
|
||||||
}
|
static void UniversalPrintCharArray(
|
||||||
*os << "\"";
|
const CharType* begin, size_t len, ostream* os) {
|
||||||
}
|
// The code
|
||||||
|
// const char kFoo[] = "foo";
|
||||||
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
// generates an array of 4, not 3, elements, with the last one being '\0'.
|
||||||
// 'begin'. CharType must be either char or wchar_t.
|
//
|
||||||
template <typename CharType>
|
// Therefore when printing a char array, we don't print the last element if
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
// it's '\0', such that the output matches the string literal as it's
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
// written in the source code.
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
if (len > 0 && begin[len - 1] == '\0') {
|
||||||
static void UniversalPrintCharArray(
|
PrintCharsAsStringTo(begin, len - 1, os);
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
return;
|
||||||
// The code
|
}
|
||||||
// const char kFoo[] = "foo";
|
|
||||||
// generates an array of 4, not 3, elements, with the last one being '\0'.
|
// If, however, the last element in the array is not '\0', e.g.
|
||||||
//
|
// const char kFoo[] = { 'f', 'o', 'o' };
|
||||||
// Therefore when printing a char array, we don't print the last element if
|
// we must print the entire array. We also print a message to indicate
|
||||||
// it's '\0', such that the output matches the string literal as it's
|
// that the array is not NUL-terminated.
|
||||||
// written in the source code.
|
PrintCharsAsStringTo(begin, len, os);
|
||||||
if (len > 0 && begin[len - 1] == '\0') {
|
*os << " (no terminating NUL)";
|
||||||
PrintCharsAsStringTo(begin, len - 1, os);
|
}
|
||||||
return;
|
|
||||||
}
|
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
|
||||||
|
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
||||||
// If, however, the last element in the array is not '\0', e.g.
|
UniversalPrintCharArray(begin, len, os);
|
||||||
// const char kFoo[] = { 'f', 'o', 'o' };
|
}
|
||||||
// we must print the entire array. We also print a message to indicate
|
|
||||||
// that the array is not NUL-terminated.
|
// Prints a (const) wchar_t array of 'len' elements, starting at address
|
||||||
PrintCharsAsStringTo(begin, len, os);
|
// 'begin'.
|
||||||
*os << " (no terminating NUL)";
|
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
||||||
}
|
UniversalPrintCharArray(begin, len, os);
|
||||||
|
}
|
||||||
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
|
|
||||||
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
|
// Prints the given C string to the ostream.
|
||||||
UniversalPrintCharArray(begin, len, os);
|
void PrintTo(const char* s, ostream* os) {
|
||||||
}
|
if (s == NULL) {
|
||||||
|
*os << "NULL";
|
||||||
// Prints a (const) wchar_t array of 'len' elements, starting at address
|
} else {
|
||||||
// 'begin'.
|
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||||
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
PrintCharsAsStringTo(s, strlen(s), os);
|
||||||
UniversalPrintCharArray(begin, len, os);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints the given C string to the ostream.
|
// MSVC compiler can be configured to define whar_t as a typedef
|
||||||
void PrintTo(const char* s, ostream* os) {
|
// of unsigned short. Defining an overload for const wchar_t* in that case
|
||||||
if (s == NULL) {
|
// would cause pointers to unsigned shorts be printed as wide strings,
|
||||||
*os << "NULL";
|
// possibly accessing more memory than intended and causing invalid
|
||||||
} else {
|
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
|
||||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
// wchar_t is implemented as a native type.
|
||||||
PrintCharsAsStringTo(s, strlen(s), os);
|
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||||
}
|
// Prints the given wide C string to the ostream.
|
||||||
}
|
void PrintTo(const wchar_t* s, ostream* os) {
|
||||||
|
if (s == NULL) {
|
||||||
// MSVC compiler can be configured to define whar_t as a typedef
|
*os << "NULL";
|
||||||
// of unsigned short. Defining an overload for const wchar_t* in that case
|
} else {
|
||||||
// would cause pointers to unsigned shorts be printed as wide strings,
|
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||||
// possibly accessing more memory than intended and causing invalid
|
PrintCharsAsStringTo(s, wcslen(s), os);
|
||||||
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
|
}
|
||||||
// wchar_t is implemented as a native type.
|
}
|
||||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
#endif // wchar_t is native
|
||||||
// Prints the given wide C string to the ostream.
|
|
||||||
void PrintTo(const wchar_t* s, ostream* os) {
|
// Prints a ::string object.
|
||||||
if (s == NULL) {
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
*os << "NULL";
|
void PrintStringTo(const ::string& s, ostream* os) {
|
||||||
} else {
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
}
|
||||||
PrintCharsAsStringTo(s, std::wcslen(s), os);
|
#endif // GTEST_HAS_GLOBAL_STRING
|
||||||
}
|
|
||||||
}
|
void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||||
#endif // wchar_t is native
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
|
}
|
||||||
// Prints a ::string object.
|
|
||||||
#if GTEST_HAS_GLOBAL_STRING
|
// Prints a ::wstring object.
|
||||||
void PrintStringTo(const ::string& s, ostream* os) {
|
#if GTEST_HAS_GLOBAL_WSTRING
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
void PrintWideStringTo(const ::wstring& s, ostream* os) {
|
||||||
}
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
#endif // GTEST_HAS_GLOBAL_STRING
|
}
|
||||||
|
#endif // GTEST_HAS_GLOBAL_WSTRING
|
||||||
void PrintStringTo(const ::std::string& s, ostream* os) {
|
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
#if GTEST_HAS_STD_WSTRING
|
||||||
}
|
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
||||||
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
// Prints a ::wstring object.
|
}
|
||||||
#if GTEST_HAS_GLOBAL_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
void PrintWideStringTo(const ::wstring& s, ostream* os) {
|
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
} // namespace internal
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_GLOBAL_WSTRING
|
} // namespace testing
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
|
||||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
} // namespace testing
|
|
||||||
@@ -1,110 +1,110 @@
|
|||||||
// Copyright 2008, Google Inc.
|
// Copyright 2008, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: mheule@google.com (Markus Heule)
|
// Author: mheule@google.com (Markus Heule)
|
||||||
//
|
//
|
||||||
// The Google C++ Testing Framework (Google Test)
|
// The Google C++ Testing Framework (Google Test)
|
||||||
|
|
||||||
#include "gtest/gtest-test-part.h"
|
#include "gtest/gtest-test-part.h"
|
||||||
|
|
||||||
// Indicates that this translation unit is part of Google Test's
|
// Indicates that this translation unit is part of Google Test's
|
||||||
// implementation. It must come before gtest-internal-inl.h is
|
// implementation. It must come before gtest-internal-inl.h is
|
||||||
// included, or there will be a compiler error. This trick is to
|
// included, or there will be a compiler error. This trick is to
|
||||||
// prevent a user from accidentally including gtest-internal-inl.h in
|
// prevent a user from accidentally including gtest-internal-inl.h in
|
||||||
// his code.
|
// his code.
|
||||||
#define GTEST_IMPLEMENTATION_ 1
|
#define GTEST_IMPLEMENTATION_ 1
|
||||||
#include "src/gtest-internal-inl.h"
|
#include "src/gtest-internal-inl.h"
|
||||||
#undef GTEST_IMPLEMENTATION_
|
#undef GTEST_IMPLEMENTATION_
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
using internal::GetUnitTestImpl;
|
using internal::GetUnitTestImpl;
|
||||||
|
|
||||||
// Gets the summary of the failure message by omitting the stack trace
|
// Gets the summary of the failure message by omitting the stack trace
|
||||||
// in it.
|
// in it.
|
||||||
std::string TestPartResult::ExtractSummary(const char* message) {
|
std::string TestPartResult::ExtractSummary(const char* message) {
|
||||||
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
||||||
return stack_trace == NULL ? message :
|
return stack_trace == NULL ? message :
|
||||||
std::string(message, stack_trace);
|
std::string(message, stack_trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints a TestPartResult object.
|
// Prints a TestPartResult object.
|
||||||
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
|
||||||
return os
|
return os
|
||||||
<< result.file_name() << ":" << result.line_number() << ": "
|
<< result.file_name() << ":" << result.line_number() << ": "
|
||||||
<< (result.type() == TestPartResult::kSuccess ? "Success" :
|
<< (result.type() == TestPartResult::kSuccess ? "Success" :
|
||||||
result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
|
result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
|
||||||
"Non-fatal failure") << ":\n"
|
"Non-fatal failure") << ":\n"
|
||||||
<< result.message() << std::endl;
|
<< result.message() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a TestPartResult to the array.
|
// Appends a TestPartResult to the array.
|
||||||
void TestPartResultArray::Append(const TestPartResult& result) {
|
void TestPartResultArray::Append(const TestPartResult& result) {
|
||||||
array_.push_back(result);
|
array_.push_back(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the TestPartResult at the given index (0-based).
|
// Returns the TestPartResult at the given index (0-based).
|
||||||
const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
|
const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
|
||||||
if (index < 0 || index >= size()) {
|
if (index < 0 || index >= size()) {
|
||||||
printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
|
printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
|
||||||
internal::posix::Abort();
|
internal::posix::Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_[index];
|
return array_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of TestPartResult objects in the array.
|
// Returns the number of TestPartResult objects in the array.
|
||||||
int TestPartResultArray::size() const {
|
int TestPartResultArray::size() const {
|
||||||
return static_cast<int>(array_.size());
|
return static_cast<int>(array_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
|
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
|
||||||
: has_new_fatal_failure_(false),
|
: has_new_fatal_failure_(false),
|
||||||
original_reporter_(GetUnitTestImpl()->
|
original_reporter_(GetUnitTestImpl()->
|
||||||
GetTestPartResultReporterForCurrentThread()) {
|
GetTestPartResultReporterForCurrentThread()) {
|
||||||
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
|
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
|
HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
|
||||||
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
|
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
|
||||||
original_reporter_);
|
original_reporter_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HasNewFatalFailureHelper::ReportTestPartResult(
|
void HasNewFatalFailureHelper::ReportTestPartResult(
|
||||||
const TestPartResult& result) {
|
const TestPartResult& result) {
|
||||||
if (result.fatally_failed())
|
if (result.fatally_failed())
|
||||||
has_new_fatal_failure_ = true;
|
has_new_fatal_failure_ = true;
|
||||||
original_reporter_->ReportTestPartResult(result);
|
original_reporter_->ReportTestPartResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
@@ -1,110 +1,110 @@
|
|||||||
// Copyright 2008 Google Inc.
|
// Copyright 2008 Google Inc.
|
||||||
// All Rights Reserved.
|
// All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
#include "gtest/gtest-typed-test.h"
|
#include "gtest/gtest-typed-test.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
#if GTEST_HAS_TYPED_TEST_P
|
#if GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
// Skips to the first non-space char in str. Returns an empty string if str
|
// Skips to the first non-space char in str. Returns an empty string if str
|
||||||
// contains only whitespace characters.
|
// contains only whitespace characters.
|
||||||
static const char* SkipSpaces(const char* str) {
|
static const char* SkipSpaces(const char* str) {
|
||||||
while (IsSpace(*str))
|
while (IsSpace(*str))
|
||||||
str++;
|
str++;
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifies that registered_tests match the test names in
|
// Verifies that registered_tests match the test names in
|
||||||
// defined_test_names_; returns registered_tests if successful, or
|
// defined_test_names_; returns registered_tests if successful, or
|
||||||
// aborts the program otherwise.
|
// aborts the program otherwise.
|
||||||
const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
const char* TypedTestCasePState::VerifyRegisteredTestNames(
|
||||||
const char* file, int line, const char* registered_tests) {
|
const char* file, int line, const char* registered_tests) {
|
||||||
typedef ::std::set<const char*>::const_iterator DefinedTestIter;
|
typedef ::std::set<const char*>::const_iterator DefinedTestIter;
|
||||||
registered_ = true;
|
registered_ = true;
|
||||||
|
|
||||||
// Skip initial whitespace in registered_tests since some
|
// Skip initial whitespace in registered_tests since some
|
||||||
// preprocessors prefix stringizied literals with whitespace.
|
// preprocessors prefix stringizied literals with whitespace.
|
||||||
registered_tests = SkipSpaces(registered_tests);
|
registered_tests = SkipSpaces(registered_tests);
|
||||||
|
|
||||||
Message errors;
|
Message errors;
|
||||||
::std::set<std::string> tests;
|
::std::set<std::string> tests;
|
||||||
for (const char* names = registered_tests; names != NULL;
|
for (const char* names = registered_tests; names != NULL;
|
||||||
names = SkipComma(names)) {
|
names = SkipComma(names)) {
|
||||||
const std::string name = GetPrefixUntilComma(names);
|
const std::string name = GetPrefixUntilComma(names);
|
||||||
if (tests.count(name) != 0) {
|
if (tests.count(name) != 0) {
|
||||||
errors << "Test " << name << " is listed more than once.\n";
|
errors << "Test " << name << " is listed more than once.\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (DefinedTestIter it = defined_test_names_.begin();
|
for (DefinedTestIter it = defined_test_names_.begin();
|
||||||
it != defined_test_names_.end();
|
it != defined_test_names_.end();
|
||||||
++it) {
|
++it) {
|
||||||
if (name == *it) {
|
if (name == *it) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
tests.insert(name);
|
tests.insert(name);
|
||||||
} else {
|
} else {
|
||||||
errors << "No test named " << name
|
errors << "No test named " << name
|
||||||
<< " can be found in this test case.\n";
|
<< " can be found in this test case.\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DefinedTestIter it = defined_test_names_.begin();
|
for (DefinedTestIter it = defined_test_names_.begin();
|
||||||
it != defined_test_names_.end();
|
it != defined_test_names_.end();
|
||||||
++it) {
|
++it) {
|
||||||
if (tests.count(*it) == 0) {
|
if (tests.count(*it) == 0) {
|
||||||
errors << "You forgot to list test " << *it << ".\n";
|
errors << "You forgot to list test " << *it << ".\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& errors_str = errors.GetString();
|
const std::string& errors_str = errors.GetString();
|
||||||
if (errors_str != "") {
|
if (errors_str != "") {
|
||||||
fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
|
fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
|
||||||
errors_str.c_str());
|
errors_str.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
posix::Abort();
|
posix::Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return registered_tests;
|
return registered_tests;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GTEST_HAS_TYPED_TEST_P
|
#endif // GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,38 +1,38 @@
|
|||||||
// Copyright 2006, Google Inc.
|
// Copyright 2006, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright
|
// * Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// * Redistributions in binary form must reproduce the above
|
// * Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
// in the documentation and/or other materials provided with the
|
// in the documentation and/or other materials provided with the
|
||||||
// distribution.
|
// distribution.
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived from
|
// contributors may be used to endorse or promote products derived from
|
||||||
// this software without specific prior written permission.
|
// this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
GTEST_API_ int main(int argc, char **argv) {
|
GTEST_API_ int main(int argc, char **argv) {
|
||||||
printf("Running main() from gtest_main.cc\n");
|
printf("Running main() from gtest_main.cc\n");
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
1078
gmock/include/gmock/gmock-actions.h
Normal file
1078
gmock/include/gmock/gmock-actions.h
Normal file
File diff suppressed because it is too large
Load Diff
147
gmock/include/gmock/gmock-cardinalities.h
Normal file
147
gmock/include/gmock/gmock-cardinalities.h
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some commonly used cardinalities. More
|
||||||
|
// cardinalities can be defined by the user implementing the
|
||||||
|
// CardinalityInterface interface if necessary.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// To implement a cardinality Foo, define:
|
||||||
|
// 1. a class FooCardinality that implements the
|
||||||
|
// CardinalityInterface interface, and
|
||||||
|
// 2. a factory function that creates a Cardinality object from a
|
||||||
|
// const FooCardinality*.
|
||||||
|
//
|
||||||
|
// The two-level delegation design follows that of Matcher, providing
|
||||||
|
// consistency for extension developers. It also eases ownership
|
||||||
|
// management as Cardinality objects can now be copied like plain values.
|
||||||
|
|
||||||
|
// The implementation of a cardinality.
|
||||||
|
class CardinalityInterface {
|
||||||
|
public:
|
||||||
|
virtual ~CardinalityInterface() {}
|
||||||
|
|
||||||
|
// Conservative estimate on the lower/upper bound of the number of
|
||||||
|
// calls allowed.
|
||||||
|
virtual int ConservativeLowerBound() const { return 0; }
|
||||||
|
virtual int ConservativeUpperBound() const { return INT_MAX; }
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will satisfy this cardinality.
|
||||||
|
virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will saturate this cardinality.
|
||||||
|
virtual bool IsSaturatedByCallCount(int call_count) const = 0;
|
||||||
|
|
||||||
|
// Describes self to an ostream.
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A Cardinality is a copyable and IMMUTABLE (except by assignment)
|
||||||
|
// object that specifies how many times a mock function is expected to
|
||||||
|
// be called. The implementation of Cardinality is just a linked_ptr
|
||||||
|
// to const CardinalityInterface, so copying is fairly cheap.
|
||||||
|
// Don't inherit from Cardinality!
|
||||||
|
class GTEST_API_ Cardinality {
|
||||||
|
public:
|
||||||
|
// Constructs a null cardinality. Needed for storing Cardinality
|
||||||
|
// objects in STL containers.
|
||||||
|
Cardinality() {}
|
||||||
|
|
||||||
|
// Constructs a Cardinality from its implementation.
|
||||||
|
explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {}
|
||||||
|
|
||||||
|
// Conservative estimate on the lower/upper bound of the number of
|
||||||
|
// calls allowed.
|
||||||
|
int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
|
||||||
|
int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will satisfy this cardinality.
|
||||||
|
bool IsSatisfiedByCallCount(int call_count) const {
|
||||||
|
return impl_->IsSatisfiedByCallCount(call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will saturate this cardinality.
|
||||||
|
bool IsSaturatedByCallCount(int call_count) const {
|
||||||
|
return impl_->IsSaturatedByCallCount(call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff call_count calls will over-saturate this
|
||||||
|
// cardinality, i.e. exceed the maximum number of allowed calls.
|
||||||
|
bool IsOverSaturatedByCallCount(int call_count) const {
|
||||||
|
return impl_->IsSaturatedByCallCount(call_count) &&
|
||||||
|
!impl_->IsSatisfiedByCallCount(call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes self to an ostream
|
||||||
|
void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
|
||||||
|
|
||||||
|
// Describes the given actual call count to an ostream.
|
||||||
|
static void DescribeActualCallCountTo(int actual_call_count,
|
||||||
|
::std::ostream* os);
|
||||||
|
|
||||||
|
private:
|
||||||
|
internal::linked_ptr<const CardinalityInterface> impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at least n calls.
|
||||||
|
GTEST_API_ Cardinality AtLeast(int n);
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at most n calls.
|
||||||
|
GTEST_API_ Cardinality AtMost(int n);
|
||||||
|
|
||||||
|
// Creates a cardinality that allows any number of calls.
|
||||||
|
GTEST_API_ Cardinality AnyNumber();
|
||||||
|
|
||||||
|
// Creates a cardinality that allows between min and max calls.
|
||||||
|
GTEST_API_ Cardinality Between(int min, int max);
|
||||||
|
|
||||||
|
// Creates a cardinality that allows exactly n calls.
|
||||||
|
GTEST_API_ Cardinality Exactly(int n);
|
||||||
|
|
||||||
|
// Creates a cardinality from its implementation.
|
||||||
|
inline Cardinality MakeCardinality(const CardinalityInterface* c) {
|
||||||
|
return Cardinality(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
||||||
2415
gmock/include/gmock/gmock-generated-actions.h
Normal file
2415
gmock/include/gmock/gmock-generated-actions.h
Normal file
File diff suppressed because it is too large
Load Diff
821
gmock/include/gmock/gmock-generated-actions.h.pump
Normal file
821
gmock/include/gmock/gmock-generated-actions.h.pump
Normal file
@@ -0,0 +1,821 @@
|
|||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-actions.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
$$}} This meta comment fixes auto-indentation in editors.
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some commonly used variadic actions.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||||
|
|
||||||
|
#include "gmock/gmock-actions.h"
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
|
||||||
|
// function or method with the unpacked values, where F is a function
|
||||||
|
// type that takes N arguments.
|
||||||
|
template <typename Result, typename ArgumentTuple>
|
||||||
|
class InvokeHelper;
|
||||||
|
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var types = [[$for j [[, typename A$j]]]]
|
||||||
|
$var as = [[$for j, [[A$j]]]]
|
||||||
|
$var args = [[$if i==0 [[]] $else [[ args]]]]
|
||||||
|
$var import = [[$if i==0 [[]] $else [[
|
||||||
|
using ::std::tr1::get;
|
||||||
|
|
||||||
|
]]]]
|
||||||
|
$var gets = [[$for j, [[get<$(j - 1)>(args)]]]]
|
||||||
|
template <typename R$types>
|
||||||
|
class InvokeHelper<R, ::std::tr1::tuple<$as> > {
|
||||||
|
public:
|
||||||
|
template <typename Function>
|
||||||
|
static R Invoke(Function function, const ::std::tr1::tuple<$as>&$args) {
|
||||||
|
$import return function($gets);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Class, typename MethodPtr>
|
||||||
|
static R InvokeMethod(Class* obj_ptr,
|
||||||
|
MethodPtr method_ptr,
|
||||||
|
const ::std::tr1::tuple<$as>&$args) {
|
||||||
|
$import return (obj_ptr->*method_ptr)($gets);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// CallableHelper has static methods for invoking "callables",
|
||||||
|
// i.e. function pointers and functors. It uses overloading to
|
||||||
|
// provide a uniform interface for invoking different kinds of
|
||||||
|
// callables. In particular, you can use:
|
||||||
|
//
|
||||||
|
// CallableHelper<R>::Call(callable, a1, a2, ..., an)
|
||||||
|
//
|
||||||
|
// to invoke an n-ary callable, where R is its return type. If an
|
||||||
|
// argument, say a2, needs to be passed by reference, you should write
|
||||||
|
// ByRef(a2) instead of a2 in the above expression.
|
||||||
|
template <typename R>
|
||||||
|
class CallableHelper {
|
||||||
|
public:
|
||||||
|
// Calls a nullary callable.
|
||||||
|
template <typename Function>
|
||||||
|
static R Call(Function function) { return function(); }
|
||||||
|
|
||||||
|
// Calls a unary callable.
|
||||||
|
|
||||||
|
// We deliberately pass a1 by value instead of const reference here
|
||||||
|
// in case it is a C-string literal. If we had declared the
|
||||||
|
// parameter as 'const A1& a1' and write Call(function, "Hi"), the
|
||||||
|
// compiler would've thought A1 is 'char[3]', which causes trouble
|
||||||
|
// when you need to copy a value of type A1. By declaring the
|
||||||
|
// parameter as 'A1 a1', the compiler will correctly infer that A1
|
||||||
|
// is 'const char*' when it sees Call(function, "Hi").
|
||||||
|
//
|
||||||
|
// Since this function is defined inline, the compiler can get rid
|
||||||
|
// of the copying of the arguments. Therefore the performance won't
|
||||||
|
// be hurt.
|
||||||
|
template <typename Function, typename A1>
|
||||||
|
static R Call(Function function, A1 a1) { return function(a1); }
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i
|
||||||
|
[[
|
||||||
|
$var arity = [[$if i==2 [[binary]] $elif i==3 [[ternary]] $else [[$i-ary]]]]
|
||||||
|
|
||||||
|
// Calls a $arity callable.
|
||||||
|
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j, [[typename A$j]]]]
|
||||||
|
$var Aas = [[$for j, [[A$j a$j]]]]
|
||||||
|
$var as = [[$for j, [[a$j]]]]
|
||||||
|
$var typename_Ts = [[$for j, [[typename T$j]]]]
|
||||||
|
$var Ts = [[$for j, [[T$j]]]]
|
||||||
|
template <typename Function, $typename_As>
|
||||||
|
static R Call(Function function, $Aas) {
|
||||||
|
return function($as);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
}; // class CallableHelper
|
||||||
|
|
||||||
|
// An INTERNAL macro for extracting the type of a tuple field. It's
|
||||||
|
// subject to change without notice - DO NOT USE IN USER CODE!
|
||||||
|
#define GMOCK_FIELD_(Tuple, N) \
|
||||||
|
typename ::std::tr1::tuple_element<N, Tuple>::type
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
|
||||||
|
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
|
||||||
|
// type of an n-ary function whose i-th (1-based) argument type is the
|
||||||
|
// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
|
||||||
|
// type, and whose return type is Result. For example,
|
||||||
|
// SelectArgs<int, ::std::tr1::tuple<bool, char, double, long>, 0, 3>::type
|
||||||
|
// is int(bool, long).
|
||||||
|
//
|
||||||
|
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
|
||||||
|
// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
|
||||||
|
// For example,
|
||||||
|
// SelectArgs<int, ::std::tr1::tuple<bool, char, double>, 2, 0>::Select(
|
||||||
|
// ::std::tr1::make_tuple(true, 'a', 2.5))
|
||||||
|
// returns ::std::tr1::tuple (2.5, true).
|
||||||
|
//
|
||||||
|
// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
|
||||||
|
// in the range [0, $n]. Duplicates are allowed and they don't have
|
||||||
|
// to be in an ascending or descending order.
|
||||||
|
|
||||||
|
template <typename Result, typename ArgumentTuple, $for i, [[int k$i]]>
|
||||||
|
class SelectArgs {
|
||||||
|
public:
|
||||||
|
typedef Result type($for i, [[GMOCK_FIELD_(ArgumentTuple, k$i)]]);
|
||||||
|
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||||
|
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return SelectedArgs($for i, [[get<k$i>(args)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 1..n
|
||||||
|
$range j1 1..i-1
|
||||||
|
template <typename Result, typename ArgumentTuple$for j1[[, int k$j1]]>
|
||||||
|
class SelectArgs<Result, ArgumentTuple,
|
||||||
|
$for j, [[$if j <= i-1 [[k$j]] $else [[-1]]]]> {
|
||||||
|
public:
|
||||||
|
typedef Result type($for j1, [[GMOCK_FIELD_(ArgumentTuple, k$j1)]]);
|
||||||
|
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||||
|
static SelectedArgs Select(const ArgumentTuple& [[]]
|
||||||
|
$if i == 1 [[/* args */]] $else [[args]]) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return SelectedArgs($for j1, [[get<k$j1>(args)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
#undef GMOCK_FIELD_
|
||||||
|
|
||||||
|
$var ks = [[$for i, [[k$i]]]]
|
||||||
|
|
||||||
|
// Implements the WithArgs action.
|
||||||
|
template <typename InnerAction, $for i, [[int k$i = -1]]>
|
||||||
|
class WithArgsAction {
|
||||||
|
public:
|
||||||
|
explicit WithArgsAction(const InnerAction& action) : action_(action) {}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename F>
|
||||||
|
class Impl : public ActionInterface<F> {
|
||||||
|
public:
|
||||||
|
typedef typename Function<F>::Result Result;
|
||||||
|
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
explicit Impl(const InnerAction& action) : action_(action) {}
|
||||||
|
|
||||||
|
virtual Result Perform(const ArgumentTuple& args) {
|
||||||
|
return action_.Perform(SelectArgs<Result, ArgumentTuple, $ks>::Select(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename SelectArgs<Result, ArgumentTuple,
|
||||||
|
$ks>::type InnerFunctionType;
|
||||||
|
|
||||||
|
Action<InnerFunctionType> action_;
|
||||||
|
};
|
||||||
|
|
||||||
|
const InnerAction action_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(WithArgsAction);
|
||||||
|
};
|
||||||
|
|
||||||
|
// A macro from the ACTION* family (defined later in this file)
|
||||||
|
// defines an action that can be used in a mock function. Typically,
|
||||||
|
// these actions only care about a subset of the arguments of the mock
|
||||||
|
// function. For example, if such an action only uses the second
|
||||||
|
// argument, it can be used in any mock function that takes >= 2
|
||||||
|
// arguments where the type of the second argument is compatible.
|
||||||
|
//
|
||||||
|
// Therefore, the action implementation must be prepared to take more
|
||||||
|
// arguments than it needs. The ExcessiveArg type is used to
|
||||||
|
// represent those excessive arguments. In order to keep the compiler
|
||||||
|
// error messages tractable, we define it in the testing namespace
|
||||||
|
// instead of testing::internal. However, this is an INTERNAL TYPE
|
||||||
|
// and subject to change without notice, so a user MUST NOT USE THIS
|
||||||
|
// TYPE DIRECTLY.
|
||||||
|
struct ExcessiveArg {};
|
||||||
|
|
||||||
|
// A helper class needed for implementing the ACTION* macros.
|
||||||
|
template <typename Result, class Impl>
|
||||||
|
class ActionHelper {
|
||||||
|
public:
|
||||||
|
$range i 0..n
|
||||||
|
$for i
|
||||||
|
|
||||||
|
[[
|
||||||
|
$var template = [[$if i==0 [[]] $else [[
|
||||||
|
$range j 0..i-1
|
||||||
|
template <$for j, [[typename A$j]]>
|
||||||
|
]]]]
|
||||||
|
$range j 0..i-1
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var as = [[$for j, [[get<$j>(args)]]]]
|
||||||
|
$range k 1..n-i
|
||||||
|
$var eas = [[$for k, [[ExcessiveArg()]]]]
|
||||||
|
$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]]
|
||||||
|
$template
|
||||||
|
static Result Perform(Impl* impl, const ::std::tr1::tuple<$As>& args) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return impl->template gmock_PerformImpl<$As>(args, $arg_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Various overloads for Invoke().
|
||||||
|
|
||||||
|
// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
|
||||||
|
// the selected arguments of the mock function to an_action and
|
||||||
|
// performs it. It serves as an adaptor between actions with
|
||||||
|
// different argument lists. C++ doesn't support default arguments for
|
||||||
|
// function templates, so we have to overload it.
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j [[int k$j, ]]typename InnerAction>
|
||||||
|
inline internal::WithArgsAction<InnerAction$for j [[, k$j]]>
|
||||||
|
WithArgs(const InnerAction& action) {
|
||||||
|
return internal::WithArgsAction<InnerAction$for j [[, k$j]]>(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// Creates an action that does actions a1, a2, ..., sequentially in
|
||||||
|
// each invocation.
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 2..i
|
||||||
|
$var types = [[$for j, [[typename Action$j]]]]
|
||||||
|
$var Aas = [[$for j [[, Action$j a$j]]]]
|
||||||
|
|
||||||
|
template <typename Action1, $types>
|
||||||
|
$range k 1..i-1
|
||||||
|
|
||||||
|
inline $for k [[internal::DoBothAction<Action$k, ]]Action$i$for k [[>]]
|
||||||
|
|
||||||
|
DoAll(Action1 a1$Aas) {
|
||||||
|
$if i==2 [[
|
||||||
|
|
||||||
|
return internal::DoBothAction<Action1, Action2>(a1, a2);
|
||||||
|
]] $else [[
|
||||||
|
$range j2 2..i
|
||||||
|
|
||||||
|
return DoAll(a1, DoAll($for j2, [[a$j2]]));
|
||||||
|
]]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
// The ACTION* family of macros can be used in a namespace scope to
|
||||||
|
// define custom actions easily. The syntax:
|
||||||
|
//
|
||||||
|
// ACTION(name) { statements; }
|
||||||
|
//
|
||||||
|
// will define an action with the given name that executes the
|
||||||
|
// statements. The value returned by the statements will be used as
|
||||||
|
// the return value of the action. Inside the statements, you can
|
||||||
|
// refer to the K-th (0-based) argument of the mock function by
|
||||||
|
// 'argK', and refer to its type by 'argK_type'. For example:
|
||||||
|
//
|
||||||
|
// ACTION(IncrementArg1) {
|
||||||
|
// arg1_type temp = arg1;
|
||||||
|
// return ++(*temp);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// allows you to write
|
||||||
|
//
|
||||||
|
// ...WillOnce(IncrementArg1());
|
||||||
|
//
|
||||||
|
// You can also refer to the entire argument tuple and its type by
|
||||||
|
// 'args' and 'args_type', and refer to the mock function type and its
|
||||||
|
// return type by 'function_type' and 'return_type'.
|
||||||
|
//
|
||||||
|
// Note that you don't need to specify the types of the mock function
|
||||||
|
// arguments. However rest assured that your code is still type-safe:
|
||||||
|
// you'll get a compiler error if *arg1 doesn't support the ++
|
||||||
|
// operator, or if the type of ++(*arg1) isn't compatible with the
|
||||||
|
// mock function's return type, for example.
|
||||||
|
//
|
||||||
|
// Sometimes you'll want to parameterize the action. For that you can use
|
||||||
|
// another macro:
|
||||||
|
//
|
||||||
|
// ACTION_P(name, param_name) { statements; }
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// ACTION_P(Add, n) { return arg0 + n; }
|
||||||
|
//
|
||||||
|
// will allow you to write:
|
||||||
|
//
|
||||||
|
// ...WillOnce(Add(5));
|
||||||
|
//
|
||||||
|
// Note that you don't need to provide the type of the parameter
|
||||||
|
// either. If you need to reference the type of a parameter named
|
||||||
|
// 'foo', you can write 'foo_type'. For example, in the body of
|
||||||
|
// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
|
||||||
|
// of 'n'.
|
||||||
|
//
|
||||||
|
// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support
|
||||||
|
// multi-parameter actions.
|
||||||
|
//
|
||||||
|
// For the purpose of typing, you can view
|
||||||
|
//
|
||||||
|
// ACTION_Pk(Foo, p1, ..., pk) { ... }
|
||||||
|
//
|
||||||
|
// as shorthand for
|
||||||
|
//
|
||||||
|
// template <typename p1_type, ..., typename pk_type>
|
||||||
|
// FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||||
|
//
|
||||||
|
// In particular, you can provide the template type arguments
|
||||||
|
// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
|
||||||
|
// although usually you can rely on the compiler to infer the types
|
||||||
|
// for you automatically. You can assign the result of expression
|
||||||
|
// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
|
||||||
|
// pk_type>. This can be useful when composing actions.
|
||||||
|
//
|
||||||
|
// You can also overload actions with different numbers of parameters:
|
||||||
|
//
|
||||||
|
// ACTION_P(Plus, a) { ... }
|
||||||
|
// ACTION_P2(Plus, a, b) { ... }
|
||||||
|
//
|
||||||
|
// While it's tempting to always use the ACTION* macros when defining
|
||||||
|
// a new action, you should also consider implementing ActionInterface
|
||||||
|
// or using MakePolymorphicAction() instead, especially if you need to
|
||||||
|
// use the action a lot. While these approaches require more work,
|
||||||
|
// they give you more control on the types of the mock function
|
||||||
|
// arguments and the action parameters, which in general leads to
|
||||||
|
// better compiler error messages that pay off in the long run. They
|
||||||
|
// also allow overloading actions based on parameter types (as opposed
|
||||||
|
// to just based on the number of parameters).
|
||||||
|
//
|
||||||
|
// CAVEAT:
|
||||||
|
//
|
||||||
|
// ACTION*() can only be used in a namespace scope. The reason is
|
||||||
|
// that C++ doesn't yet allow function-local types to be used to
|
||||||
|
// instantiate templates. The up-coming C++0x standard will fix this.
|
||||||
|
// Once that's done, we'll consider supporting using ACTION*() inside
|
||||||
|
// a function.
|
||||||
|
//
|
||||||
|
// MORE INFORMATION:
|
||||||
|
//
|
||||||
|
// To learn more about using these macros, please search for 'ACTION'
|
||||||
|
// on http://code.google.com/p/googlemock/wiki/CookBook.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$range k 0..n-1
|
||||||
|
|
||||||
|
// An internal macro needed for implementing ACTION*().
|
||||||
|
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
|
||||||
|
const args_type& args GTEST_ATTRIBUTE_UNUSED_
|
||||||
|
$for k [[, \
|
||||||
|
arg$k[[]]_type arg$k GTEST_ATTRIBUTE_UNUSED_]]
|
||||||
|
|
||||||
|
|
||||||
|
// Sometimes you want to give an action explicit template parameters
|
||||||
|
// that cannot be inferred from its value parameters. ACTION() and
|
||||||
|
// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that
|
||||||
|
// and can be viewed as an extension to ACTION() and ACTION_P*().
|
||||||
|
//
|
||||||
|
// The syntax:
|
||||||
|
//
|
||||||
|
// ACTION_TEMPLATE(ActionName,
|
||||||
|
// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
|
||||||
|
// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
|
||||||
|
//
|
||||||
|
// defines an action template that takes m explicit template
|
||||||
|
// parameters and n value parameters. name_i is the name of the i-th
|
||||||
|
// template parameter, and kind_i specifies whether it's a typename,
|
||||||
|
// an integral constant, or a template. p_i is the name of the i-th
|
||||||
|
// value parameter.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// // DuplicateArg<k, T>(output) converts the k-th argument of the mock
|
||||||
|
// // function to type T and copies it to *output.
|
||||||
|
// ACTION_TEMPLATE(DuplicateArg,
|
||||||
|
// HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
|
||||||
|
// AND_1_VALUE_PARAMS(output)) {
|
||||||
|
// *output = T(std::tr1::get<k>(args));
|
||||||
|
// }
|
||||||
|
// ...
|
||||||
|
// int n;
|
||||||
|
// EXPECT_CALL(mock, Foo(_, _))
|
||||||
|
// .WillOnce(DuplicateArg<1, unsigned char>(&n));
|
||||||
|
//
|
||||||
|
// To create an instance of an action template, write:
|
||||||
|
//
|
||||||
|
// ActionName<t1, ..., t_m>(v1, ..., v_n)
|
||||||
|
//
|
||||||
|
// where the ts are the template arguments and the vs are the value
|
||||||
|
// arguments. The value argument types are inferred by the compiler.
|
||||||
|
// If you want to explicitly specify the value argument types, you can
|
||||||
|
// provide additional template arguments:
|
||||||
|
//
|
||||||
|
// ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
|
||||||
|
//
|
||||||
|
// where u_i is the desired type of v_i.
|
||||||
|
//
|
||||||
|
// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
|
||||||
|
// number of value parameters, but not on the number of template
|
||||||
|
// parameters. Without the restriction, the meaning of the following
|
||||||
|
// is unclear:
|
||||||
|
//
|
||||||
|
// OverloadedAction<int, bool>(x);
|
||||||
|
//
|
||||||
|
// Are we using a single-template-parameter action where 'bool' refers
|
||||||
|
// to the type of x, or are we using a two-template-parameter action
|
||||||
|
// where the compiler is asked to infer the type of x?
|
||||||
|
//
|
||||||
|
// Implementation notes:
|
||||||
|
//
|
||||||
|
// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
|
||||||
|
// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
|
||||||
|
// implementing ACTION_TEMPLATE. The main trick we use is to create
|
||||||
|
// new macro invocations when expanding a macro. For example, we have
|
||||||
|
//
|
||||||
|
// #define ACTION_TEMPLATE(name, template_params, value_params)
|
||||||
|
// ... GMOCK_INTERNAL_DECL_##template_params ...
|
||||||
|
//
|
||||||
|
// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
|
||||||
|
// to expand to
|
||||||
|
//
|
||||||
|
// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
|
||||||
|
//
|
||||||
|
// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
|
||||||
|
// preprocessor will continue to expand it to
|
||||||
|
//
|
||||||
|
// ... typename T ...
|
||||||
|
//
|
||||||
|
// This technique conforms to the C++ standard and is portable. It
|
||||||
|
// allows us to implement action templates using O(N) code, where N is
|
||||||
|
// the maximum number of template/value parameters supported. Without
|
||||||
|
// using it, we'd have to devote O(N^2) amount of code to implement all
|
||||||
|
// combinations of m and n.
|
||||||
|
|
||||||
|
// Declares the template parameters.
|
||||||
|
|
||||||
|
$range j 1..n
|
||||||
|
$for j [[
|
||||||
|
$range m 0..j-1
|
||||||
|
#define GMOCK_INTERNAL_DECL_HAS_$j[[]]
|
||||||
|
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Lists the template parameters.
|
||||||
|
|
||||||
|
$for j [[
|
||||||
|
$range m 0..j-1
|
||||||
|
#define GMOCK_INTERNAL_LIST_HAS_$j[[]]
|
||||||
|
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Declares the types of value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Initializes the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\
|
||||||
|
($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(gmock_p$j)]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Declares the fields for storing the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_DEFN_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Lists the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_LIST_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Lists the value parameter types.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]]
|
||||||
|
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Declares the value parameters.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
|
||||||
|
$for j, [[p$j##_type p$j]]
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// The suffix of the class template implementing the action template.
|
||||||
|
$for i [[
|
||||||
|
|
||||||
|
|
||||||
|
$range j 0..i-1
|
||||||
|
#define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
|
||||||
|
$if i==1 [[P]] $elif i>=2 [[P$i]]
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
// The name of the class template implementing the action template.
|
||||||
|
#define GMOCK_ACTION_CLASS_(name, value_params)\
|
||||||
|
GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
|
||||||
|
|
||||||
|
$range k 0..n-1
|
||||||
|
|
||||||
|
#define ACTION_TEMPLATE(name, template_params, value_params)\
|
||||||
|
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||||
|
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||||
|
class GMOCK_ACTION_CLASS_(name, value_params) {\
|
||||||
|
public:\
|
||||||
|
GMOCK_ACTION_CLASS_(name, value_params)\
|
||||||
|
GMOCK_INTERNAL_INIT_##value_params {}\
|
||||||
|
template <typename F>\
|
||||||
|
class gmock_Impl : public ::testing::ActionInterface<F> {\
|
||||||
|
public:\
|
||||||
|
typedef F function_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::Result return_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
|
||||||
|
args_type;\
|
||||||
|
explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
|
||||||
|
virtual return_type Perform(const args_type& args) {\
|
||||||
|
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
|
||||||
|
Perform(this, args);\
|
||||||
|
}\
|
||||||
|
template <$for k, [[typename arg$k[[]]_type]]>\
|
||||||
|
return_type gmock_PerformImpl(const args_type& args[[]]
|
||||||
|
$for k [[, arg$k[[]]_type arg$k]]) const;\
|
||||||
|
GMOCK_INTERNAL_DEFN_##value_params\
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||||
|
};\
|
||||||
|
template <typename F> operator ::testing::Action<F>() const {\
|
||||||
|
return ::testing::Action<F>(\
|
||||||
|
new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
|
||||||
|
}\
|
||||||
|
GMOCK_INTERNAL_DEFN_##value_params\
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
|
||||||
|
};\
|
||||||
|
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||||
|
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||||
|
inline GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||||
|
GMOCK_INTERNAL_LIST_##template_params\
|
||||||
|
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
|
||||||
|
GMOCK_INTERNAL_DECL_##value_params) {\
|
||||||
|
return GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||||
|
GMOCK_INTERNAL_LIST_##template_params\
|
||||||
|
GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
|
||||||
|
GMOCK_INTERNAL_LIST_##value_params);\
|
||||||
|
}\
|
||||||
|
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||||
|
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||||
|
template <typename F>\
|
||||||
|
template <typename arg0_type, typename arg1_type, typename arg2_type, \
|
||||||
|
typename arg3_type, typename arg4_type, typename arg5_type, \
|
||||||
|
typename arg6_type, typename arg7_type, typename arg8_type, \
|
||||||
|
typename arg9_type>\
|
||||||
|
typename ::testing::internal::Function<F>::Result\
|
||||||
|
GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||||
|
GMOCK_INTERNAL_LIST_##template_params\
|
||||||
|
GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
|
||||||
|
gmock_PerformImpl(\
|
||||||
|
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
|
||||||
|
|
||||||
|
$for i
|
||||||
|
|
||||||
|
[[
|
||||||
|
$var template = [[$if i==0 [[]] $else [[
|
||||||
|
$range j 0..i-1
|
||||||
|
|
||||||
|
template <$for j, [[typename p$j##_type]]>\
|
||||||
|
]]]]
|
||||||
|
$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]]
|
||||||
|
$else [[P$i]]]]]]
|
||||||
|
$range j 0..i-1
|
||||||
|
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
|
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
||||||
|
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
||||||
|
$var param_field_decls = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
$var param_field_decls2 = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
$var params = [[$for j, [[p$j]]]]
|
||||||
|
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||||
|
$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]]
|
||||||
|
$var arg_types_and_names = [[$for k, [[arg$k[[]]_type arg$k]]]]
|
||||||
|
$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]]
|
||||||
|
$else [[ACTION_P$i]]]]
|
||||||
|
|
||||||
|
#define $macro_name(name$for j [[, p$j]])\$template
|
||||||
|
class $class_name {\
|
||||||
|
public:\
|
||||||
|
$class_name($ctor_param_list)$inits {}\
|
||||||
|
template <typename F>\
|
||||||
|
class gmock_Impl : public ::testing::ActionInterface<F> {\
|
||||||
|
public:\
|
||||||
|
typedef F function_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::Result return_type;\
|
||||||
|
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
|
||||||
|
args_type;\
|
||||||
|
[[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\
|
||||||
|
virtual return_type Perform(const args_type& args) {\
|
||||||
|
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
|
||||||
|
Perform(this, args);\
|
||||||
|
}\
|
||||||
|
template <$typename_arg_types>\
|
||||||
|
return_type gmock_PerformImpl(const args_type& args, [[]]
|
||||||
|
$arg_types_and_names) const;\$param_field_decls
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||||
|
};\
|
||||||
|
template <typename F> operator ::testing::Action<F>() const {\
|
||||||
|
return ::testing::Action<F>(new gmock_Impl<F>($params));\
|
||||||
|
}\$param_field_decls2
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_($class_name);\
|
||||||
|
};\$template
|
||||||
|
inline $class_name$param_types name($param_types_and_names) {\
|
||||||
|
return $class_name$param_types($params);\
|
||||||
|
}\$template
|
||||||
|
template <typename F>\
|
||||||
|
template <$typename_arg_types>\
|
||||||
|
typename ::testing::internal::Function<F>::Result\
|
||||||
|
$class_name$param_types::gmock_Impl<F>::gmock_PerformImpl(\
|
||||||
|
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
|
||||||
|
]]
|
||||||
|
$$ } // This meta comment fixes auto-indentation in Emacs. It won't
|
||||||
|
$$ // show up in the generated code.
|
||||||
|
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||||
|
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||||
|
// the macro definition, as the warnings are generated when the macro
|
||||||
|
// is expanded and macro expansion cannot contain #pragma. Therefore
|
||||||
|
// we suppress them here.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4100)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Various overloads for InvokeArgument<N>().
|
||||||
|
//
|
||||||
|
// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
|
||||||
|
// (0-based) argument, which must be a k-ary callable, of the mock
|
||||||
|
// function, with arguments a1, a2, ..., a_k.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// 1. The arguments are passed by value by default. If you need to
|
||||||
|
// pass an argument by reference, wrap it inside ByRef(). For
|
||||||
|
// example,
|
||||||
|
//
|
||||||
|
// InvokeArgument<1>(5, string("Hello"), ByRef(foo))
|
||||||
|
//
|
||||||
|
// passes 5 and string("Hello") by value, and passes foo by
|
||||||
|
// reference.
|
||||||
|
//
|
||||||
|
// 2. If the callable takes an argument by reference but ByRef() is
|
||||||
|
// not used, it will receive the reference to a copy of the value,
|
||||||
|
// instead of the original value. For example, when the 0-th
|
||||||
|
// argument of the mock function takes a const string&, the action
|
||||||
|
//
|
||||||
|
// InvokeArgument<0>(string("Hello"))
|
||||||
|
//
|
||||||
|
// makes a copy of the temporary string("Hello") object and passes a
|
||||||
|
// reference of the copy, instead of the original temporary object,
|
||||||
|
// to the callable. This makes it easy for a user to define an
|
||||||
|
// InvokeArgument action from temporary values and have it performed
|
||||||
|
// later.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
|
||||||
|
ACTION_TEMPLATE(InvokeArgument,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) {
|
||||||
|
return internal::CallableHelper<return_type>::Call(
|
||||||
|
::std::tr1::get<k>(args)$for j [[, p$j]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Various overloads for ReturnNew<T>().
|
||||||
|
//
|
||||||
|
// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
|
||||||
|
// instance of type T, constructed on the heap with constructor arguments
|
||||||
|
// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
$var ps = [[$for j, [[p$j]]]]
|
||||||
|
|
||||||
|
ACTION_TEMPLATE(ReturnNew,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(typename, T),
|
||||||
|
AND_$i[[]]_VALUE_PARAMS($ps)) {
|
||||||
|
return new T($ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||||
991
gmock/include/gmock/gmock-generated-function-mockers.h
Normal file
991
gmock/include/gmock/gmock-generated-function-mockers.h
Normal file
@@ -0,0 +1,991 @@
|
|||||||
|
// This file was GENERATED by command:
|
||||||
|
// pump.py gmock-generated-function-mockers.h.pump
|
||||||
|
// DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements function mockers of various arities.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
|
||||||
|
#include "gmock/gmock-spec-builders.h"
|
||||||
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMockerBase;
|
||||||
|
|
||||||
|
// Note: class FunctionMocker really belongs to the ::testing
|
||||||
|
// namespace. However if we define it in ::testing, MSVC will
|
||||||
|
// complain when classes in ::testing::internal declare it as a
|
||||||
|
// friend class template. To workaround this compiler bug, we define
|
||||||
|
// FunctionMocker in ::testing::internal and import it into ::testing.
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMocker;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class FunctionMocker<R()> : public
|
||||||
|
internal::FunctionMockerBase<R()> {
|
||||||
|
public:
|
||||||
|
typedef R F();
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With() {
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke() {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
class FunctionMocker<R(A1)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
class FunctionMocker<R(A1, A2)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3>
|
||||||
|
class FunctionMocker<R(A1, A2, A3)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4,
|
||||||
|
m5));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7, m8));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
|
||||||
|
const Matcher<A9>& m9) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7, m8, m9));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9,
|
||||||
|
typename A10>
|
||||||
|
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> : public
|
||||||
|
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> {
|
||||||
|
public:
|
||||||
|
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
|
||||||
|
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
|
||||||
|
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
|
||||||
|
const Matcher<A9>& m9, const Matcher<A10>& m10) {
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
|
||||||
|
m6, m7, m8, m9, m10));
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9,
|
||||||
|
A10 a10) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9,
|
||||||
|
a10));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// The style guide prohibits "using" statements in a namespace scope
|
||||||
|
// inside a header file. However, the FunctionMocker class template
|
||||||
|
// is meant to be defined in the ::testing namespace. The following
|
||||||
|
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||||
|
// cannot handle it if we define FunctionMocker in ::testing.
|
||||||
|
using internal::FunctionMocker;
|
||||||
|
|
||||||
|
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
|
||||||
|
// We define this as a variadic macro in case F contains unprotected
|
||||||
|
// commas (the same reason that we use variadic macros in other places
|
||||||
|
// in this file).
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_RESULT_(tn, ...) \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::Result
|
||||||
|
|
||||||
|
// The type of argument N of the given function type.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_ARG_(tn, N, ...) \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::Argument##N
|
||||||
|
|
||||||
|
// The matcher type for argument N of the given function type.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MATCHER_(tn, N, ...) \
|
||||||
|
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
|
||||||
|
|
||||||
|
// The variable for mocking the given method.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||||
|
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 0), \
|
||||||
|
this_method_does_not_take_0_arguments); \
|
||||||
|
GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method() constness { \
|
||||||
|
GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(0, constness, Method).With(); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 1), \
|
||||||
|
this_method_does_not_take_1_argument); \
|
||||||
|
GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(1, constness, Method).Invoke(gmock_a1); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
|
||||||
|
GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 2), \
|
||||||
|
this_method_does_not_take_2_arguments); \
|
||||||
|
GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(2, constness, Method).Invoke(gmock_a1, gmock_a2); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \
|
||||||
|
GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 3), \
|
||||||
|
this_method_does_not_take_3_arguments); \
|
||||||
|
GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(3, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \
|
||||||
|
GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 4), \
|
||||||
|
this_method_does_not_take_4_arguments); \
|
||||||
|
GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(4, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
|
||||||
|
GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 5), \
|
||||||
|
this_method_does_not_take_5_arguments); \
|
||||||
|
GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(5, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \
|
||||||
|
GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 6), \
|
||||||
|
this_method_does_not_take_6_arguments); \
|
||||||
|
GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(6, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \
|
||||||
|
GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 7), \
|
||||||
|
this_method_does_not_take_7_arguments); \
|
||||||
|
GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(7, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
|
||||||
|
GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||||
|
GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 8), \
|
||||||
|
this_method_does_not_take_8_arguments); \
|
||||||
|
GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(8, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||||
|
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \
|
||||||
|
GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||||
|
GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||||
|
GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 9), \
|
||||||
|
this_method_does_not_take_9_arguments); \
|
||||||
|
GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(9, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
|
||||||
|
gmock_a9); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||||
|
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||||
|
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \
|
||||||
|
GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
|
||||||
|
gmock_a9); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||||
|
GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||||
|
GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \
|
||||||
|
GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value \
|
||||||
|
== 10), \
|
||||||
|
this_method_does_not_take_10_arguments); \
|
||||||
|
GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_(10, constness, Method).Invoke(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
|
||||||
|
gmock_a10); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||||
|
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||||
|
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||||
|
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||||
|
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||||
|
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||||
|
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||||
|
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||||
|
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \
|
||||||
|
GMOCK_MATCHER_(tn, 10, \
|
||||||
|
__VA_ARGS__) gmock_a10) constness { \
|
||||||
|
GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
|
||||||
|
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
|
||||||
|
gmock_a10); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \
|
||||||
|
Method)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0_T(m, ...) \
|
||||||
|
GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD1_T(m, ...) \
|
||||||
|
GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD2_T(m, ...) \
|
||||||
|
GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD3_T(m, ...) \
|
||||||
|
GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD4_T(m, ...) \
|
||||||
|
GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD5_T(m, ...) \
|
||||||
|
GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD6_T(m, ...) \
|
||||||
|
GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD7_T(m, ...) \
|
||||||
|
GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD8_T(m, ...) \
|
||||||
|
GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD9_T(m, ...) \
|
||||||
|
GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD10_T(m, ...) \
|
||||||
|
GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD0_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD1_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD2_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD3_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD4_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD5_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD6_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD7_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD8_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD9_(, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD10_(, , ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
// A MockFunction<F> class has one mock method whose type is F. It is
|
||||||
|
// useful when you just want your test code to emit some messages and
|
||||||
|
// have Google Mock verify the right messages are sent (and perhaps at
|
||||||
|
// the right times). For example, if you are exercising code:
|
||||||
|
//
|
||||||
|
// Foo(1);
|
||||||
|
// Foo(2);
|
||||||
|
// Foo(3);
|
||||||
|
//
|
||||||
|
// and want to verify that Foo(1) and Foo(3) both invoke
|
||||||
|
// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
|
||||||
|
//
|
||||||
|
// TEST(FooTest, InvokesBarCorrectly) {
|
||||||
|
// MyMock mock;
|
||||||
|
// MockFunction<void(string check_point_name)> check;
|
||||||
|
// {
|
||||||
|
// InSequence s;
|
||||||
|
//
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// EXPECT_CALL(check, Call("1"));
|
||||||
|
// EXPECT_CALL(check, Call("2"));
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// }
|
||||||
|
// Foo(1);
|
||||||
|
// check.Call("1");
|
||||||
|
// Foo(2);
|
||||||
|
// check.Call("2");
|
||||||
|
// Foo(3);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The expectation spec says that the first Bar("a") must happen
|
||||||
|
// before check point "1", the second Bar("a") must happen after check
|
||||||
|
// point "2", and nothing should happen between the two check
|
||||||
|
// points. The explicit check points make it easy to tell which
|
||||||
|
// Bar("a") is called by which call to Foo().
|
||||||
|
template <typename F>
|
||||||
|
class MockFunction;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class MockFunction<R()> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD0_T(Call, R());
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0>
|
||||||
|
class MockFunction<R(A0)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD1_T(Call, R(A0));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1>
|
||||||
|
class MockFunction<R(A0, A1)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD2_T(Call, R(A0, A1));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2>
|
||||||
|
class MockFunction<R(A0, A1, A2)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD3_T(Call, R(A0, A1, A2));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD4_T(Call, R(A0, A1, A2, A3));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6, typename A7>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6, typename A7, typename A8>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A0, typename A1, typename A2, typename A3,
|
||||||
|
typename A4, typename A5, typename A6, typename A7, typename A8,
|
||||||
|
typename A9>
|
||||||
|
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
265
gmock/include/gmock/gmock-generated-function-mockers.h.pump
Normal file
265
gmock/include/gmock/gmock-generated-function-mockers.h.pump
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-function-mockers.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements function mockers of various arities.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
|
||||||
|
#include "gmock/gmock-spec-builders.h"
|
||||||
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMockerBase;
|
||||||
|
|
||||||
|
// Note: class FunctionMocker really belongs to the ::testing
|
||||||
|
// namespace. However if we define it in ::testing, MSVC will
|
||||||
|
// complain when classes in ::testing::internal declare it as a
|
||||||
|
// friend class template. To workaround this compiler bug, we define
|
||||||
|
// FunctionMocker in ::testing::internal and import it into ::testing.
|
||||||
|
template <typename F>
|
||||||
|
class FunctionMocker;
|
||||||
|
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j [[, typename A$j]]]]
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var as = [[$for j, [[a$j]]]]
|
||||||
|
$var Aas = [[$for j, [[A$j a$j]]]]
|
||||||
|
$var ms = [[$for j, [[m$j]]]]
|
||||||
|
$var matchers = [[$for j, [[const Matcher<A$j>& m$j]]]]
|
||||||
|
template <typename R$typename_As>
|
||||||
|
class FunctionMocker<R($As)> : public
|
||||||
|
internal::FunctionMockerBase<R($As)> {
|
||||||
|
public:
|
||||||
|
typedef R F($As);
|
||||||
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
|
MockSpec<F>& With($matchers) {
|
||||||
|
|
||||||
|
$if i >= 1 [[
|
||||||
|
this->current_spec().SetMatchers(::std::tr1::make_tuple($ms));
|
||||||
|
|
||||||
|
]]
|
||||||
|
return this->current_spec();
|
||||||
|
}
|
||||||
|
|
||||||
|
R Invoke($Aas) {
|
||||||
|
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
||||||
|
// by the C++ standard [14.6.4] here, as the base class type is
|
||||||
|
// dependent on the template argument (and thus shouldn't be
|
||||||
|
// looked into when resolving InvokeWith).
|
||||||
|
return this->InvokeWith(ArgumentTuple($as));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// The style guide prohibits "using" statements in a namespace scope
|
||||||
|
// inside a header file. However, the FunctionMocker class template
|
||||||
|
// is meant to be defined in the ::testing namespace. The following
|
||||||
|
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||||
|
// cannot handle it if we define FunctionMocker in ::testing.
|
||||||
|
using internal::FunctionMocker;
|
||||||
|
|
||||||
|
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
|
||||||
|
// We define this as a variadic macro in case F contains unprotected
|
||||||
|
// commas (the same reason that we use variadic macros in other places
|
||||||
|
// in this file).
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_RESULT_(tn, ...) \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::Result
|
||||||
|
|
||||||
|
// The type of argument N of the given function type.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_ARG_(tn, N, ...) \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::Argument##N
|
||||||
|
|
||||||
|
// The matcher type for argument N of the given function type.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MATCHER_(tn, N, ...) \
|
||||||
|
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
|
||||||
|
|
||||||
|
// The variable for mocking the given method.
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||||
|
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var arg_as = [[$for j, \
|
||||||
|
[[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
||||||
|
$var as = [[$for j, [[gmock_a$j]]]]
|
||||||
|
$var matcher_as = [[$for j, \
|
||||||
|
[[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
||||||
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
|
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
|
||||||
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
|
$arg_as) constness { \
|
||||||
|
GTEST_COMPILE_ASSERT_((::std::tr1::tuple_size< \
|
||||||
|
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value == $i), \
|
||||||
|
this_method_does_not_take_$i[[]]_argument[[$if i != 1 [[s]]]]); \
|
||||||
|
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
|
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
|
||||||
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__>& \
|
||||||
|
gmock_##Method($matcher_as) constness { \
|
||||||
|
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
|
||||||
|
return GMOCK_MOCKER_($i, constness, Method).With($as); \
|
||||||
|
} \
|
||||||
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method)
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \
|
||||||
|
GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
|
||||||
|
GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__)
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// A MockFunction<F> class has one mock method whose type is F. It is
|
||||||
|
// useful when you just want your test code to emit some messages and
|
||||||
|
// have Google Mock verify the right messages are sent (and perhaps at
|
||||||
|
// the right times). For example, if you are exercising code:
|
||||||
|
//
|
||||||
|
// Foo(1);
|
||||||
|
// Foo(2);
|
||||||
|
// Foo(3);
|
||||||
|
//
|
||||||
|
// and want to verify that Foo(1) and Foo(3) both invoke
|
||||||
|
// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
|
||||||
|
//
|
||||||
|
// TEST(FooTest, InvokesBarCorrectly) {
|
||||||
|
// MyMock mock;
|
||||||
|
// MockFunction<void(string check_point_name)> check;
|
||||||
|
// {
|
||||||
|
// InSequence s;
|
||||||
|
//
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// EXPECT_CALL(check, Call("1"));
|
||||||
|
// EXPECT_CALL(check, Call("2"));
|
||||||
|
// EXPECT_CALL(mock, Bar("a"));
|
||||||
|
// }
|
||||||
|
// Foo(1);
|
||||||
|
// check.Call("1");
|
||||||
|
// Foo(2);
|
||||||
|
// check.Call("2");
|
||||||
|
// Foo(3);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The expectation spec says that the first Bar("a") must happen
|
||||||
|
// before check point "1", the second Bar("a") must happen after check
|
||||||
|
// point "2", and nothing should happen between the two check
|
||||||
|
// points. The explicit check points make it easy to tell which
|
||||||
|
// Bar("a") is called by which call to Foo().
|
||||||
|
template <typename F>
|
||||||
|
class MockFunction;
|
||||||
|
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$range j 0..i-1
|
||||||
|
template <typename R$for j [[, typename A$j]]>
|
||||||
|
class MockFunction<R($for j, [[A$j]])> {
|
||||||
|
public:
|
||||||
|
MockFunction() {}
|
||||||
|
|
||||||
|
MOCK_METHOD$i[[]]_T(Call, R($for j, [[A$j]]));
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
2190
gmock/include/gmock/gmock-generated-matchers.h
Normal file
2190
gmock/include/gmock/gmock-generated-matchers.h
Normal file
File diff suppressed because it is too large
Load Diff
674
gmock/include/gmock/gmock-generated-matchers.h.pump
Normal file
674
gmock/include/gmock/gmock-generated-matchers.h.pump
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-actions.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
$$ }} This line fixes auto-indentation of the following code in Emacs.
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some commonly used variadic matchers.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "gmock/gmock-matchers.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
$range i 0..n-1
|
||||||
|
|
||||||
|
// The type of the i-th (0-based) field of Tuple.
|
||||||
|
#define GMOCK_FIELD_TYPE_(Tuple, i) \
|
||||||
|
typename ::std::tr1::tuple_element<i, Tuple>::type
|
||||||
|
|
||||||
|
// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
|
||||||
|
// tuple of type Tuple. It has two members:
|
||||||
|
//
|
||||||
|
// type: a tuple type whose i-th field is the ki-th field of Tuple.
|
||||||
|
// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
|
||||||
|
//
|
||||||
|
// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
|
||||||
|
//
|
||||||
|
// type is tuple<int, bool>, and
|
||||||
|
// GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
|
||||||
|
|
||||||
|
template <class Tuple$for i [[, int k$i = -1]]>
|
||||||
|
class TupleFields;
|
||||||
|
|
||||||
|
// This generic version is used when there are $n selectors.
|
||||||
|
template <class Tuple$for i [[, int k$i]]>
|
||||||
|
class TupleFields {
|
||||||
|
public:
|
||||||
|
typedef ::std::tr1::tuple<$for i, [[GMOCK_FIELD_TYPE_(Tuple, k$i)]]> type;
|
||||||
|
static type GetSelectedFields(const Tuple& t) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type($for i, [[get<k$i>(t)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following specialization is used for 0 ~ $(n-1) selectors.
|
||||||
|
|
||||||
|
$for i [[
|
||||||
|
$$ }}}
|
||||||
|
$range j 0..i-1
|
||||||
|
$range k 0..n-1
|
||||||
|
|
||||||
|
template <class Tuple$for j [[, int k$j]]>
|
||||||
|
class TupleFields<Tuple, $for k, [[$if k < i [[k$k]] $else [[-1]]]]> {
|
||||||
|
public:
|
||||||
|
typedef ::std::tr1::tuple<$for j, [[GMOCK_FIELD_TYPE_(Tuple, k$j)]]> type;
|
||||||
|
static type GetSelectedFields(const Tuple& $if i==0 [[/* t */]] $else [[t]]) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type($for j, [[get<k$j>(t)]]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
#undef GMOCK_FIELD_TYPE_
|
||||||
|
|
||||||
|
// Implements the Args() matcher.
|
||||||
|
|
||||||
|
$var ks = [[$for i, [[k$i]]]]
|
||||||
|
template <class ArgsTuple$for i [[, int k$i = -1]]>
|
||||||
|
class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
|
||||||
|
public:
|
||||||
|
// ArgsTuple may have top-level const or reference modifiers.
|
||||||
|
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple;
|
||||||
|
typedef typename internal::TupleFields<RawArgsTuple, $ks>::type SelectedArgs;
|
||||||
|
typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
|
||||||
|
|
||||||
|
template <typename InnerMatcher>
|
||||||
|
explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
|
||||||
|
: inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
|
||||||
|
|
||||||
|
virtual bool MatchAndExplain(ArgsTuple args,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
|
const SelectedArgs& selected_args = GetSelectedArgs(args);
|
||||||
|
if (!listener->IsInterested())
|
||||||
|
return inner_matcher_.Matches(selected_args);
|
||||||
|
|
||||||
|
PrintIndices(listener->stream());
|
||||||
|
*listener << "are " << PrintToString(selected_args);
|
||||||
|
|
||||||
|
StringMatchResultListener inner_listener;
|
||||||
|
const bool match = inner_matcher_.MatchAndExplain(selected_args,
|
||||||
|
&inner_listener);
|
||||||
|
PrintIfNotEmpty(inner_listener.str(), listener->stream());
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const {
|
||||||
|
*os << "are a tuple ";
|
||||||
|
PrintIndices(os);
|
||||||
|
inner_matcher_.DescribeTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||||
|
*os << "are a tuple ";
|
||||||
|
PrintIndices(os);
|
||||||
|
inner_matcher_.DescribeNegationTo(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static SelectedArgs GetSelectedArgs(ArgsTuple args) {
|
||||||
|
return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the indices of the selected fields.
|
||||||
|
static void PrintIndices(::std::ostream* os) {
|
||||||
|
*os << "whose fields (";
|
||||||
|
const int indices[$n] = { $ks };
|
||||||
|
for (int i = 0; i < $n; i++) {
|
||||||
|
if (indices[i] < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i >= 1)
|
||||||
|
*os << ", ";
|
||||||
|
|
||||||
|
*os << "#" << indices[i];
|
||||||
|
}
|
||||||
|
*os << ") ";
|
||||||
|
}
|
||||||
|
|
||||||
|
const MonomorphicInnerMatcher inner_matcher_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class InnerMatcher$for i [[, int k$i = -1]]>
|
||||||
|
class ArgsMatcher {
|
||||||
|
public:
|
||||||
|
explicit ArgsMatcher(const InnerMatcher& inner_matcher)
|
||||||
|
: inner_matcher_(inner_matcher) {}
|
||||||
|
|
||||||
|
template <typename ArgsTuple>
|
||||||
|
operator Matcher<ArgsTuple>() const {
|
||||||
|
return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, $ks>(inner_matcher_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const InnerMatcher inner_matcher_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
|
||||||
|
};
|
||||||
|
|
||||||
|
// A set of metafunctions for computing the result type of AllOf.
|
||||||
|
// AllOf(m1, ..., mN) returns
|
||||||
|
// AllOfResultN<decltype(m1), ..., decltype(mN)>::type.
|
||||||
|
|
||||||
|
// Although AllOf isn't defined for one argument, AllOfResult1 is defined
|
||||||
|
// to simplify the implementation.
|
||||||
|
template <typename M1>
|
||||||
|
struct AllOfResult1 {
|
||||||
|
typedef M1 type;
|
||||||
|
};
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 2..i
|
||||||
|
$var m = i/2
|
||||||
|
$range k 1..m
|
||||||
|
$range t m+1..i
|
||||||
|
|
||||||
|
template <typename M1$for j [[, typename M$j]]>
|
||||||
|
struct AllOfResult$i {
|
||||||
|
typedef BothOfMatcher<
|
||||||
|
typename AllOfResult$m<$for k, [[M$k]]>::type,
|
||||||
|
typename AllOfResult$(i-m)<$for t, [[M$t]]>::type
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// A set of metafunctions for computing the result type of AnyOf.
|
||||||
|
// AnyOf(m1, ..., mN) returns
|
||||||
|
// AnyOfResultN<decltype(m1), ..., decltype(mN)>::type.
|
||||||
|
|
||||||
|
// Although AnyOf isn't defined for one argument, AnyOfResult1 is defined
|
||||||
|
// to simplify the implementation.
|
||||||
|
template <typename M1>
|
||||||
|
struct AnyOfResult1 {
|
||||||
|
typedef M1 type;
|
||||||
|
};
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 2..i
|
||||||
|
$var m = i/2
|
||||||
|
$range k 1..m
|
||||||
|
$range t m+1..i
|
||||||
|
|
||||||
|
template <typename M1$for j [[, typename M$j]]>
|
||||||
|
struct AnyOfResult$i {
|
||||||
|
typedef EitherOfMatcher<
|
||||||
|
typename AnyOfResult$m<$for k, [[M$k]]>::type,
|
||||||
|
typename AnyOfResult$(i-m)<$for t, [[M$t]]>::type
|
||||||
|
> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
|
||||||
|
// fields of it matches a_matcher. C++ doesn't support default
|
||||||
|
// arguments for function templates, so we have to overload it.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j [[int k$j, ]]typename InnerMatcher>
|
||||||
|
inline internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>
|
||||||
|
Args(const InnerMatcher& matcher) {
|
||||||
|
return internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>(matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// ElementsAre(e_1, e_2, ... e_n) matches an STL-style container with
|
||||||
|
// n elements, where the i-th element in the container must
|
||||||
|
// match the i-th argument in the list. Each argument of
|
||||||
|
// ElementsAre() can be either a value or a matcher. We support up to
|
||||||
|
// $n arguments.
|
||||||
|
//
|
||||||
|
// The use of DecayArray in the implementation allows ElementsAre()
|
||||||
|
// to accept string literals, whose type is const char[N], but we
|
||||||
|
// want to treat them as const char*.
|
||||||
|
//
|
||||||
|
// NOTE: Since ElementsAre() cares about the order of the elements, it
|
||||||
|
// must not be used with containers whose elements's order is
|
||||||
|
// undefined (e.g. hash_map).
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
|
||||||
|
$range j 1..i
|
||||||
|
|
||||||
|
$if i>0 [[
|
||||||
|
|
||||||
|
template <$for j, [[typename T$j]]>
|
||||||
|
]]
|
||||||
|
|
||||||
|
inline internal::ElementsAreMatcher<
|
||||||
|
std::tr1::tuple<
|
||||||
|
$for j, [[
|
||||||
|
|
||||||
|
typename internal::DecayArray<T$j[[]]>::type]]> >
|
||||||
|
ElementsAre($for j, [[const T$j& e$j]]) {
|
||||||
|
typedef std::tr1::tuple<
|
||||||
|
$for j, [[
|
||||||
|
|
||||||
|
typename internal::DecayArray<T$j[[]]>::type]]> Args;
|
||||||
|
return internal::ElementsAreMatcher<Args>(Args($for j, [[e$j]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension
|
||||||
|
// that matches n elements in any order. We support up to n=$n arguments.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
|
||||||
|
$range j 1..i
|
||||||
|
|
||||||
|
$if i>0 [[
|
||||||
|
|
||||||
|
template <$for j, [[typename T$j]]>
|
||||||
|
]]
|
||||||
|
|
||||||
|
inline internal::UnorderedElementsAreMatcher<
|
||||||
|
std::tr1::tuple<
|
||||||
|
$for j, [[
|
||||||
|
|
||||||
|
typename internal::DecayArray<T$j[[]]>::type]]> >
|
||||||
|
UnorderedElementsAre($for j, [[const T$j& e$j]]) {
|
||||||
|
typedef std::tr1::tuple<
|
||||||
|
$for j, [[
|
||||||
|
|
||||||
|
typename internal::DecayArray<T$j[[]]>::type]]> Args;
|
||||||
|
return internal::UnorderedElementsAreMatcher<Args>(Args($for j, [[e$j]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// AllOf(m1, m2, ..., mk) matches any value that matches all of the given
|
||||||
|
// sub-matchers. AllOf is called fully qualified to prevent ADL from firing.
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var m = i/2
|
||||||
|
$range k 1..m
|
||||||
|
$range t m+1..i
|
||||||
|
|
||||||
|
template <$for j, [[typename M$j]]>
|
||||||
|
inline typename internal::AllOfResult$i<$for j, [[M$j]]>::type
|
||||||
|
AllOf($for j, [[M$j m$j]]) {
|
||||||
|
return typename internal::AllOfResult$i<$for j, [[M$j]]>::type(
|
||||||
|
$if m == 1 [[m1]] $else [[::testing::AllOf($for k, [[m$k]])]],
|
||||||
|
$if m+1 == i [[m$i]] $else [[::testing::AllOf($for t, [[m$t]])]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given
|
||||||
|
// sub-matchers. AnyOf is called fully qualified to prevent ADL from firing.
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var m = i/2
|
||||||
|
$range k 1..m
|
||||||
|
$range t m+1..i
|
||||||
|
|
||||||
|
template <$for j, [[typename M$j]]>
|
||||||
|
inline typename internal::AnyOfResult$i<$for j, [[M$j]]>::type
|
||||||
|
AnyOf($for j, [[M$j m$j]]) {
|
||||||
|
return typename internal::AnyOfResult$i<$for j, [[M$j]]>::type(
|
||||||
|
$if m == 1 [[m1]] $else [[::testing::AnyOf($for k, [[m$k]])]],
|
||||||
|
$if m+1 == i [[m$i]] $else [[::testing::AnyOf($for t, [[m$t]])]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
$$ } // This Pump meta comment fixes auto-indentation in Emacs. It will not
|
||||||
|
$$ // show up in the generated code.
|
||||||
|
|
||||||
|
|
||||||
|
// The MATCHER* family of macros can be used in a namespace scope to
|
||||||
|
// define custom matchers easily.
|
||||||
|
//
|
||||||
|
// Basic Usage
|
||||||
|
// ===========
|
||||||
|
//
|
||||||
|
// The syntax
|
||||||
|
//
|
||||||
|
// MATCHER(name, description_string) { statements; }
|
||||||
|
//
|
||||||
|
// defines a matcher with the given name that executes the statements,
|
||||||
|
// which must return a bool to indicate if the match succeeds. Inside
|
||||||
|
// the statements, you can refer to the value being matched by 'arg',
|
||||||
|
// and refer to its type by 'arg_type'.
|
||||||
|
//
|
||||||
|
// The description string documents what the matcher does, and is used
|
||||||
|
// to generate the failure message when the match fails. Since a
|
||||||
|
// MATCHER() is usually defined in a header file shared by multiple
|
||||||
|
// C++ source files, we require the description to be a C-string
|
||||||
|
// literal to avoid possible side effects. It can be empty, in which
|
||||||
|
// case we'll use the sequence of words in the matcher name as the
|
||||||
|
// description.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
|
||||||
|
//
|
||||||
|
// allows you to write
|
||||||
|
//
|
||||||
|
// // Expects mock_foo.Bar(n) to be called where n is even.
|
||||||
|
// EXPECT_CALL(mock_foo, Bar(IsEven()));
|
||||||
|
//
|
||||||
|
// or,
|
||||||
|
//
|
||||||
|
// // Verifies that the value of some_expression is even.
|
||||||
|
// EXPECT_THAT(some_expression, IsEven());
|
||||||
|
//
|
||||||
|
// If the above assertion fails, it will print something like:
|
||||||
|
//
|
||||||
|
// Value of: some_expression
|
||||||
|
// Expected: is even
|
||||||
|
// Actual: 7
|
||||||
|
//
|
||||||
|
// where the description "is even" is automatically calculated from the
|
||||||
|
// matcher name IsEven.
|
||||||
|
//
|
||||||
|
// Argument Type
|
||||||
|
// =============
|
||||||
|
//
|
||||||
|
// Note that the type of the value being matched (arg_type) is
|
||||||
|
// determined by the context in which you use the matcher and is
|
||||||
|
// supplied to you by the compiler, so you don't need to worry about
|
||||||
|
// declaring it (nor can you). This allows the matcher to be
|
||||||
|
// polymorphic. For example, IsEven() can be used to match any type
|
||||||
|
// where the value of "(arg % 2) == 0" can be implicitly converted to
|
||||||
|
// a bool. In the "Bar(IsEven())" example above, if method Bar()
|
||||||
|
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
|
||||||
|
// 'arg_type' will be unsigned long; and so on.
|
||||||
|
//
|
||||||
|
// Parameterizing Matchers
|
||||||
|
// =======================
|
||||||
|
//
|
||||||
|
// Sometimes you'll want to parameterize the matcher. For that you
|
||||||
|
// can use another macro:
|
||||||
|
//
|
||||||
|
// MATCHER_P(name, param_name, description_string) { statements; }
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
|
||||||
|
//
|
||||||
|
// will allow you to write:
|
||||||
|
//
|
||||||
|
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
|
||||||
|
//
|
||||||
|
// which may lead to this message (assuming n is 10):
|
||||||
|
//
|
||||||
|
// Value of: Blah("a")
|
||||||
|
// Expected: has absolute value 10
|
||||||
|
// Actual: -9
|
||||||
|
//
|
||||||
|
// Note that both the matcher description and its parameter are
|
||||||
|
// printed, making the message human-friendly.
|
||||||
|
//
|
||||||
|
// In the matcher definition body, you can write 'foo_type' to
|
||||||
|
// reference the type of a parameter named 'foo'. For example, in the
|
||||||
|
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
|
||||||
|
// 'value_type' to refer to the type of 'value'.
|
||||||
|
//
|
||||||
|
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
|
||||||
|
// support multi-parameter matchers.
|
||||||
|
//
|
||||||
|
// Describing Parameterized Matchers
|
||||||
|
// =================================
|
||||||
|
//
|
||||||
|
// The last argument to MATCHER*() is a string-typed expression. The
|
||||||
|
// expression can reference all of the matcher's parameters and a
|
||||||
|
// special bool-typed variable named 'negation'. When 'negation' is
|
||||||
|
// false, the expression should evaluate to the matcher's description;
|
||||||
|
// otherwise it should evaluate to the description of the negation of
|
||||||
|
// the matcher. For example,
|
||||||
|
//
|
||||||
|
// using testing::PrintToString;
|
||||||
|
//
|
||||||
|
// MATCHER_P2(InClosedRange, low, hi,
|
||||||
|
// string(negation ? "is not" : "is") + " in range [" +
|
||||||
|
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
|
||||||
|
// return low <= arg && arg <= hi;
|
||||||
|
// }
|
||||||
|
// ...
|
||||||
|
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||||
|
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||||
|
//
|
||||||
|
// would generate two failures that contain the text:
|
||||||
|
//
|
||||||
|
// Expected: is in range [4, 6]
|
||||||
|
// ...
|
||||||
|
// Expected: is not in range [2, 4]
|
||||||
|
//
|
||||||
|
// If you specify "" as the description, the failure message will
|
||||||
|
// contain the sequence of words in the matcher name followed by the
|
||||||
|
// parameter values printed as a tuple. For example,
|
||||||
|
//
|
||||||
|
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
|
||||||
|
// ...
|
||||||
|
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||||
|
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||||
|
//
|
||||||
|
// would generate two failures that contain the text:
|
||||||
|
//
|
||||||
|
// Expected: in closed range (4, 6)
|
||||||
|
// ...
|
||||||
|
// Expected: not (in closed range (2, 4))
|
||||||
|
//
|
||||||
|
// Types of Matcher Parameters
|
||||||
|
// ===========================
|
||||||
|
//
|
||||||
|
// For the purpose of typing, you can view
|
||||||
|
//
|
||||||
|
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
|
||||||
|
//
|
||||||
|
// as shorthand for
|
||||||
|
//
|
||||||
|
// template <typename p1_type, ..., typename pk_type>
|
||||||
|
// FooMatcherPk<p1_type, ..., pk_type>
|
||||||
|
// Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||||
|
//
|
||||||
|
// When you write Foo(v1, ..., vk), the compiler infers the types of
|
||||||
|
// the parameters v1, ..., and vk for you. If you are not happy with
|
||||||
|
// the result of the type inference, you can specify the types by
|
||||||
|
// explicitly instantiating the template, as in Foo<long, bool>(5,
|
||||||
|
// false). As said earlier, you don't get to (or need to) specify
|
||||||
|
// 'arg_type' as that's determined by the context in which the matcher
|
||||||
|
// is used. You can assign the result of expression Foo(p1, ..., pk)
|
||||||
|
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
|
||||||
|
// can be useful when composing matchers.
|
||||||
|
//
|
||||||
|
// While you can instantiate a matcher template with reference types,
|
||||||
|
// passing the parameters by pointer usually makes your code more
|
||||||
|
// readable. If, however, you still want to pass a parameter by
|
||||||
|
// reference, be aware that in the failure message generated by the
|
||||||
|
// matcher you will see the value of the referenced object but not its
|
||||||
|
// address.
|
||||||
|
//
|
||||||
|
// Explaining Match Results
|
||||||
|
// ========================
|
||||||
|
//
|
||||||
|
// Sometimes the matcher description alone isn't enough to explain why
|
||||||
|
// the match has failed or succeeded. For example, when expecting a
|
||||||
|
// long string, it can be very helpful to also print the diff between
|
||||||
|
// the expected string and the actual one. To achieve that, you can
|
||||||
|
// optionally stream additional information to a special variable
|
||||||
|
// named result_listener, whose type is a pointer to class
|
||||||
|
// MatchResultListener:
|
||||||
|
//
|
||||||
|
// MATCHER_P(EqualsLongString, str, "") {
|
||||||
|
// if (arg == str) return true;
|
||||||
|
//
|
||||||
|
// *result_listener << "the difference: "
|
||||||
|
/// << DiffStrings(str, arg);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Overloading Matchers
|
||||||
|
// ====================
|
||||||
|
//
|
||||||
|
// You can overload matchers with different numbers of parameters:
|
||||||
|
//
|
||||||
|
// MATCHER_P(Blah, a, description_string1) { ... }
|
||||||
|
// MATCHER_P2(Blah, a, b, description_string2) { ... }
|
||||||
|
//
|
||||||
|
// Caveats
|
||||||
|
// =======
|
||||||
|
//
|
||||||
|
// When defining a new matcher, you should also consider implementing
|
||||||
|
// MatcherInterface or using MakePolymorphicMatcher(). These
|
||||||
|
// approaches require more work than the MATCHER* macros, but also
|
||||||
|
// give you more control on the types of the value being matched and
|
||||||
|
// the matcher parameters, which may leads to better compiler error
|
||||||
|
// messages when the matcher is used wrong. They also allow
|
||||||
|
// overloading matchers based on parameter types (as opposed to just
|
||||||
|
// based on the number of parameters).
|
||||||
|
//
|
||||||
|
// MATCHER*() can only be used in a namespace scope. The reason is
|
||||||
|
// that C++ doesn't yet allow function-local types to be used to
|
||||||
|
// instantiate templates. The up-coming C++0x standard will fix this.
|
||||||
|
// Once that's done, we'll consider supporting using MATCHER*() inside
|
||||||
|
// a function.
|
||||||
|
//
|
||||||
|
// More Information
|
||||||
|
// ================
|
||||||
|
//
|
||||||
|
// To learn more about using these macros, please search for 'MATCHER'
|
||||||
|
// on http://code.google.com/p/googlemock/wiki/CookBook.
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i
|
||||||
|
|
||||||
|
[[
|
||||||
|
$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]]
|
||||||
|
$else [[MATCHER_P$i]]]]
|
||||||
|
$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]]
|
||||||
|
$else [[P$i]]]]]]
|
||||||
|
$range j 0..i-1
|
||||||
|
$var template = [[$if i==0 [[]] $else [[
|
||||||
|
|
||||||
|
template <$for j, [[typename p$j##_type]]>\
|
||||||
|
]]]]
|
||||||
|
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
|
$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
|
$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
||||||
|
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
||||||
|
$var params = [[$for j, [[p$j]]]]
|
||||||
|
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||||
|
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
||||||
|
$var param_field_decls = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
$var param_field_decls2 = [[$for j
|
||||||
|
[[
|
||||||
|
|
||||||
|
p$j##_type p$j;\
|
||||||
|
]]]]
|
||||||
|
|
||||||
|
#define $macro_name(name$for j [[, p$j]], description)\$template
|
||||||
|
class $class_name {\
|
||||||
|
public:\
|
||||||
|
template <typename arg_type>\
|
||||||
|
class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
|
||||||
|
public:\
|
||||||
|
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
|
||||||
|
$impl_inits {}\
|
||||||
|
virtual bool MatchAndExplain(\
|
||||||
|
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
|
||||||
|
virtual void DescribeTo(::std::ostream* gmock_os) const {\
|
||||||
|
*gmock_os << FormatDescription(false);\
|
||||||
|
}\
|
||||||
|
virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
|
||||||
|
*gmock_os << FormatDescription(true);\
|
||||||
|
}\$param_field_decls
|
||||||
|
private:\
|
||||||
|
::testing::internal::string FormatDescription(bool negation) const {\
|
||||||
|
const ::testing::internal::string gmock_description = (description);\
|
||||||
|
if (!gmock_description.empty())\
|
||||||
|
return gmock_description;\
|
||||||
|
return ::testing::internal::FormatMatcherDescription(\
|
||||||
|
negation, #name, \
|
||||||
|
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||||
|
::std::tr1::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
|
||||||
|
}\
|
||||||
|
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||||
|
};\
|
||||||
|
template <typename arg_type>\
|
||||||
|
operator ::testing::Matcher<arg_type>() const {\
|
||||||
|
return ::testing::Matcher<arg_type>(\
|
||||||
|
new gmock_Impl<arg_type>($params));\
|
||||||
|
}\
|
||||||
|
$class_name($ctor_param_list)$inits {\
|
||||||
|
}\$param_field_decls2
|
||||||
|
private:\
|
||||||
|
GTEST_DISALLOW_ASSIGN_($class_name);\
|
||||||
|
};\$template
|
||||||
|
inline $class_name$param_types name($param_types_and_names) {\
|
||||||
|
return $class_name$param_types($params);\
|
||||||
|
}\$template
|
||||||
|
template <typename arg_type>\
|
||||||
|
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||||
|
arg_type arg, \
|
||||||
|
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||||
|
const
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||||
397
gmock/include/gmock/gmock-generated-nice-strict.h
Normal file
397
gmock/include/gmock/gmock-generated-nice-strict.h
Normal file
@@ -0,0 +1,397 @@
|
|||||||
|
// This file was GENERATED by command:
|
||||||
|
// pump.py gmock-generated-nice-strict.h.pump
|
||||||
|
// DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Implements class templates NiceMock, NaggyMock, and StrictMock.
|
||||||
|
//
|
||||||
|
// Given a mock class MockFoo that is created using Google Mock,
|
||||||
|
// NiceMock<MockFoo> is a subclass of MockFoo that allows
|
||||||
|
// uninteresting calls (i.e. calls to mock methods that have no
|
||||||
|
// EXPECT_CALL specs), NaggyMock<MockFoo> is a subclass of MockFoo
|
||||||
|
// that prints a warning when an uninteresting call occurs, and
|
||||||
|
// StrictMock<MockFoo> is a subclass of MockFoo that treats all
|
||||||
|
// uninteresting calls as errors.
|
||||||
|
//
|
||||||
|
// Currently a mock is naggy by default, so MockFoo and
|
||||||
|
// NaggyMock<MockFoo> behave like the same. However, we will soon
|
||||||
|
// switch the default behavior of mocks to be nice, as that in general
|
||||||
|
// leads to more maintainable tests. When that happens, MockFoo will
|
||||||
|
// stop behaving like NaggyMock<MockFoo> and start behaving like
|
||||||
|
// NiceMock<MockFoo>.
|
||||||
|
//
|
||||||
|
// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
|
||||||
|
// their respective base class, with up-to 10 arguments. Therefore
|
||||||
|
// you can write NiceMock<MockFoo>(5, "a") to construct a nice mock
|
||||||
|
// where MockFoo has a constructor that accepts (int, const char*),
|
||||||
|
// for example.
|
||||||
|
//
|
||||||
|
// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
|
||||||
|
// and StrictMock<MockFoo> only works for mock methods defined using
|
||||||
|
// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.
|
||||||
|
// If a mock method is defined in a base class of MockFoo, the "nice"
|
||||||
|
// or "strict" modifier may not affect it, depending on the compiler.
|
||||||
|
// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
|
||||||
|
// supported.
|
||||||
|
//
|
||||||
|
// Another known limitation is that the constructors of the base mock
|
||||||
|
// cannot have arguments passed by non-const reference, which are
|
||||||
|
// banned by the Google C++ style guide anyway.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
|
||||||
|
#include "gmock/gmock-spec-builders.h"
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class NiceMock : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
NiceMock() {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++ doesn't (yet) allow inheritance of constructors, so we have
|
||||||
|
// to define it for each arity.
|
||||||
|
template <typename A1>
|
||||||
|
explicit NiceMock(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3,
|
||||||
|
const A4& a4) : MockClass(a1, a2, a3, a4) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
|
||||||
|
a6, a7) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
|
||||||
|
a2, a3, a4, a5, a6, a7, a8) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8,
|
||||||
|
const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9, typename A10>
|
||||||
|
NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
|
||||||
|
const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~NiceMock() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class NaggyMock : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
NaggyMock() {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++ doesn't (yet) allow inheritance of constructors, so we have
|
||||||
|
// to define it for each arity.
|
||||||
|
template <typename A1>
|
||||||
|
explicit NaggyMock(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3,
|
||||||
|
const A4& a4) : MockClass(a1, a2, a3, a4) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
|
||||||
|
a6, a7) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
|
||||||
|
a2, a3, a4, a5, a6, a7, a8) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8,
|
||||||
|
const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9, typename A10>
|
||||||
|
NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
|
||||||
|
const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~NaggyMock() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(NaggyMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class StrictMock : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
StrictMock() {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++ doesn't (yet) allow inheritance of constructors, so we have
|
||||||
|
// to define it for each arity.
|
||||||
|
template <typename A1>
|
||||||
|
explicit StrictMock(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3,
|
||||||
|
const A4& a4) : MockClass(a1, a2, a3, a4) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
|
||||||
|
a6, a7) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
|
||||||
|
a2, a3, a4, a5, a6, a7, a8) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8,
|
||||||
|
const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9, typename A10>
|
||||||
|
StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
|
||||||
|
const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
|
||||||
|
const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~StrictMock() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following specializations catch some (relatively more common)
|
||||||
|
// user errors of nesting nice and strict mocks. They do NOT catch
|
||||||
|
// all possible errors.
|
||||||
|
|
||||||
|
// These specializations are declared but not defined, as NiceMock,
|
||||||
|
// NaggyMock, and StrictMock cannot be nested.
|
||||||
|
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<NaggyMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
template <typename MockClass>
|
||||||
|
class NaggyMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NaggyMock<NaggyMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NaggyMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<NaggyMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
161
gmock/include/gmock/gmock-generated-nice-strict.h.pump
Normal file
161
gmock/include/gmock/gmock-generated-nice-strict.h.pump
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-nice-strict.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Implements class templates NiceMock, NaggyMock, and StrictMock.
|
||||||
|
//
|
||||||
|
// Given a mock class MockFoo that is created using Google Mock,
|
||||||
|
// NiceMock<MockFoo> is a subclass of MockFoo that allows
|
||||||
|
// uninteresting calls (i.e. calls to mock methods that have no
|
||||||
|
// EXPECT_CALL specs), NaggyMock<MockFoo> is a subclass of MockFoo
|
||||||
|
// that prints a warning when an uninteresting call occurs, and
|
||||||
|
// StrictMock<MockFoo> is a subclass of MockFoo that treats all
|
||||||
|
// uninteresting calls as errors.
|
||||||
|
//
|
||||||
|
// Currently a mock is naggy by default, so MockFoo and
|
||||||
|
// NaggyMock<MockFoo> behave like the same. However, we will soon
|
||||||
|
// switch the default behavior of mocks to be nice, as that in general
|
||||||
|
// leads to more maintainable tests. When that happens, MockFoo will
|
||||||
|
// stop behaving like NaggyMock<MockFoo> and start behaving like
|
||||||
|
// NiceMock<MockFoo>.
|
||||||
|
//
|
||||||
|
// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
|
||||||
|
// their respective base class, with up-to $n arguments. Therefore
|
||||||
|
// you can write NiceMock<MockFoo>(5, "a") to construct a nice mock
|
||||||
|
// where MockFoo has a constructor that accepts (int, const char*),
|
||||||
|
// for example.
|
||||||
|
//
|
||||||
|
// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
|
||||||
|
// and StrictMock<MockFoo> only works for mock methods defined using
|
||||||
|
// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.
|
||||||
|
// If a mock method is defined in a base class of MockFoo, the "nice"
|
||||||
|
// or "strict" modifier may not affect it, depending on the compiler.
|
||||||
|
// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
|
||||||
|
// supported.
|
||||||
|
//
|
||||||
|
// Another known limitation is that the constructors of the base mock
|
||||||
|
// cannot have arguments passed by non-const reference, which are
|
||||||
|
// banned by the Google C++ style guide anyway.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
|
|
||||||
|
#include "gmock/gmock-spec-builders.h"
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
$range kind 0..2
|
||||||
|
$for kind [[
|
||||||
|
|
||||||
|
$var clazz=[[$if kind==0 [[NiceMock]]
|
||||||
|
$elif kind==1 [[NaggyMock]]
|
||||||
|
$else [[StrictMock]]]]
|
||||||
|
|
||||||
|
$var method=[[$if kind==0 [[AllowUninterestingCalls]]
|
||||||
|
$elif kind==1 [[WarnUninterestingCalls]]
|
||||||
|
$else [[FailUninterestingCalls]]]]
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class $clazz : public MockClass {
|
||||||
|
public:
|
||||||
|
// We don't factor out the constructor body to a common method, as
|
||||||
|
// we have to avoid a possible clash with members of MockClass.
|
||||||
|
$clazz() {
|
||||||
|
::testing::Mock::$method(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++ doesn't (yet) allow inheritance of constructors, so we have
|
||||||
|
// to define it for each arity.
|
||||||
|
template <typename A1>
|
||||||
|
explicit $clazz(const A1& a1) : MockClass(a1) {
|
||||||
|
::testing::Mock::$method(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
$range i 2..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
template <$for j, [[typename A$j]]>
|
||||||
|
$clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {
|
||||||
|
::testing::Mock::$method(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
virtual ~$clazz() {
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz);
|
||||||
|
};
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
// The following specializations catch some (relatively more common)
|
||||||
|
// user errors of nesting nice and strict mocks. They do NOT catch
|
||||||
|
// all possible errors.
|
||||||
|
|
||||||
|
// These specializations are declared but not defined, as NiceMock,
|
||||||
|
// NaggyMock, and StrictMock cannot be nested.
|
||||||
|
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<NaggyMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NiceMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
template <typename MockClass>
|
||||||
|
class NaggyMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NaggyMock<NaggyMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class NaggyMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<NiceMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<NaggyMock<MockClass> >;
|
||||||
|
template <typename MockClass>
|
||||||
|
class StrictMock<StrictMock<MockClass> >;
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
||||||
3986
gmock/include/gmock/gmock-matchers.h
Normal file
3986
gmock/include/gmock/gmock-matchers.h
Normal file
File diff suppressed because it is too large
Load Diff
233
gmock/include/gmock/gmock-more-actions.h
Normal file
233
gmock/include/gmock/gmock-more-actions.h
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some actions that depend on gmock-generated-actions.h.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "gmock/gmock-generated-actions.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Implements the Invoke(f) action. The template argument
|
||||||
|
// FunctionImpl is the implementation type of f, which can be either a
|
||||||
|
// function pointer or a functor. Invoke(f) can be used as an
|
||||||
|
// Action<F> as long as f's type is compatible with F (i.e. f can be
|
||||||
|
// assigned to a tr1::function<F>).
|
||||||
|
template <typename FunctionImpl>
|
||||||
|
class InvokeAction {
|
||||||
|
public:
|
||||||
|
// The c'tor makes a copy of function_impl (either a function
|
||||||
|
// pointer or a functor).
|
||||||
|
explicit InvokeAction(FunctionImpl function_impl)
|
||||||
|
: function_impl_(function_impl) {}
|
||||||
|
|
||||||
|
template <typename Result, typename ArgumentTuple>
|
||||||
|
Result Perform(const ArgumentTuple& args) {
|
||||||
|
return InvokeHelper<Result, ArgumentTuple>::Invoke(function_impl_, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionImpl function_impl_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(InvokeAction);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implements the Invoke(object_ptr, &Class::Method) action.
|
||||||
|
template <class Class, typename MethodPtr>
|
||||||
|
class InvokeMethodAction {
|
||||||
|
public:
|
||||||
|
InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr)
|
||||||
|
: obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
|
||||||
|
|
||||||
|
template <typename Result, typename ArgumentTuple>
|
||||||
|
Result Perform(const ArgumentTuple& args) const {
|
||||||
|
return InvokeHelper<Result, ArgumentTuple>::InvokeMethod(
|
||||||
|
obj_ptr_, method_ptr_, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Class* const obj_ptr_;
|
||||||
|
const MethodPtr method_ptr_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(InvokeMethodAction);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Various overloads for Invoke().
|
||||||
|
|
||||||
|
// Creates an action that invokes 'function_impl' with the mock
|
||||||
|
// function's arguments.
|
||||||
|
template <typename FunctionImpl>
|
||||||
|
PolymorphicAction<internal::InvokeAction<FunctionImpl> > Invoke(
|
||||||
|
FunctionImpl function_impl) {
|
||||||
|
return MakePolymorphicAction(
|
||||||
|
internal::InvokeAction<FunctionImpl>(function_impl));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an action that invokes the given method on the given object
|
||||||
|
// with the mock function's arguments.
|
||||||
|
template <class Class, typename MethodPtr>
|
||||||
|
PolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
|
||||||
|
Class* obj_ptr, MethodPtr method_ptr) {
|
||||||
|
return MakePolymorphicAction(
|
||||||
|
internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutArgs(inner_action) can be used in a mock function with a
|
||||||
|
// non-empty argument list to perform inner_action, which takes no
|
||||||
|
// argument. In other words, it adapts an action accepting no
|
||||||
|
// argument to one that accepts (and ignores) arguments.
|
||||||
|
template <typename InnerAction>
|
||||||
|
inline internal::WithArgsAction<InnerAction>
|
||||||
|
WithoutArgs(const InnerAction& action) {
|
||||||
|
return internal::WithArgsAction<InnerAction>(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithArg<k>(an_action) creates an action that passes the k-th
|
||||||
|
// (0-based) argument of the mock function to an_action and performs
|
||||||
|
// it. It adapts an action accepting one argument to one that accepts
|
||||||
|
// multiple arguments. For convenience, we also provide
|
||||||
|
// WithArgs<k>(an_action) (defined below) as a synonym.
|
||||||
|
template <int k, typename InnerAction>
|
||||||
|
inline internal::WithArgsAction<InnerAction, k>
|
||||||
|
WithArg(const InnerAction& action) {
|
||||||
|
return internal::WithArgsAction<InnerAction, k>(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||||
|
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||||
|
// the macro definition, as the warnings are generated when the macro
|
||||||
|
// is expanded and macro expansion cannot contain #pragma. Therefore
|
||||||
|
// we suppress them here.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4100)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Action ReturnArg<k>() returns the k-th argument of the mock function.
|
||||||
|
ACTION_TEMPLATE(ReturnArg,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_0_VALUE_PARAMS()) {
|
||||||
|
return std::tr1::get<k>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
|
||||||
|
// mock function to *pointer.
|
||||||
|
ACTION_TEMPLATE(SaveArg,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_1_VALUE_PARAMS(pointer)) {
|
||||||
|
*pointer = ::std::tr1::get<k>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action SaveArgPointee<k>(pointer) saves the value pointed to
|
||||||
|
// by the k-th (0-based) argument of the mock function to *pointer.
|
||||||
|
ACTION_TEMPLATE(SaveArgPointee,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_1_VALUE_PARAMS(pointer)) {
|
||||||
|
*pointer = *::std::tr1::get<k>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action SetArgReferee<k>(value) assigns 'value' to the variable
|
||||||
|
// referenced by the k-th (0-based) argument of the mock function.
|
||||||
|
ACTION_TEMPLATE(SetArgReferee,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_1_VALUE_PARAMS(value)) {
|
||||||
|
typedef typename ::std::tr1::tuple_element<k, args_type>::type argk_type;
|
||||||
|
// Ensures that argument #k is a reference. If you get a compiler
|
||||||
|
// error on the next line, you are using SetArgReferee<k>(value) in
|
||||||
|
// a mock function whose k-th (0-based) argument is not a reference.
|
||||||
|
GTEST_COMPILE_ASSERT_(internal::is_reference<argk_type>::value,
|
||||||
|
SetArgReferee_must_be_used_with_a_reference_argument);
|
||||||
|
::std::tr1::get<k>(args) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action SetArrayArgument<k>(first, last) copies the elements in
|
||||||
|
// source range [first, last) to the array pointed to by the k-th
|
||||||
|
// (0-based) argument, which can be either a pointer or an
|
||||||
|
// iterator. The action does not take ownership of the elements in the
|
||||||
|
// source range.
|
||||||
|
ACTION_TEMPLATE(SetArrayArgument,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_2_VALUE_PARAMS(first, last)) {
|
||||||
|
// Microsoft compiler deprecates ::std::copy, so we want to suppress warning
|
||||||
|
// 4996 (Function call with parameters that may be unsafe) there.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4996) // Temporarily disables warning 4996.
|
||||||
|
#endif
|
||||||
|
::std::copy(first, last, ::std::tr1::get<k>(args));
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
|
||||||
|
// function.
|
||||||
|
ACTION_TEMPLATE(DeleteArg,
|
||||||
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
|
AND_0_VALUE_PARAMS()) {
|
||||||
|
delete ::std::tr1::get<k>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This action returns the value pointed to by 'pointer'.
|
||||||
|
ACTION_P(ReturnPointee, pointer) { return *pointer; }
|
||||||
|
|
||||||
|
// Action Throw(exception) can be used in a mock function of any type
|
||||||
|
// to throw the given exception. Any copyable value can be thrown.
|
||||||
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
// Suppresses the 'unreachable code' warning that VC generates in opt modes.
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4702) // Temporarily disables warning 4702.
|
||||||
|
# endif
|
||||||
|
ACTION_P(Throw, exception) { throw exception; }
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||||
58
gmock/include/gmock/gmock-more-matchers.h
Normal file
58
gmock/include/gmock/gmock-more-matchers.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2013, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: marcus.boerger@google.com (Marcus Boerger)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements some matchers that depend on gmock-generated-matchers.h.
|
||||||
|
//
|
||||||
|
// Note that tests are implemented in gmock-matchers_test.cc rather than
|
||||||
|
// gmock-more-matchers-test.cc.
|
||||||
|
|
||||||
|
#ifndef GMOCK_GMOCK_MORE_MATCHERS_H_
|
||||||
|
#define GMOCK_GMOCK_MORE_MATCHERS_H_
|
||||||
|
|
||||||
|
#include "gmock/gmock-generated-matchers.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Defines a matcher that matches an empty container. The container must
|
||||||
|
// support both size() and empty(), which all STL-like containers provide.
|
||||||
|
MATCHER(IsEmpty, negation ? "isn't empty" : "is empty") {
|
||||||
|
if (arg.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*result_listener << "whose size is " << arg.size();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_GMOCK_MORE_MATCHERS_H_
|
||||||
1791
gmock/include/gmock/gmock-spec-builders.h
Normal file
1791
gmock/include/gmock/gmock-spec-builders.h
Normal file
File diff suppressed because it is too large
Load Diff
94
gmock/include/gmock/gmock.h
Normal file
94
gmock/include/gmock/gmock.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This is the main header file a user should include.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
||||||
|
|
||||||
|
// This file implements the following syntax:
|
||||||
|
//
|
||||||
|
// ON_CALL(mock_object.Method(...))
|
||||||
|
// .With(...) ?
|
||||||
|
// .WillByDefault(...);
|
||||||
|
//
|
||||||
|
// where With() is optional and WillByDefault() must appear exactly
|
||||||
|
// once.
|
||||||
|
//
|
||||||
|
// EXPECT_CALL(mock_object.Method(...))
|
||||||
|
// .With(...) ?
|
||||||
|
// .Times(...) ?
|
||||||
|
// .InSequence(...) *
|
||||||
|
// .WillOnce(...) *
|
||||||
|
// .WillRepeatedly(...) ?
|
||||||
|
// .RetiresOnSaturation() ? ;
|
||||||
|
//
|
||||||
|
// where all clauses are optional and WillOnce() can be repeated.
|
||||||
|
|
||||||
|
#include "gmock/gmock-actions.h"
|
||||||
|
#include "gmock/gmock-cardinalities.h"
|
||||||
|
#include "gmock/gmock-generated-actions.h"
|
||||||
|
#include "gmock/gmock-generated-function-mockers.h"
|
||||||
|
#include "gmock/gmock-generated-nice-strict.h"
|
||||||
|
#include "gmock/gmock-generated-matchers.h"
|
||||||
|
#include "gmock/gmock-matchers.h"
|
||||||
|
#include "gmock/gmock-more-actions.h"
|
||||||
|
#include "gmock/gmock-more-matchers.h"
|
||||||
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Declares Google Mock flags that we want a user to use programmatically.
|
||||||
|
GMOCK_DECLARE_bool_(catch_leaked_mocks);
|
||||||
|
GMOCK_DECLARE_string_(verbose);
|
||||||
|
|
||||||
|
// Initializes Google Mock. This must be called before running the
|
||||||
|
// tests. In particular, it parses the command line for the flags
|
||||||
|
// that Google Mock recognizes. Whenever a Google Mock flag is seen,
|
||||||
|
// it is removed from argv, and *argc is decremented.
|
||||||
|
//
|
||||||
|
// No value is returned. Instead, the Google Mock flag variables are
|
||||||
|
// updated.
|
||||||
|
//
|
||||||
|
// Since Google Test is needed for Google Mock to work, this function
|
||||||
|
// also initializes Google Test and parses its flags, if that hasn't
|
||||||
|
// been done.
|
||||||
|
GTEST_API_ void InitGoogleMock(int* argc, char** argv);
|
||||||
|
|
||||||
|
// This overloaded version can be used in Windows programs compiled in
|
||||||
|
// UNICODE mode.
|
||||||
|
GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv);
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
||||||
279
gmock/include/gmock/internal/gmock-generated-internal-utils.h
Normal file
279
gmock/include/gmock/internal/gmock-generated-internal-utils.h
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
// This file was GENERATED by command:
|
||||||
|
// pump.py gmock-generated-internal-utils.h.pump
|
||||||
|
// DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file contains template meta-programming utility classes needed
|
||||||
|
// for implementing Google Mock.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Matcher;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||||
|
// This is used in implementing the IgnoreResult(a) action.
|
||||||
|
class IgnoredValue {
|
||||||
|
public:
|
||||||
|
// This constructor template allows any value to be implicitly
|
||||||
|
// converted to IgnoredValue. The object has no data member and
|
||||||
|
// doesn't try to remember anything about the argument. We
|
||||||
|
// deliberately omit the 'explicit' keyword in order to allow the
|
||||||
|
// conversion to be implicit.
|
||||||
|
template <typename T>
|
||||||
|
IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit)
|
||||||
|
};
|
||||||
|
|
||||||
|
// MatcherTuple<T>::type is a tuple type where each field is a Matcher
|
||||||
|
// for the corresponding field in tuple type T.
|
||||||
|
template <typename Tuple>
|
||||||
|
struct MatcherTuple;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<> > {
|
||||||
|
typedef ::std::tr1::tuple< > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>,
|
||||||
|
Matcher<A4> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename A3, typename A4, typename A5,
|
||||||
|
typename A6, typename A7, typename A8, typename A9, typename A10>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
|
||||||
|
A10> > {
|
||||||
|
typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
|
||||||
|
Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9>,
|
||||||
|
Matcher<A10> > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Template struct Function<F>, where F must be a function type, contains
|
||||||
|
// the following typedefs:
|
||||||
|
//
|
||||||
|
// Result: the function's return type.
|
||||||
|
// ArgumentN: the type of the N-th argument, where N starts with 1.
|
||||||
|
// ArgumentTuple: the tuple type consisting of all parameters of F.
|
||||||
|
// ArgumentMatcherTuple: the tuple type consisting of Matchers for all
|
||||||
|
// parameters of F.
|
||||||
|
// MakeResultVoid: the function type obtained by substituting void
|
||||||
|
// for the return type of F.
|
||||||
|
// MakeResultIgnoredValue:
|
||||||
|
// the function type obtained by substituting Something
|
||||||
|
// for the return type of F.
|
||||||
|
template <typename F>
|
||||||
|
struct Function;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct Function<R()> {
|
||||||
|
typedef R Result;
|
||||||
|
typedef ::std::tr1::tuple<> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid();
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1>
|
||||||
|
struct Function<R(A1)>
|
||||||
|
: Function<R()> {
|
||||||
|
typedef A1 Argument1;
|
||||||
|
typedef ::std::tr1::tuple<A1> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2>
|
||||||
|
struct Function<R(A1, A2)>
|
||||||
|
: Function<R(A1)> {
|
||||||
|
typedef A2 Argument2;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3>
|
||||||
|
struct Function<R(A1, A2, A3)>
|
||||||
|
: Function<R(A1, A2)> {
|
||||||
|
typedef A3 Argument3;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4>
|
||||||
|
struct Function<R(A1, A2, A3, A4)>
|
||||||
|
: Function<R(A1, A2, A3)> {
|
||||||
|
typedef A4 Argument4;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5)>
|
||||||
|
: Function<R(A1, A2, A3, A4)> {
|
||||||
|
typedef A5 Argument5;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5)> {
|
||||||
|
typedef A6 Argument6;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6)> {
|
||||||
|
typedef A7 Argument7;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6, A7)> {
|
||||||
|
typedef A8 Argument8;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
|
||||||
|
typedef A9 Argument9;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
|
||||||
|
A9);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename A1, typename A2, typename A3, typename A4,
|
||||||
|
typename A5, typename A6, typename A7, typename A8, typename A9,
|
||||||
|
typename A10>
|
||||||
|
struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>
|
||||||
|
: Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
|
||||||
|
typedef A10 Argument10;
|
||||||
|
typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
|
||||||
|
A10> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
|
||||||
|
A9, A10);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
$$ -*- mode: c++; -*-
|
||||||
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
|
$$ gmock-generated-function-mockers.h.
|
||||||
|
$$
|
||||||
|
$var n = 10 $$ The maximum arity we support.
|
||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file contains template meta-programming utility classes needed
|
||||||
|
// for implementing Google Mock.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
|
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Matcher;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||||
|
// This is used in implementing the IgnoreResult(a) action.
|
||||||
|
class IgnoredValue {
|
||||||
|
public:
|
||||||
|
// This constructor template allows any value to be implicitly
|
||||||
|
// converted to IgnoredValue. The object has no data member and
|
||||||
|
// doesn't try to remember anything about the argument. We
|
||||||
|
// deliberately omit the 'explicit' keyword in order to allow the
|
||||||
|
// conversion to be implicit.
|
||||||
|
template <typename T>
|
||||||
|
IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit)
|
||||||
|
};
|
||||||
|
|
||||||
|
// MatcherTuple<T>::type is a tuple type where each field is a Matcher
|
||||||
|
// for the corresponding field in tuple type T.
|
||||||
|
template <typename Tuple>
|
||||||
|
struct MatcherTuple;
|
||||||
|
|
||||||
|
|
||||||
|
$range i 0..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j, [[typename A$j]]]]
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var matcher_As = [[$for j, [[Matcher<A$j>]]]]
|
||||||
|
template <$typename_As>
|
||||||
|
struct MatcherTuple< ::std::tr1::tuple<$As> > {
|
||||||
|
typedef ::std::tr1::tuple<$matcher_As > type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
// Template struct Function<F>, where F must be a function type, contains
|
||||||
|
// the following typedefs:
|
||||||
|
//
|
||||||
|
// Result: the function's return type.
|
||||||
|
// ArgumentN: the type of the N-th argument, where N starts with 1.
|
||||||
|
// ArgumentTuple: the tuple type consisting of all parameters of F.
|
||||||
|
// ArgumentMatcherTuple: the tuple type consisting of Matchers for all
|
||||||
|
// parameters of F.
|
||||||
|
// MakeResultVoid: the function type obtained by substituting void
|
||||||
|
// for the return type of F.
|
||||||
|
// MakeResultIgnoredValue:
|
||||||
|
// the function type obtained by substituting Something
|
||||||
|
// for the return type of F.
|
||||||
|
template <typename F>
|
||||||
|
struct Function;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
struct Function<R()> {
|
||||||
|
typedef R Result;
|
||||||
|
typedef ::std::tr1::tuple<> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid();
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$range i 1..n
|
||||||
|
$for i [[
|
||||||
|
$range j 1..i
|
||||||
|
$var typename_As = [[$for j [[, typename A$j]]]]
|
||||||
|
$var As = [[$for j, [[A$j]]]]
|
||||||
|
$var matcher_As = [[$for j, [[Matcher<A$j>]]]]
|
||||||
|
$range k 1..i-1
|
||||||
|
$var prev_As = [[$for k, [[A$k]]]]
|
||||||
|
template <typename R$typename_As>
|
||||||
|
struct Function<R($As)>
|
||||||
|
: Function<R($prev_As)> {
|
||||||
|
typedef A$i Argument$i;
|
||||||
|
typedef ::std::tr1::tuple<$As> ArgumentTuple;
|
||||||
|
typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
|
||||||
|
typedef void MakeResultVoid($As);
|
||||||
|
typedef IgnoredValue MakeResultIgnoredValue($As);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
]]
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
|
||||||
498
gmock/include/gmock/internal/gmock-internal-utils.h
Normal file
498
gmock/include/gmock/internal/gmock-internal-utils.h
Normal file
@@ -0,0 +1,498 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file defines some utilities useful for implementing Google
|
||||||
|
// Mock. They are subject to change without notice, so please DO NOT
|
||||||
|
// USE THEM IN USER CODE.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "gmock/internal/gmock-generated-internal-utils.h"
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Converts an identifier name to a space-separated list of lower-case
|
||||||
|
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
|
||||||
|
// treated as one word. For example, both "FooBar123" and
|
||||||
|
// "foo_bar_123" are converted to "foo bar 123".
|
||||||
|
GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name);
|
||||||
|
|
||||||
|
// PointeeOf<Pointer>::type is the type of a value pointed to by a
|
||||||
|
// Pointer, which can be either a smart pointer or a raw pointer. The
|
||||||
|
// following default implementation is for the case where Pointer is a
|
||||||
|
// smart pointer.
|
||||||
|
template <typename Pointer>
|
||||||
|
struct PointeeOf {
|
||||||
|
// Smart pointer classes define type element_type as the type of
|
||||||
|
// their pointees.
|
||||||
|
typedef typename Pointer::element_type type;
|
||||||
|
};
|
||||||
|
// This specialization is for the raw pointer case.
|
||||||
|
template <typename T>
|
||||||
|
struct PointeeOf<T*> { typedef T type; }; // NOLINT
|
||||||
|
|
||||||
|
// GetRawPointer(p) returns the raw pointer underlying p when p is a
|
||||||
|
// smart pointer, or returns p itself when p is already a raw pointer.
|
||||||
|
// The following default implementation is for the smart pointer case.
|
||||||
|
template <typename Pointer>
|
||||||
|
inline const typename Pointer::element_type* GetRawPointer(const Pointer& p) {
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
// This overloaded version is for the raw pointer case.
|
||||||
|
template <typename Element>
|
||||||
|
inline Element* GetRawPointer(Element* p) { return p; }
|
||||||
|
|
||||||
|
// This comparator allows linked_ptr to be stored in sets.
|
||||||
|
template <typename T>
|
||||||
|
struct LinkedPtrLessThan {
|
||||||
|
bool operator()(const ::testing::internal::linked_ptr<T>& lhs,
|
||||||
|
const ::testing::internal::linked_ptr<T>& rhs) const {
|
||||||
|
return lhs.get() < rhs.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Symbian compilation can be done with wchar_t being either a native
|
||||||
|
// type or a typedef. Using Google Mock with OpenC without wchar_t
|
||||||
|
// should require the definition of _STLP_NO_WCHAR_T.
|
||||||
|
//
|
||||||
|
// MSVC treats wchar_t as a native type usually, but treats it as the
|
||||||
|
// same as unsigned short when the compiler option /Zc:wchar_t- is
|
||||||
|
// specified. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
|
||||||
|
// is a native type.
|
||||||
|
#if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \
|
||||||
|
(defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED))
|
||||||
|
// wchar_t is a typedef.
|
||||||
|
#else
|
||||||
|
# define GMOCK_WCHAR_T_IS_NATIVE_ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// signed wchar_t and unsigned wchar_t are NOT in the C++ standard.
|
||||||
|
// Using them is a bad practice and not portable. So DON'T use them.
|
||||||
|
//
|
||||||
|
// Still, Google Mock is designed to work even if the user uses signed
|
||||||
|
// wchar_t or unsigned wchar_t (obviously, assuming the compiler
|
||||||
|
// supports them).
|
||||||
|
//
|
||||||
|
// To gcc,
|
||||||
|
// wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
|
||||||
|
#ifdef __GNUC__
|
||||||
|
// signed/unsigned wchar_t are valid types.
|
||||||
|
# define GMOCK_HAS_SIGNED_WCHAR_T_ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// In what follows, we use the term "kind" to indicate whether a type
|
||||||
|
// is bool, an integer type (excluding bool), a floating-point type,
|
||||||
|
// or none of them. This categorization is useful for determining
|
||||||
|
// when a matcher argument type can be safely converted to another
|
||||||
|
// type in the implementation of SafeMatcherCast.
|
||||||
|
enum TypeKind {
|
||||||
|
kBool, kInteger, kFloatingPoint, kOther
|
||||||
|
};
|
||||||
|
|
||||||
|
// KindOf<T>::value is the kind of type T.
|
||||||
|
template <typename T> struct KindOf {
|
||||||
|
enum { value = kOther }; // The default kind.
|
||||||
|
};
|
||||||
|
|
||||||
|
// This macro declares that the kind of 'type' is 'kind'.
|
||||||
|
#define GMOCK_DECLARE_KIND_(type, kind) \
|
||||||
|
template <> struct KindOf<type> { enum { value = kind }; }
|
||||||
|
|
||||||
|
GMOCK_DECLARE_KIND_(bool, kBool);
|
||||||
|
|
||||||
|
// All standard integer types.
|
||||||
|
GMOCK_DECLARE_KIND_(char, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(signed char, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned char, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(short, kInteger); // NOLINT
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned short, kInteger); // NOLINT
|
||||||
|
GMOCK_DECLARE_KIND_(int, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned int, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT
|
||||||
|
GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT
|
||||||
|
|
||||||
|
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||||
|
GMOCK_DECLARE_KIND_(wchar_t, kInteger);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Non-standard integer types.
|
||||||
|
GMOCK_DECLARE_KIND_(Int64, kInteger);
|
||||||
|
GMOCK_DECLARE_KIND_(UInt64, kInteger);
|
||||||
|
|
||||||
|
// All standard floating-point types.
|
||||||
|
GMOCK_DECLARE_KIND_(float, kFloatingPoint);
|
||||||
|
GMOCK_DECLARE_KIND_(double, kFloatingPoint);
|
||||||
|
GMOCK_DECLARE_KIND_(long double, kFloatingPoint);
|
||||||
|
|
||||||
|
#undef GMOCK_DECLARE_KIND_
|
||||||
|
|
||||||
|
// Evaluates to the kind of 'type'.
|
||||||
|
#define GMOCK_KIND_OF_(type) \
|
||||||
|
static_cast< ::testing::internal::TypeKind>( \
|
||||||
|
::testing::internal::KindOf<type>::value)
|
||||||
|
|
||||||
|
// Evaluates to true iff integer type T is signed.
|
||||||
|
#define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0)
|
||||||
|
|
||||||
|
// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
|
||||||
|
// is true iff arithmetic type From can be losslessly converted to
|
||||||
|
// arithmetic type To.
|
||||||
|
//
|
||||||
|
// It's the user's responsibility to ensure that both From and To are
|
||||||
|
// raw (i.e. has no CV modifier, is not a pointer, and is not a
|
||||||
|
// reference) built-in arithmetic types, kFromKind is the kind of
|
||||||
|
// From, and kToKind is the kind of To; the value is
|
||||||
|
// implementation-defined when the above pre-condition is violated.
|
||||||
|
template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl : public false_type {};
|
||||||
|
|
||||||
|
// Converting bool to bool is lossless.
|
||||||
|
template <>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool>
|
||||||
|
: public true_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting bool to any integer type is lossless.
|
||||||
|
template <typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To>
|
||||||
|
: public true_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting bool to any floating-point type is lossless.
|
||||||
|
template <typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To>
|
||||||
|
: public true_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting an integer to bool is lossy.
|
||||||
|
template <typename From>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting an integer to another non-bool integer is lossless iff
|
||||||
|
// the target type's range encloses the source type's range.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To>
|
||||||
|
: public bool_constant<
|
||||||
|
// When converting from a smaller size to a larger size, we are
|
||||||
|
// fine as long as we are not converting from signed to unsigned.
|
||||||
|
((sizeof(From) < sizeof(To)) &&
|
||||||
|
(!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) ||
|
||||||
|
// When converting between the same size, the signedness must match.
|
||||||
|
((sizeof(From) == sizeof(To)) &&
|
||||||
|
(GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {}; // NOLINT
|
||||||
|
|
||||||
|
#undef GMOCK_IS_SIGNED_
|
||||||
|
|
||||||
|
// Converting an integer to a floating-point type may be lossy, since
|
||||||
|
// the format of a floating-point number is implementation-defined.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting a floating-point to bool is lossy.
|
||||||
|
template <typename From>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting a floating-point to an integer is lossy.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To>
|
||||||
|
: public false_type {}; // NOLINT
|
||||||
|
|
||||||
|
// Converting a floating-point to another floating-point is lossless
|
||||||
|
// iff the target type is at least as big as the source type.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertibleImpl<
|
||||||
|
kFloatingPoint, From, kFloatingPoint, To>
|
||||||
|
: public bool_constant<sizeof(From) <= sizeof(To)> {}; // NOLINT
|
||||||
|
|
||||||
|
// LosslessArithmeticConvertible<From, To>::value is true iff arithmetic
|
||||||
|
// type From can be losslessly converted to arithmetic type To.
|
||||||
|
//
|
||||||
|
// It's the user's responsibility to ensure that both From and To are
|
||||||
|
// raw (i.e. has no CV modifier, is not a pointer, and is not a
|
||||||
|
// reference) built-in arithmetic types; the value is
|
||||||
|
// implementation-defined when the above pre-condition is violated.
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct LosslessArithmeticConvertible
|
||||||
|
: public LosslessArithmeticConvertibleImpl<
|
||||||
|
GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {}; // NOLINT
|
||||||
|
|
||||||
|
// This interface knows how to report a Google Mock failure (either
|
||||||
|
// non-fatal or fatal).
|
||||||
|
class FailureReporterInterface {
|
||||||
|
public:
|
||||||
|
// The type of a failure (either non-fatal or fatal).
|
||||||
|
enum FailureType {
|
||||||
|
kNonfatal, kFatal
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~FailureReporterInterface() {}
|
||||||
|
|
||||||
|
// Reports a failure that occurred at the given source file location.
|
||||||
|
virtual void ReportFailure(FailureType type, const char* file, int line,
|
||||||
|
const string& message) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the failure reporter used by Google Mock.
|
||||||
|
GTEST_API_ FailureReporterInterface* GetFailureReporter();
|
||||||
|
|
||||||
|
// Asserts that condition is true; aborts the process with the given
|
||||||
|
// message if condition is false. We cannot use LOG(FATAL) or CHECK()
|
||||||
|
// as Google Mock might be used to mock the log sink itself. We
|
||||||
|
// inline this function to prevent it from showing up in the stack
|
||||||
|
// trace.
|
||||||
|
inline void Assert(bool condition, const char* file, int line,
|
||||||
|
const string& msg) {
|
||||||
|
if (!condition) {
|
||||||
|
GetFailureReporter()->ReportFailure(FailureReporterInterface::kFatal,
|
||||||
|
file, line, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void Assert(bool condition, const char* file, int line) {
|
||||||
|
Assert(condition, file, line, "Assertion failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies that condition is true; generates a non-fatal failure if
|
||||||
|
// condition is false.
|
||||||
|
inline void Expect(bool condition, const char* file, int line,
|
||||||
|
const string& msg) {
|
||||||
|
if (!condition) {
|
||||||
|
GetFailureReporter()->ReportFailure(FailureReporterInterface::kNonfatal,
|
||||||
|
file, line, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void Expect(bool condition, const char* file, int line) {
|
||||||
|
Expect(condition, file, line, "Expectation failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Severity level of a log.
|
||||||
|
enum LogSeverity {
|
||||||
|
kInfo = 0,
|
||||||
|
kWarning = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Valid values for the --gmock_verbose flag.
|
||||||
|
|
||||||
|
// All logs (informational and warnings) are printed.
|
||||||
|
const char kInfoVerbosity[] = "info";
|
||||||
|
// Only warnings are printed.
|
||||||
|
const char kWarningVerbosity[] = "warning";
|
||||||
|
// No logs are printed.
|
||||||
|
const char kErrorVerbosity[] = "error";
|
||||||
|
|
||||||
|
// Returns true iff a log with the given severity is visible according
|
||||||
|
// to the --gmock_verbose flag.
|
||||||
|
GTEST_API_ bool LogIsVisible(LogSeverity severity);
|
||||||
|
|
||||||
|
// Prints the given message to stdout iff 'severity' >= the level
|
||||||
|
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
||||||
|
// 0, also prints the stack trace excluding the top
|
||||||
|
// stack_frames_to_skip frames. In opt mode, any positive
|
||||||
|
// stack_frames_to_skip is treated as 0, since we don't know which
|
||||||
|
// function calls will be inlined by the compiler and need to be
|
||||||
|
// conservative.
|
||||||
|
GTEST_API_ void Log(LogSeverity severity,
|
||||||
|
const string& message,
|
||||||
|
int stack_frames_to_skip);
|
||||||
|
|
||||||
|
// TODO(wan@google.com): group all type utilities together.
|
||||||
|
|
||||||
|
// Type traits.
|
||||||
|
|
||||||
|
// is_reference<T>::value is non-zero iff T is a reference type.
|
||||||
|
template <typename T> struct is_reference : public false_type {};
|
||||||
|
template <typename T> struct is_reference<T&> : public true_type {};
|
||||||
|
|
||||||
|
// type_equals<T1, T2>::value is non-zero iff T1 and T2 are the same type.
|
||||||
|
template <typename T1, typename T2> struct type_equals : public false_type {};
|
||||||
|
template <typename T> struct type_equals<T, T> : public true_type {};
|
||||||
|
|
||||||
|
// remove_reference<T>::type removes the reference from type T, if any.
|
||||||
|
template <typename T> struct remove_reference { typedef T type; }; // NOLINT
|
||||||
|
template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
|
||||||
|
|
||||||
|
// DecayArray<T>::type turns an array type U[N] to const U* and preserves
|
||||||
|
// other types. Useful for saving a copy of a function argument.
|
||||||
|
template <typename T> struct DecayArray { typedef T type; }; // NOLINT
|
||||||
|
template <typename T, size_t N> struct DecayArray<T[N]> {
|
||||||
|
typedef const T* type;
|
||||||
|
};
|
||||||
|
// Sometimes people use arrays whose size is not available at the use site
|
||||||
|
// (e.g. extern const char kNamePrefix[]). This specialization covers that
|
||||||
|
// case.
|
||||||
|
template <typename T> struct DecayArray<T[]> {
|
||||||
|
typedef const T* type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invalid<T>() returns an invalid value of type T. This is useful
|
||||||
|
// when a value of type T is needed for compilation, but the statement
|
||||||
|
// will not really be executed (or we don't care if the statement
|
||||||
|
// crashes).
|
||||||
|
template <typename T>
|
||||||
|
inline T Invalid() {
|
||||||
|
return const_cast<typename remove_reference<T>::type&>(
|
||||||
|
*static_cast<volatile typename remove_reference<T>::type*>(NULL));
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
inline void Invalid<void>() {}
|
||||||
|
|
||||||
|
// Given a raw type (i.e. having no top-level reference or const
|
||||||
|
// modifier) RawContainer that's either an STL-style container or a
|
||||||
|
// native array, class StlContainerView<RawContainer> has the
|
||||||
|
// following members:
|
||||||
|
//
|
||||||
|
// - type is a type that provides an STL-style container view to
|
||||||
|
// (i.e. implements the STL container concept for) RawContainer;
|
||||||
|
// - const_reference is a type that provides a reference to a const
|
||||||
|
// RawContainer;
|
||||||
|
// - ConstReference(raw_container) returns a const reference to an STL-style
|
||||||
|
// container view to raw_container, which is a RawContainer.
|
||||||
|
// - Copy(raw_container) returns an STL-style container view of a
|
||||||
|
// copy of raw_container, which is a RawContainer.
|
||||||
|
//
|
||||||
|
// This generic version is used when RawContainer itself is already an
|
||||||
|
// STL-style container.
|
||||||
|
template <class RawContainer>
|
||||||
|
class StlContainerView {
|
||||||
|
public:
|
||||||
|
typedef RawContainer type;
|
||||||
|
typedef const type& const_reference;
|
||||||
|
|
||||||
|
static const_reference ConstReference(const RawContainer& container) {
|
||||||
|
// Ensures that RawContainer is not a const type.
|
||||||
|
testing::StaticAssertTypeEq<RawContainer,
|
||||||
|
GTEST_REMOVE_CONST_(RawContainer)>();
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
static type Copy(const RawContainer& container) { return container; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// This specialization is used when RawContainer is a native array type.
|
||||||
|
template <typename Element, size_t N>
|
||||||
|
class StlContainerView<Element[N]> {
|
||||||
|
public:
|
||||||
|
typedef GTEST_REMOVE_CONST_(Element) RawElement;
|
||||||
|
typedef internal::NativeArray<RawElement> type;
|
||||||
|
// NativeArray<T> can represent a native array either by value or by
|
||||||
|
// reference (selected by a constructor argument), so 'const type'
|
||||||
|
// can be used to reference a const native array. We cannot
|
||||||
|
// 'typedef const type& const_reference' here, as that would mean
|
||||||
|
// ConstReference() has to return a reference to a local variable.
|
||||||
|
typedef const type const_reference;
|
||||||
|
|
||||||
|
static const_reference ConstReference(const Element (&array)[N]) {
|
||||||
|
// Ensures that Element is not a const type.
|
||||||
|
testing::StaticAssertTypeEq<Element, RawElement>();
|
||||||
|
#if GTEST_OS_SYMBIAN
|
||||||
|
// The Nokia Symbian compiler confuses itself in template instantiation
|
||||||
|
// for this call without the cast to Element*:
|
||||||
|
// function call '[testing::internal::NativeArray<char *>].NativeArray(
|
||||||
|
// {lval} const char *[4], long, testing::internal::RelationToSource)'
|
||||||
|
// does not match
|
||||||
|
// 'testing::internal::NativeArray<char *>::NativeArray(
|
||||||
|
// char *const *, unsigned int, testing::internal::RelationToSource)'
|
||||||
|
// (instantiating: 'testing::internal::ContainsMatcherImpl
|
||||||
|
// <const char * (&)[4]>::Matches(const char * (&)[4]) const')
|
||||||
|
// (instantiating: 'testing::internal::StlContainerView<char *[4]>::
|
||||||
|
// ConstReference(const char * (&)[4])')
|
||||||
|
// (and though the N parameter type is mismatched in the above explicit
|
||||||
|
// conversion of it doesn't help - only the conversion of the array).
|
||||||
|
return type(const_cast<Element*>(&array[0]), N, kReference);
|
||||||
|
#else
|
||||||
|
return type(array, N, kReference);
|
||||||
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
}
|
||||||
|
static type Copy(const Element (&array)[N]) {
|
||||||
|
#if GTEST_OS_SYMBIAN
|
||||||
|
return type(const_cast<Element*>(&array[0]), N, kCopy);
|
||||||
|
#else
|
||||||
|
return type(array, N, kCopy);
|
||||||
|
#endif // GTEST_OS_SYMBIAN
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This specialization is used when RawContainer is a native array
|
||||||
|
// represented as a (pointer, size) tuple.
|
||||||
|
template <typename ElementPointer, typename Size>
|
||||||
|
class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
|
||||||
|
public:
|
||||||
|
typedef GTEST_REMOVE_CONST_(
|
||||||
|
typename internal::PointeeOf<ElementPointer>::type) RawElement;
|
||||||
|
typedef internal::NativeArray<RawElement> type;
|
||||||
|
typedef const type const_reference;
|
||||||
|
|
||||||
|
static const_reference ConstReference(
|
||||||
|
const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type(get<0>(array), get<1>(array), kReference);
|
||||||
|
}
|
||||||
|
static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
||||||
|
using ::std::tr1::get;
|
||||||
|
return type(get<0>(array), get<1>(array), kCopy);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The following specialization prevents the user from instantiating
|
||||||
|
// StlContainer with a reference type.
|
||||||
|
template <typename T> class StlContainerView<T&>;
|
||||||
|
|
||||||
|
// A type transform to remove constness from the first part of a pair.
|
||||||
|
// Pairs like that are used as the value_type of associative containers,
|
||||||
|
// and this transform produces a similar but assignable pair.
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveConstFromKey {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Partially specialized to remove constness from std::pair<const K, V>.
|
||||||
|
template <typename K, typename V>
|
||||||
|
struct RemoveConstFromKey<std::pair<const K, V> > {
|
||||||
|
typedef std::pair<K, V> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mapping from booleans to types. Similar to boost::bool_<kValue> and
|
||||||
|
// std::integral_constant<bool, kValue>.
|
||||||
|
template <bool kValue>
|
||||||
|
struct BooleanConstant {};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
|
||||||
78
gmock/include/gmock/internal/gmock-port.h
Normal file
78
gmock/include/gmock/internal/gmock-port.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: vadimb@google.com (Vadim Berman)
|
||||||
|
//
|
||||||
|
// Low-level types and utilities for porting Google Mock to various
|
||||||
|
// platforms. They are subject to change without notice. DO NOT USE
|
||||||
|
// THEM IN USER CODE.
|
||||||
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// Most of the types needed for porting Google Mock are also required
|
||||||
|
// for Google Test and are defined in gtest-port.h.
|
||||||
|
#include "gtest/internal/gtest-linked_ptr.h"
|
||||||
|
#include "gtest/internal/gtest-port.h"
|
||||||
|
|
||||||
|
// To avoid conditional compilation everywhere, we make it
|
||||||
|
// gmock-port.h's responsibility to #include the header implementing
|
||||||
|
// tr1/tuple. gmock-port.h does this via gtest-port.h, which is
|
||||||
|
// guaranteed to pull in the tuple header.
|
||||||
|
|
||||||
|
// For MS Visual C++, check the compiler version. At least VS 2003 is
|
||||||
|
// required to compile Google Mock.
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1310
|
||||||
|
# error "At least Visual C++ 2003 (7.1) is required to compile Google Mock."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Macro for referencing flags. This is public as we want the user to
|
||||||
|
// use this syntax to reference Google Mock flags.
|
||||||
|
#define GMOCK_FLAG(name) FLAGS_gmock_##name
|
||||||
|
|
||||||
|
// Macros for declaring flags.
|
||||||
|
#define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name)
|
||||||
|
#define GMOCK_DECLARE_int32_(name) \
|
||||||
|
extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name)
|
||||||
|
#define GMOCK_DECLARE_string_(name) \
|
||||||
|
extern GTEST_API_ ::std::string GMOCK_FLAG(name)
|
||||||
|
|
||||||
|
// Macros for defining flags.
|
||||||
|
#define GMOCK_DEFINE_bool_(name, default_val, doc) \
|
||||||
|
GTEST_API_ bool GMOCK_FLAG(name) = (default_val)
|
||||||
|
#define GMOCK_DEFINE_int32_(name, default_val, doc) \
|
||||||
|
GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
|
||||||
|
#define GMOCK_DEFINE_string_(name, default_val, doc) \
|
||||||
|
GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val)
|
||||||
|
|
||||||
|
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
|
||||||
47
gmock/src/gmock-all.cc
Normal file
47
gmock/src/gmock-all.cc
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
//
|
||||||
|
// Google C++ Mocking Framework (Google Mock)
|
||||||
|
//
|
||||||
|
// This file #includes all Google Mock implementation .cc files. The
|
||||||
|
// purpose is to allow a user to build Google Mock by compiling this
|
||||||
|
// file alone.
|
||||||
|
|
||||||
|
// This line ensures that gmock.h can be compiled on its own, even
|
||||||
|
// when it's fused.
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
// The following lines pull in the real gmock *.cc files.
|
||||||
|
#include "src/gmock-cardinalities.cc"
|
||||||
|
#include "src/gmock-internal-utils.cc"
|
||||||
|
#include "src/gmock-matchers.cc"
|
||||||
|
#include "src/gmock-spec-builders.cc"
|
||||||
|
#include "src/gmock.cc"
|
||||||
156
gmock/src/gmock-cardinalities.cc
Normal file
156
gmock/src/gmock-cardinalities.cc
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements cardinalities.
|
||||||
|
|
||||||
|
#include "gmock/gmock-cardinalities.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Implements the Between(m, n) cardinality.
|
||||||
|
class BetweenCardinalityImpl : public CardinalityInterface {
|
||||||
|
public:
|
||||||
|
BetweenCardinalityImpl(int min, int max)
|
||||||
|
: min_(min >= 0 ? min : 0),
|
||||||
|
max_(max >= min_ ? max : min_) {
|
||||||
|
std::stringstream ss;
|
||||||
|
if (min < 0) {
|
||||||
|
ss << "The invocation lower bound must be >= 0, "
|
||||||
|
<< "but is actually " << min << ".";
|
||||||
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
|
} else if (max < 0) {
|
||||||
|
ss << "The invocation upper bound must be >= 0, "
|
||||||
|
<< "but is actually " << max << ".";
|
||||||
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
|
} else if (min > max) {
|
||||||
|
ss << "The invocation upper bound (" << max
|
||||||
|
<< ") must be >= the invocation lower bound (" << min
|
||||||
|
<< ").";
|
||||||
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conservative estimate on the lower/upper bound of the number of
|
||||||
|
// calls allowed.
|
||||||
|
virtual int ConservativeLowerBound() const { return min_; }
|
||||||
|
virtual int ConservativeUpperBound() const { return max_; }
|
||||||
|
|
||||||
|
virtual bool IsSatisfiedByCallCount(int call_count) const {
|
||||||
|
return min_ <= call_count && call_count <= max_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsSaturatedByCallCount(int call_count) const {
|
||||||
|
return call_count >= max_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DescribeTo(::std::ostream* os) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int min_;
|
||||||
|
const int max_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(BetweenCardinalityImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Formats "n times" in a human-friendly way.
|
||||||
|
inline internal::string FormatTimes(int n) {
|
||||||
|
if (n == 1) {
|
||||||
|
return "once";
|
||||||
|
} else if (n == 2) {
|
||||||
|
return "twice";
|
||||||
|
} else {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << n << " times";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes the Between(m, n) cardinality in human-friendly text.
|
||||||
|
void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const {
|
||||||
|
if (min_ == 0) {
|
||||||
|
if (max_ == 0) {
|
||||||
|
*os << "never called";
|
||||||
|
} else if (max_ == INT_MAX) {
|
||||||
|
*os << "called any number of times";
|
||||||
|
} else {
|
||||||
|
*os << "called at most " << FormatTimes(max_);
|
||||||
|
}
|
||||||
|
} else if (min_ == max_) {
|
||||||
|
*os << "called " << FormatTimes(min_);
|
||||||
|
} else if (max_ == INT_MAX) {
|
||||||
|
*os << "called at least " << FormatTimes(min_);
|
||||||
|
} else {
|
||||||
|
// 0 < min_ < max_ < INT_MAX
|
||||||
|
*os << "called between " << min_ << " and " << max_ << " times";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Unnamed namespace
|
||||||
|
|
||||||
|
// Describes the given call count to an ostream.
|
||||||
|
void Cardinality::DescribeActualCallCountTo(int actual_call_count,
|
||||||
|
::std::ostream* os) {
|
||||||
|
if (actual_call_count > 0) {
|
||||||
|
*os << "called " << FormatTimes(actual_call_count);
|
||||||
|
} else {
|
||||||
|
*os << "never called";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at least n calls.
|
||||||
|
GTEST_API_ Cardinality AtLeast(int n) { return Between(n, INT_MAX); }
|
||||||
|
|
||||||
|
// Creates a cardinality that allows at most n calls.
|
||||||
|
GTEST_API_ Cardinality AtMost(int n) { return Between(0, n); }
|
||||||
|
|
||||||
|
// Creates a cardinality that allows any number of calls.
|
||||||
|
GTEST_API_ Cardinality AnyNumber() { return AtLeast(0); }
|
||||||
|
|
||||||
|
// Creates a cardinality that allows between min and max calls.
|
||||||
|
GTEST_API_ Cardinality Between(int min, int max) {
|
||||||
|
return Cardinality(new BetweenCardinalityImpl(min, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a cardinality that allows exactly n calls.
|
||||||
|
GTEST_API_ Cardinality Exactly(int n) { return Between(n, n); }
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
174
gmock/src/gmock-internal-utils.cc
Normal file
174
gmock/src/gmock-internal-utils.cc
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file defines some utilities useful for implementing Google
|
||||||
|
// Mock. They are subject to change without notice, so please DO NOT
|
||||||
|
// USE THEM IN USER CODE.
|
||||||
|
|
||||||
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <ostream> // NOLINT
|
||||||
|
#include <string>
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Converts an identifier name to a space-separated list of lower-case
|
||||||
|
// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
|
||||||
|
// treated as one word. For example, both "FooBar123" and
|
||||||
|
// "foo_bar_123" are converted to "foo bar 123".
|
||||||
|
GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name) {
|
||||||
|
string result;
|
||||||
|
char prev_char = '\0';
|
||||||
|
for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
|
||||||
|
// We don't care about the current locale as the input is
|
||||||
|
// guaranteed to be a valid C++ identifier name.
|
||||||
|
const bool starts_new_word = IsUpper(*p) ||
|
||||||
|
(!IsAlpha(prev_char) && IsLower(*p)) ||
|
||||||
|
(!IsDigit(prev_char) && IsDigit(*p));
|
||||||
|
|
||||||
|
if (IsAlNum(*p)) {
|
||||||
|
if (starts_new_word && result != "")
|
||||||
|
result += ' ';
|
||||||
|
result += ToLower(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class reports Google Mock failures as Google Test failures. A
|
||||||
|
// user can define another class in a similar fashion if he intends to
|
||||||
|
// use Google Mock with a testing framework other than Google Test.
|
||||||
|
class GoogleTestFailureReporter : public FailureReporterInterface {
|
||||||
|
public:
|
||||||
|
virtual void ReportFailure(FailureType type, const char* file, int line,
|
||||||
|
const string& message) {
|
||||||
|
AssertHelper(type == kFatal ?
|
||||||
|
TestPartResult::kFatalFailure :
|
||||||
|
TestPartResult::kNonFatalFailure,
|
||||||
|
file,
|
||||||
|
line,
|
||||||
|
message.c_str()) = Message();
|
||||||
|
if (type == kFatal) {
|
||||||
|
posix::Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the global failure reporter. Will create a
|
||||||
|
// GoogleTestFailureReporter and return it the first time called.
|
||||||
|
GTEST_API_ FailureReporterInterface* GetFailureReporter() {
|
||||||
|
// Points to the global failure reporter used by Google Mock. gcc
|
||||||
|
// guarantees that the following use of failure_reporter is
|
||||||
|
// thread-safe. We may need to add additional synchronization to
|
||||||
|
// protect failure_reporter if we port Google Mock to other
|
||||||
|
// compilers.
|
||||||
|
static FailureReporterInterface* const failure_reporter =
|
||||||
|
new GoogleTestFailureReporter();
|
||||||
|
return failure_reporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protects global resources (stdout in particular) used by Log().
|
||||||
|
static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
|
||||||
|
|
||||||
|
// Returns true iff a log with the given severity is visible according
|
||||||
|
// to the --gmock_verbose flag.
|
||||||
|
GTEST_API_ bool LogIsVisible(LogSeverity severity) {
|
||||||
|
if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
|
||||||
|
// Always show the log if --gmock_verbose=info.
|
||||||
|
return true;
|
||||||
|
} else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
|
||||||
|
// Always hide it if --gmock_verbose=error.
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// If --gmock_verbose is neither "info" nor "error", we treat it
|
||||||
|
// as "warning" (its default value).
|
||||||
|
return severity == kWarning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the given message to stdout iff 'severity' >= the level
|
||||||
|
// specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
||||||
|
// 0, also prints the stack trace excluding the top
|
||||||
|
// stack_frames_to_skip frames. In opt mode, any positive
|
||||||
|
// stack_frames_to_skip is treated as 0, since we don't know which
|
||||||
|
// function calls will be inlined by the compiler and need to be
|
||||||
|
// conservative.
|
||||||
|
GTEST_API_ void Log(LogSeverity severity,
|
||||||
|
const string& message,
|
||||||
|
int stack_frames_to_skip) {
|
||||||
|
if (!LogIsVisible(severity))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ensures that logs from different threads don't interleave.
|
||||||
|
MutexLock l(&g_log_mutex);
|
||||||
|
|
||||||
|
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a
|
||||||
|
// macro.
|
||||||
|
|
||||||
|
if (severity == kWarning) {
|
||||||
|
// Prints a GMOCK WARNING marker to make the warnings easily searchable.
|
||||||
|
std::cout << "\nGMOCK WARNING:";
|
||||||
|
}
|
||||||
|
// Pre-pends a new-line to message if it doesn't start with one.
|
||||||
|
if (message.empty() || message[0] != '\n') {
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
std::cout << message;
|
||||||
|
if (stack_frames_to_skip >= 0) {
|
||||||
|
#ifdef NDEBUG
|
||||||
|
// In opt mode, we have to be conservative and skip no stack frame.
|
||||||
|
const int actual_to_skip = 0;
|
||||||
|
#else
|
||||||
|
// In dbg mode, we can do what the caller tell us to do (plus one
|
||||||
|
// for skipping this function's stack frame).
|
||||||
|
const int actual_to_skip = stack_frames_to_skip + 1;
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
// Appends a new-line to message if it doesn't end with one.
|
||||||
|
if (!message.empty() && *message.rbegin() != '\n') {
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
std::cout << "Stack trace:\n"
|
||||||
|
<< ::testing::internal::GetCurrentOsStackTraceExceptTop(
|
||||||
|
::testing::UnitTest::GetInstance(), actual_to_skip);
|
||||||
|
}
|
||||||
|
std::cout << ::std::flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
498
gmock/src/gmock-matchers.cc
Normal file
498
gmock/src/gmock-matchers.cc
Normal file
@@ -0,0 +1,498 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements Matcher<const string&>, Matcher<string>, and
|
||||||
|
// utilities for defining matchers.
|
||||||
|
|
||||||
|
#include "gmock/gmock-matchers.h"
|
||||||
|
#include "gmock/gmock-generated-matchers.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const internal::string&>::Matcher(const internal::string& s) {
|
||||||
|
*this = Eq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const string& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const internal::string&>::Matcher(const char* s) {
|
||||||
|
*this = Eq(internal::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a string whose value is equal to s.
|
||||||
|
Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); }
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a string whose value is equal to s.
|
||||||
|
Matcher<internal::string>::Matcher(const char* s) {
|
||||||
|
*this = Eq(internal::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GTEST_HAS_STRING_PIECE_
|
||||||
|
// Constructs a matcher that matches a const StringPiece& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const StringPiece&>::Matcher(const internal::string& s) {
|
||||||
|
*this = Eq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const StringPiece& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const StringPiece&>::Matcher(const char* s) {
|
||||||
|
*this = Eq(internal::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a const StringPiece& whose value is
|
||||||
|
// equal to s.
|
||||||
|
Matcher<const StringPiece&>::Matcher(StringPiece s) {
|
||||||
|
*this = Eq(s.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a StringPiece whose value is equal to s.
|
||||||
|
Matcher<StringPiece>::Matcher(const internal::string& s) {
|
||||||
|
*this = Eq(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a StringPiece whose value is equal to s.
|
||||||
|
Matcher<StringPiece>::Matcher(const char* s) {
|
||||||
|
*this = Eq(internal::string(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs a matcher that matches a StringPiece whose value is equal to s.
|
||||||
|
Matcher<StringPiece>::Matcher(StringPiece s) {
|
||||||
|
*this = Eq(s.ToString());
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_STRING_PIECE_
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Joins a vector of strings as if they are fields of a tuple; returns
|
||||||
|
// the joined string.
|
||||||
|
GTEST_API_ string JoinAsTuple(const Strings& fields) {
|
||||||
|
switch (fields.size()) {
|
||||||
|
case 0:
|
||||||
|
return "";
|
||||||
|
case 1:
|
||||||
|
return fields[0];
|
||||||
|
default:
|
||||||
|
string result = "(" + fields[0];
|
||||||
|
for (size_t i = 1; i < fields.size(); i++) {
|
||||||
|
result += ", ";
|
||||||
|
result += fields[i];
|
||||||
|
}
|
||||||
|
result += ")";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the description for a matcher defined using the MATCHER*()
|
||||||
|
// macro where the user-supplied description string is "", if
|
||||||
|
// 'negation' is false; otherwise returns the description of the
|
||||||
|
// negation of the matcher. 'param_values' contains a list of strings
|
||||||
|
// that are the print-out of the matcher's parameters.
|
||||||
|
GTEST_API_ string FormatMatcherDescription(bool negation,
|
||||||
|
const char* matcher_name,
|
||||||
|
const Strings& param_values) {
|
||||||
|
string result = ConvertIdentifierNameToWords(matcher_name);
|
||||||
|
if (param_values.size() >= 1)
|
||||||
|
result += " " + JoinAsTuple(param_values);
|
||||||
|
return negation ? "not (" + result + ")" : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindMaxBipartiteMatching and its helper class.
|
||||||
|
//
|
||||||
|
// Uses the well-known Ford-Fulkerson max flow method to find a maximum
|
||||||
|
// bipartite matching. Flow is considered to be from left to right.
|
||||||
|
// There is an implicit source node that is connected to all of the left
|
||||||
|
// nodes, and an implicit sink node that is connected to all of the
|
||||||
|
// right nodes. All edges have unit capacity.
|
||||||
|
//
|
||||||
|
// Neither the flow graph nor the residual flow graph are represented
|
||||||
|
// explicitly. Instead, they are implied by the information in 'graph' and
|
||||||
|
// a vector<int> called 'left_' whose elements are initialized to the
|
||||||
|
// value kUnused. This represents the initial state of the algorithm,
|
||||||
|
// where the flow graph is empty, and the residual flow graph has the
|
||||||
|
// following edges:
|
||||||
|
// - An edge from source to each left_ node
|
||||||
|
// - An edge from each right_ node to sink
|
||||||
|
// - An edge from each left_ node to each right_ node, if the
|
||||||
|
// corresponding edge exists in 'graph'.
|
||||||
|
//
|
||||||
|
// When the TryAugment() method adds a flow, it sets left_[l] = r for some
|
||||||
|
// nodes l and r. This induces the following changes:
|
||||||
|
// - The edges (source, l), (l, r), and (r, sink) are added to the
|
||||||
|
// flow graph.
|
||||||
|
// - The same three edges are removed from the residual flow graph.
|
||||||
|
// - The reverse edges (l, source), (r, l), and (sink, r) are added
|
||||||
|
// to the residual flow graph, which is a directional graph
|
||||||
|
// representing unused flow capacity.
|
||||||
|
//
|
||||||
|
// When the method augments a flow (moving left_[l] from some r1 to some
|
||||||
|
// other r2), this can be thought of as "undoing" the above steps with
|
||||||
|
// respect to r1 and "redoing" them with respect to r2.
|
||||||
|
//
|
||||||
|
// It bears repeating that the flow graph and residual flow graph are
|
||||||
|
// never represented explicitly, but can be derived by looking at the
|
||||||
|
// information in 'graph' and in left_.
|
||||||
|
//
|
||||||
|
// As an optimization, there is a second vector<int> called right_ which
|
||||||
|
// does not provide any new information. Instead, it enables more
|
||||||
|
// efficient queries about edges entering or leaving the right-side nodes
|
||||||
|
// of the flow or residual flow graphs. The following invariants are
|
||||||
|
// maintained:
|
||||||
|
//
|
||||||
|
// left[l] == kUnused or right[left[l]] == l
|
||||||
|
// right[r] == kUnused or left[right[r]] == r
|
||||||
|
//
|
||||||
|
// . [ source ] .
|
||||||
|
// . ||| .
|
||||||
|
// . ||| .
|
||||||
|
// . ||\--> left[0]=1 ---\ right[0]=-1 ----\ .
|
||||||
|
// . || | | .
|
||||||
|
// . |\---> left[1]=-1 \--> right[1]=0 ---\| .
|
||||||
|
// . | || .
|
||||||
|
// . \----> left[2]=2 ------> right[2]=2 --\|| .
|
||||||
|
// . ||| .
|
||||||
|
// . elements matchers vvv .
|
||||||
|
// . [ sink ] .
|
||||||
|
//
|
||||||
|
// See Also:
|
||||||
|
// [1] Cormen, et al (2001). "Section 26.2: The Ford–Fulkerson method".
|
||||||
|
// "Introduction to Algorithms (Second ed.)", pp. 651–664.
|
||||||
|
// [2] "Ford–Fulkerson algorithm", Wikipedia,
|
||||||
|
// 'http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm'
|
||||||
|
class MaxBipartiteMatchState {
|
||||||
|
public:
|
||||||
|
explicit MaxBipartiteMatchState(const MatchMatrix& graph)
|
||||||
|
: graph_(&graph),
|
||||||
|
left_(graph_->LhsSize(), kUnused),
|
||||||
|
right_(graph_->RhsSize(), kUnused) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the edges of a maximal match, each in the form {left, right}.
|
||||||
|
ElementMatcherPairs Compute() {
|
||||||
|
// 'seen' is used for path finding { 0: unseen, 1: seen }.
|
||||||
|
::std::vector<char> seen;
|
||||||
|
// Searches the residual flow graph for a path from each left node to
|
||||||
|
// the sink in the residual flow graph, and if one is found, add flow
|
||||||
|
// to the graph. It's okay to search through the left nodes once. The
|
||||||
|
// edge from the implicit source node to each previously-visited left
|
||||||
|
// node will have flow if that left node has any path to the sink
|
||||||
|
// whatsoever. Subsequent augmentations can only add flow to the
|
||||||
|
// network, and cannot take away that previous flow unit from the source.
|
||||||
|
// Since the source-to-left edge can only carry one flow unit (or,
|
||||||
|
// each element can be matched to only one matcher), there is no need
|
||||||
|
// to visit the left nodes more than once looking for augmented paths.
|
||||||
|
// The flow is known to be possible or impossible by looking at the
|
||||||
|
// node once.
|
||||||
|
for (size_t ilhs = 0; ilhs < graph_->LhsSize(); ++ilhs) {
|
||||||
|
// Reset the path-marking vector and try to find a path from
|
||||||
|
// source to sink starting at the left_[ilhs] node.
|
||||||
|
GTEST_CHECK_(left_[ilhs] == kUnused)
|
||||||
|
<< "ilhs: " << ilhs << ", left_[ilhs]: " << left_[ilhs];
|
||||||
|
// 'seen' initialized to 'graph_->RhsSize()' copies of 0.
|
||||||
|
seen.assign(graph_->RhsSize(), 0);
|
||||||
|
TryAugment(ilhs, &seen);
|
||||||
|
}
|
||||||
|
ElementMatcherPairs result;
|
||||||
|
for (size_t ilhs = 0; ilhs < left_.size(); ++ilhs) {
|
||||||
|
size_t irhs = left_[ilhs];
|
||||||
|
if (irhs == kUnused) continue;
|
||||||
|
result.push_back(ElementMatcherPair(ilhs, irhs));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const size_t kUnused = static_cast<size_t>(-1);
|
||||||
|
|
||||||
|
// Perform a depth-first search from left node ilhs to the sink. If a
|
||||||
|
// path is found, flow is added to the network by linking the left and
|
||||||
|
// right vector elements corresponding each segment of the path.
|
||||||
|
// Returns true if a path to sink was found, which means that a unit of
|
||||||
|
// flow was added to the network. The 'seen' vector elements correspond
|
||||||
|
// to right nodes and are marked to eliminate cycles from the search.
|
||||||
|
//
|
||||||
|
// Left nodes will only be explored at most once because they
|
||||||
|
// are accessible from at most one right node in the residual flow
|
||||||
|
// graph.
|
||||||
|
//
|
||||||
|
// Note that left_[ilhs] is the only element of left_ that TryAugment will
|
||||||
|
// potentially transition from kUnused to another value. Any other
|
||||||
|
// left_ element holding kUnused before TryAugment will be holding it
|
||||||
|
// when TryAugment returns.
|
||||||
|
//
|
||||||
|
bool TryAugment(size_t ilhs, ::std::vector<char>* seen) {
|
||||||
|
for (size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
|
||||||
|
if ((*seen)[irhs])
|
||||||
|
continue;
|
||||||
|
if (!graph_->HasEdge(ilhs, irhs))
|
||||||
|
continue;
|
||||||
|
// There's an available edge from ilhs to irhs.
|
||||||
|
(*seen)[irhs] = 1;
|
||||||
|
// Next a search is performed to determine whether
|
||||||
|
// this edge is a dead end or leads to the sink.
|
||||||
|
//
|
||||||
|
// right_[irhs] == kUnused means that there is residual flow from
|
||||||
|
// right node irhs to the sink, so we can use that to finish this
|
||||||
|
// flow path and return success.
|
||||||
|
//
|
||||||
|
// Otherwise there is residual flow to some ilhs. We push flow
|
||||||
|
// along that path and call ourselves recursively to see if this
|
||||||
|
// ultimately leads to sink.
|
||||||
|
if (right_[irhs] == kUnused || TryAugment(right_[irhs], seen)) {
|
||||||
|
// Add flow from left_[ilhs] to right_[irhs].
|
||||||
|
left_[ilhs] = irhs;
|
||||||
|
right_[irhs] = ilhs;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MatchMatrix* graph_; // not owned
|
||||||
|
// Each element of the left_ vector represents a left hand side node
|
||||||
|
// (i.e. an element) and each element of right_ is a right hand side
|
||||||
|
// node (i.e. a matcher). The values in the left_ vector indicate
|
||||||
|
// outflow from that node to a node on the the right_ side. The values
|
||||||
|
// in the right_ indicate inflow, and specify which left_ node is
|
||||||
|
// feeding that right_ node, if any. For example, left_[3] == 1 means
|
||||||
|
// there's a flow from element #3 to matcher #1. Such a flow would also
|
||||||
|
// be redundantly represented in the right_ vector as right_[1] == 3.
|
||||||
|
// Elements of left_ and right_ are either kUnused or mutually
|
||||||
|
// referent. Mutually referent means that left_[right_[i]] = i and
|
||||||
|
// right_[left_[i]] = i.
|
||||||
|
::std::vector<size_t> left_;
|
||||||
|
::std::vector<size_t> right_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(MaxBipartiteMatchState);
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t MaxBipartiteMatchState::kUnused;
|
||||||
|
|
||||||
|
GTEST_API_ ElementMatcherPairs
|
||||||
|
FindMaxBipartiteMatching(const MatchMatrix& g) {
|
||||||
|
return MaxBipartiteMatchState(g).Compute();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
|
||||||
|
::std::ostream* stream) {
|
||||||
|
typedef ElementMatcherPairs::const_iterator Iter;
|
||||||
|
::std::ostream& os = *stream;
|
||||||
|
os << "{";
|
||||||
|
const char *sep = "";
|
||||||
|
for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
|
||||||
|
os << sep << "\n ("
|
||||||
|
<< "element #" << it->first << ", "
|
||||||
|
<< "matcher #" << it->second << ")";
|
||||||
|
sep = ",";
|
||||||
|
}
|
||||||
|
os << "\n}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tries to find a pairing, and explains the result.
|
||||||
|
GTEST_API_ bool FindPairing(const MatchMatrix& matrix,
|
||||||
|
MatchResultListener* listener) {
|
||||||
|
ElementMatcherPairs matches = FindMaxBipartiteMatching(matrix);
|
||||||
|
|
||||||
|
size_t max_flow = matches.size();
|
||||||
|
bool result = (max_flow == matrix.RhsSize());
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
if (listener->IsInterested()) {
|
||||||
|
*listener << "where no permutation of the elements can "
|
||||||
|
"satisfy all matchers, and the closest match is "
|
||||||
|
<< max_flow << " of " << matrix.RhsSize()
|
||||||
|
<< " matchers with the pairings:\n";
|
||||||
|
LogElementMatcherPairVec(matches, listener->stream());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches.size() > 1) {
|
||||||
|
if (listener->IsInterested()) {
|
||||||
|
const char *sep = "where:\n";
|
||||||
|
for (size_t mi = 0; mi < matches.size(); ++mi) {
|
||||||
|
*listener << sep << " - element #" << matches[mi].first
|
||||||
|
<< " is matched by matcher #" << matches[mi].second;
|
||||||
|
sep = ",\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchMatrix::NextGraph() {
|
||||||
|
for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
|
||||||
|
for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
|
||||||
|
char& b = matched_[SpaceIndex(ilhs, irhs)];
|
||||||
|
if (!b) {
|
||||||
|
b = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
b = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatchMatrix::Randomize() {
|
||||||
|
for (size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
|
||||||
|
for (size_t irhs = 0; irhs < RhsSize(); ++irhs) {
|
||||||
|
char& b = matched_[SpaceIndex(ilhs, irhs)];
|
||||||
|
b = static_cast<char>(rand() & 1); // NOLINT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string MatchMatrix::DebugString() const {
|
||||||
|
::std::stringstream ss;
|
||||||
|
const char *sep = "";
|
||||||
|
for (size_t i = 0; i < LhsSize(); ++i) {
|
||||||
|
ss << sep;
|
||||||
|
for (size_t j = 0; j < RhsSize(); ++j) {
|
||||||
|
ss << HasEdge(i, j);
|
||||||
|
}
|
||||||
|
sep = ";";
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
|
||||||
|
::std::ostream* os) const {
|
||||||
|
if (matcher_describers_.empty()) {
|
||||||
|
*os << "is empty";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (matcher_describers_.size() == 1) {
|
||||||
|
*os << "has " << Elements(1) << " and that element ";
|
||||||
|
matcher_describers_[0]->DescribeTo(os);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*os << "has " << Elements(matcher_describers_.size())
|
||||||
|
<< " and there exists some permutation of elements such that:\n";
|
||||||
|
const char* sep = "";
|
||||||
|
for (size_t i = 0; i != matcher_describers_.size(); ++i) {
|
||||||
|
*os << sep << " - element #" << i << " ";
|
||||||
|
matcher_describers_[i]->DescribeTo(os);
|
||||||
|
sep = ", and\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
|
||||||
|
::std::ostream* os) const {
|
||||||
|
if (matcher_describers_.empty()) {
|
||||||
|
*os << "isn't empty";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (matcher_describers_.size() == 1) {
|
||||||
|
*os << "doesn't have " << Elements(1)
|
||||||
|
<< ", or has " << Elements(1) << " that ";
|
||||||
|
matcher_describers_[0]->DescribeNegationTo(os);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*os << "doesn't have " << Elements(matcher_describers_.size())
|
||||||
|
<< ", or there exists no permutation of elements such that:\n";
|
||||||
|
const char* sep = "";
|
||||||
|
for (size_t i = 0; i != matcher_describers_.size(); ++i) {
|
||||||
|
*os << sep << " - element #" << i << " ";
|
||||||
|
matcher_describers_[i]->DescribeTo(os);
|
||||||
|
sep = ", and\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks that all matchers match at least one element, and that all
|
||||||
|
// elements match at least one matcher. This enables faster matching
|
||||||
|
// and better error reporting.
|
||||||
|
// Returns false, writing an explanation to 'listener', if and only
|
||||||
|
// if the success criteria are not met.
|
||||||
|
bool UnorderedElementsAreMatcherImplBase::
|
||||||
|
VerifyAllElementsAndMatchersAreMatched(
|
||||||
|
const ::std::vector<string>& element_printouts,
|
||||||
|
const MatchMatrix& matrix,
|
||||||
|
MatchResultListener* listener) const {
|
||||||
|
bool result = true;
|
||||||
|
::std::vector<char> element_matched(matrix.LhsSize(), 0);
|
||||||
|
::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
|
||||||
|
|
||||||
|
for (size_t ilhs = 0; ilhs < matrix.LhsSize(); ilhs++) {
|
||||||
|
for (size_t irhs = 0; irhs < matrix.RhsSize(); irhs++) {
|
||||||
|
char matched = matrix.HasEdge(ilhs, irhs);
|
||||||
|
element_matched[ilhs] |= matched;
|
||||||
|
matcher_matched[irhs] |= matched;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char* sep =
|
||||||
|
"where the following matchers don't match any elements:\n";
|
||||||
|
for (size_t mi = 0; mi < matcher_matched.size(); ++mi) {
|
||||||
|
if (matcher_matched[mi])
|
||||||
|
continue;
|
||||||
|
result = false;
|
||||||
|
if (listener->IsInterested()) {
|
||||||
|
*listener << sep << "matcher #" << mi << ": ";
|
||||||
|
matcher_describers_[mi]->DescribeTo(listener->stream());
|
||||||
|
sep = ",\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char* sep =
|
||||||
|
"where the following elements don't match any matchers:\n";
|
||||||
|
const char* outer_sep = "";
|
||||||
|
if (!result) {
|
||||||
|
outer_sep = "\nand ";
|
||||||
|
}
|
||||||
|
for (size_t ei = 0; ei < element_matched.size(); ++ei) {
|
||||||
|
if (element_matched[ei])
|
||||||
|
continue;
|
||||||
|
result = false;
|
||||||
|
if (listener->IsInterested()) {
|
||||||
|
*listener << outer_sep << sep << "element #" << ei << ": "
|
||||||
|
<< element_printouts[ei];
|
||||||
|
sep = ",\n";
|
||||||
|
outer_sep = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace testing
|
||||||
813
gmock/src/gmock-spec-builders.cc
Normal file
813
gmock/src/gmock-spec-builders.cc
Normal file
@@ -0,0 +1,813 @@
|
|||||||
|
// Copyright 2007, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
|
//
|
||||||
|
// This file implements the spec builder syntax (ON_CALL and
|
||||||
|
// EXPECT_CALL).
|
||||||
|
|
||||||
|
#include "gmock/gmock-spec-builders.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <iostream> // NOLINT
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC
|
||||||
|
# include <unistd.h> // NOLINT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Protects the mock object registry (in class Mock), all function
|
||||||
|
// mockers, and all expectations.
|
||||||
|
GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
|
||||||
|
|
||||||
|
// Logs a message including file and line number information.
|
||||||
|
GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity,
|
||||||
|
const char* file, int line,
|
||||||
|
const string& message) {
|
||||||
|
::std::ostringstream s;
|
||||||
|
s << file << ":" << line << ": " << message << ::std::endl;
|
||||||
|
Log(severity, s.str(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs an ExpectationBase object.
|
||||||
|
ExpectationBase::ExpectationBase(const char* a_file,
|
||||||
|
int a_line,
|
||||||
|
const string& a_source_text)
|
||||||
|
: file_(a_file),
|
||||||
|
line_(a_line),
|
||||||
|
source_text_(a_source_text),
|
||||||
|
cardinality_specified_(false),
|
||||||
|
cardinality_(Exactly(1)),
|
||||||
|
call_count_(0),
|
||||||
|
retired_(false),
|
||||||
|
extra_matcher_specified_(false),
|
||||||
|
repeated_action_specified_(false),
|
||||||
|
retires_on_saturation_(false),
|
||||||
|
last_clause_(kNone),
|
||||||
|
action_count_checked_(false) {}
|
||||||
|
|
||||||
|
// Destructs an ExpectationBase object.
|
||||||
|
ExpectationBase::~ExpectationBase() {}
|
||||||
|
|
||||||
|
// Explicitly specifies the cardinality of this expectation. Used by
|
||||||
|
// the subclasses to implement the .Times() clause.
|
||||||
|
void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) {
|
||||||
|
cardinality_specified_ = true;
|
||||||
|
cardinality_ = a_cardinality;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retires all pre-requisites of this expectation.
|
||||||
|
void ExpectationBase::RetireAllPreRequisites()
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||||
|
if (is_retired()) {
|
||||||
|
// We can take this short-cut as we never retire an expectation
|
||||||
|
// until we have retired all its pre-requisites.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
|
ExpectationBase* const prerequisite = it->expectation_base().get();
|
||||||
|
if (!prerequisite->is_retired()) {
|
||||||
|
prerequisite->RetireAllPreRequisites();
|
||||||
|
prerequisite->Retire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true iff all pre-requisites of this expectation have been
|
||||||
|
// satisfied.
|
||||||
|
bool ExpectationBase::AllPrerequisitesAreSatisfied() const
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||||
|
g_gmock_mutex.AssertHeld();
|
||||||
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
|
if (!(it->expectation_base()->IsSatisfied()) ||
|
||||||
|
!(it->expectation_base()->AllPrerequisitesAreSatisfied()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds unsatisfied pre-requisites of this expectation to 'result'.
|
||||||
|
void ExpectationBase::FindUnsatisfiedPrerequisites(ExpectationSet* result) const
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||||
|
g_gmock_mutex.AssertHeld();
|
||||||
|
for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
|
||||||
|
it != immediate_prerequisites_.end(); ++it) {
|
||||||
|
if (it->expectation_base()->IsSatisfied()) {
|
||||||
|
// If *it is satisfied and has a call count of 0, some of its
|
||||||
|
// pre-requisites may not be satisfied yet.
|
||||||
|
if (it->expectation_base()->call_count_ == 0) {
|
||||||
|
it->expectation_base()->FindUnsatisfiedPrerequisites(result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Now that we know *it is unsatisfied, we are not so interested
|
||||||
|
// in whether its pre-requisites are satisfied. Therefore we
|
||||||
|
// don't recursively call FindUnsatisfiedPrerequisites() here.
|
||||||
|
*result += *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes how many times a function call matching this
|
||||||
|
// expectation has occurred.
|
||||||
|
void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||||
|
g_gmock_mutex.AssertHeld();
|
||||||
|
|
||||||
|
// Describes how many times the function is expected to be called.
|
||||||
|
*os << " Expected: to be ";
|
||||||
|
cardinality().DescribeTo(os);
|
||||||
|
*os << "\n Actual: ";
|
||||||
|
Cardinality::DescribeActualCallCountTo(call_count(), os);
|
||||||
|
|
||||||
|
// Describes the state of the expectation (e.g. is it satisfied?
|
||||||
|
// is it active?).
|
||||||
|
*os << " - " << (IsOverSaturated() ? "over-saturated" :
|
||||||
|
IsSaturated() ? "saturated" :
|
||||||
|
IsSatisfied() ? "satisfied" : "unsatisfied")
|
||||||
|
<< " and "
|
||||||
|
<< (is_retired() ? "retired" : "active");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks the action count (i.e. the number of WillOnce() and
|
||||||
|
// WillRepeatedly() clauses) against the cardinality if this hasn't
|
||||||
|
// been done before. Prints a warning if there are too many or too
|
||||||
|
// few actions.
|
||||||
|
void ExpectationBase::CheckActionCountIfNotDone() const
|
||||||
|
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||||
|
bool should_check = false;
|
||||||
|
{
|
||||||
|
MutexLock l(&mutex_);
|
||||||
|
if (!action_count_checked_) {
|
||||||
|
action_count_checked_ = true;
|
||||||
|
should_check = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_check) {
|
||||||
|
if (!cardinality_specified_) {
|
||||||
|
// The cardinality was inferred - no need to check the action
|
||||||
|
// count against it.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The cardinality was explicitly specified.
|
||||||
|
const int action_count = static_cast<int>(untyped_actions_.size());
|
||||||
|
const int upper_bound = cardinality().ConservativeUpperBound();
|
||||||
|
const int lower_bound = cardinality().ConservativeLowerBound();
|
||||||
|
bool too_many; // True if there are too many actions, or false
|
||||||
|
// if there are too few.
|
||||||
|
if (action_count > upper_bound ||
|
||||||
|
(action_count == upper_bound && repeated_action_specified_)) {
|
||||||
|
too_many = true;
|
||||||
|
} else if (0 < action_count && action_count < lower_bound &&
|
||||||
|
!repeated_action_specified_) {
|
||||||
|
too_many = false;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
::std::stringstream ss;
|
||||||
|
DescribeLocationTo(&ss);
|
||||||
|
ss << "Too " << (too_many ? "many" : "few")
|
||||||
|
<< " actions specified in " << source_text() << "...\n"
|
||||||
|
<< "Expected to be ";
|
||||||
|
cardinality().DescribeTo(&ss);
|
||||||
|
ss << ", but has " << (too_many ? "" : "only ")
|
||||||
|
<< action_count << " WillOnce()"
|
||||||
|
<< (action_count == 1 ? "" : "s");
|
||||||
|
if (repeated_action_specified_) {
|
||||||
|
ss << " and a WillRepeatedly()";
|
||||||
|
}
|
||||||
|
ss << ".";
|
||||||
|
Log(kWarning, ss.str(), -1); // -1 means "don't print stack trace".
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the .Times() clause.
|
||||||
|
void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
|
||||||
|
if (last_clause_ == kTimes) {
|
||||||
|
ExpectSpecProperty(false,
|
||||||
|
".Times() cannot appear "
|
||||||
|
"more than once in an EXPECT_CALL().");
|
||||||
|
} else {
|
||||||
|
ExpectSpecProperty(last_clause_ < kTimes,
|
||||||
|
".Times() cannot appear after "
|
||||||
|
".InSequence(), .WillOnce(), .WillRepeatedly(), "
|
||||||
|
"or .RetiresOnSaturation().");
|
||||||
|
}
|
||||||
|
last_clause_ = kTimes;
|
||||||
|
|
||||||
|
SpecifyCardinality(a_cardinality);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Points to the implicit sequence introduced by a living InSequence
|
||||||
|
// object (if any) in the current thread or NULL.
|
||||||
|
GTEST_API_ ThreadLocal<Sequence*> g_gmock_implicit_sequence;
|
||||||
|
|
||||||
|
// Reports an uninteresting call (whose description is in msg) in the
|
||||||
|
// manner specified by 'reaction'.
|
||||||
|
void ReportUninterestingCall(CallReaction reaction, const string& msg) {
|
||||||
|
switch (reaction) {
|
||||||
|
case kAllow:
|
||||||
|
Log(kInfo, msg, 3);
|
||||||
|
break;
|
||||||
|
case kWarn:
|
||||||
|
Log(kWarning, msg, 3);
|
||||||
|
break;
|
||||||
|
default: // FAIL
|
||||||
|
Expect(false, NULL, -1, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UntypedFunctionMockerBase::UntypedFunctionMockerBase()
|
||||||
|
: mock_obj_(NULL), name_("") {}
|
||||||
|
|
||||||
|
UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {}
|
||||||
|
|
||||||
|
// Sets the mock object this mock method belongs to, and registers
|
||||||
|
// this information in the global mock registry. Will be called
|
||||||
|
// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
|
||||||
|
// method.
|
||||||
|
void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
|
{
|
||||||
|
MutexLock l(&g_gmock_mutex);
|
||||||
|
mock_obj_ = mock_obj;
|
||||||
|
}
|
||||||
|
Mock::Register(mock_obj, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the mock object this mock method belongs to, and sets the name
|
||||||
|
// of the mock function. Will be called upon each invocation of this
|
||||||
|
// mock function.
|
||||||
|
void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj,
|
||||||
|
const char* name)
|
||||||
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
|
// We protect name_ under g_gmock_mutex in case this mock function
|
||||||
|
// is called from two threads concurrently.
|
||||||
|
MutexLock l(&g_gmock_mutex);
|
||||||
|
mock_obj_ = mock_obj;
|
||||||
|
name_ = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the name of the function being mocked. Must be called
|
||||||
|
// after RegisterOwner() or SetOwnerAndName() has been called.
|
||||||
|
const void* UntypedFunctionMockerBase::MockObject() const
|
||||||
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
|
const void* mock_obj;
|
||||||
|
{
|
||||||
|
// We protect mock_obj_ under g_gmock_mutex in case this mock
|
||||||
|
// function is called from two threads concurrently.
|
||||||
|
MutexLock l(&g_gmock_mutex);
|
||||||
|
Assert(mock_obj_ != NULL, __FILE__, __LINE__,
|
||||||
|
"MockObject() must not be called before RegisterOwner() or "
|
||||||
|
"SetOwnerAndName() has been called.");
|
||||||
|
mock_obj = mock_obj_;
|
||||||
|
}
|
||||||
|
return mock_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the name of this mock method. Must be called after
|
||||||
|
// SetOwnerAndName() has been called.
|
||||||
|
const char* UntypedFunctionMockerBase::Name() const
|
||||||
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
|
const char* name;
|
||||||
|
{
|
||||||
|
// We protect name_ under g_gmock_mutex in case this mock
|
||||||
|
// function is called from two threads concurrently.
|
||||||
|
MutexLock l(&g_gmock_mutex);
|
||||||
|
Assert(name_ != NULL, __FILE__, __LINE__,
|
||||||
|
"Name() must not be called before SetOwnerAndName() has "
|
||||||
|
"been called.");
|
||||||
|
name = name_;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the result of invoking this mock function with the given
|
||||||
|
// arguments, prints it, and returns it. The caller is responsible
|
||||||
|
// for deleting the result.
|
||||||
|
const UntypedActionResultHolderBase*
|
||||||
|
UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args)
|
||||||
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
|
if (untyped_expectations_.size() == 0) {
|
||||||
|
// No expectation is set on this mock method - we have an
|
||||||
|
// uninteresting call.
|
||||||
|
|
||||||
|
// We must get Google Mock's reaction on uninteresting calls
|
||||||
|
// made on this mock object BEFORE performing the action,
|
||||||
|
// because the action may DELETE the mock object and make the
|
||||||
|
// following expression meaningless.
|
||||||
|
const CallReaction reaction =
|
||||||
|
Mock::GetReactionOnUninterestingCalls(MockObject());
|
||||||
|
|
||||||
|
// True iff we need to print this call's arguments and return
|
||||||
|
// value. This definition must be kept in sync with
|
||||||
|
// the behavior of ReportUninterestingCall().
|
||||||
|
const bool need_to_report_uninteresting_call =
|
||||||
|
// If the user allows this uninteresting call, we print it
|
||||||
|
// only when he wants informational messages.
|
||||||
|
reaction == kAllow ? LogIsVisible(kInfo) :
|
||||||
|
// If the user wants this to be a warning, we print it only
|
||||||
|
// when he wants to see warnings.
|
||||||
|
reaction == kWarn ? LogIsVisible(kWarning) :
|
||||||
|
// Otherwise, the user wants this to be an error, and we
|
||||||
|
// should always print detailed information in the error.
|
||||||
|
true;
|
||||||
|
|
||||||
|
if (!need_to_report_uninteresting_call) {
|
||||||
|
// Perform the action without printing the call information.
|
||||||
|
return this->UntypedPerformDefaultAction(untyped_args, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warns about the uninteresting call.
|
||||||
|
::std::stringstream ss;
|
||||||
|
this->UntypedDescribeUninterestingCall(untyped_args, &ss);
|
||||||
|
|
||||||
|
// Calculates the function result.
|
||||||
|
const UntypedActionResultHolderBase* const result =
|
||||||
|
this->UntypedPerformDefaultAction(untyped_args, ss.str());
|
||||||
|
|
||||||
|
// Prints the function result.
|
||||||
|
if (result != NULL)
|
||||||
|
result->PrintAsActionResult(&ss);
|
||||||
|
|
||||||
|
ReportUninterestingCall(reaction, ss.str());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_excessive = false;
|
||||||
|
::std::stringstream ss;
|
||||||
|
::std::stringstream why;
|
||||||
|
::std::stringstream loc;
|
||||||
|
const void* untyped_action = NULL;
|
||||||
|
|
||||||
|
// The UntypedFindMatchingExpectation() function acquires and
|
||||||
|
// releases g_gmock_mutex.
|
||||||
|
const ExpectationBase* const untyped_expectation =
|
||||||
|
this->UntypedFindMatchingExpectation(
|
||||||
|
untyped_args, &untyped_action, &is_excessive,
|
||||||
|
&ss, &why);
|
||||||
|
const bool found = untyped_expectation != NULL;
|
||||||
|
|
||||||
|
// True iff we need to print the call's arguments and return value.
|
||||||
|
// This definition must be kept in sync with the uses of Expect()
|
||||||
|
// and Log() in this function.
|
||||||
|
const bool need_to_report_call =
|
||||||
|
!found || is_excessive || LogIsVisible(kInfo);
|
||||||
|
if (!need_to_report_call) {
|
||||||
|
// Perform the action without printing the call information.
|
||||||
|
return
|
||||||
|
untyped_action == NULL ?
|
||||||
|
this->UntypedPerformDefaultAction(untyped_args, "") :
|
||||||
|
this->UntypedPerformAction(untyped_action, untyped_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << " Function call: " << Name();
|
||||||
|
this->UntypedPrintArgs(untyped_args, &ss);
|
||||||
|
|
||||||
|
// In case the action deletes a piece of the expectation, we
|
||||||
|
// generate the message beforehand.
|
||||||
|
if (found && !is_excessive) {
|
||||||
|
untyped_expectation->DescribeLocationTo(&loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
const UntypedActionResultHolderBase* const result =
|
||||||
|
untyped_action == NULL ?
|
||||||
|
this->UntypedPerformDefaultAction(untyped_args, ss.str()) :
|
||||||
|
this->UntypedPerformAction(untyped_action, untyped_args);
|
||||||
|
if (result != NULL)
|
||||||
|
result->PrintAsActionResult(&ss);
|
||||||
|
ss << "\n" << why.str();
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
// No expectation matches this call - reports a failure.
|
||||||
|
Expect(false, NULL, -1, ss.str());
|
||||||
|
} else if (is_excessive) {
|
||||||
|
// We had an upper-bound violation and the failure message is in ss.
|
||||||
|
Expect(false, untyped_expectation->file(),
|
||||||
|
untyped_expectation->line(), ss.str());
|
||||||
|
} else {
|
||||||
|
// We had an expected call and the matching expectation is
|
||||||
|
// described in ss.
|
||||||
|
Log(kInfo, loc.str() + ss.str(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns an Expectation object that references and co-owns exp,
|
||||||
|
// which must be an expectation on this mock function.
|
||||||
|
Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
|
||||||
|
for (UntypedExpectations::const_iterator it =
|
||||||
|
untyped_expectations_.begin();
|
||||||
|
it != untyped_expectations_.end(); ++it) {
|
||||||
|
if (it->get() == exp) {
|
||||||
|
return Expectation(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
|
||||||
|
return Expectation();
|
||||||
|
// The above statement is just to make the code compile, and will
|
||||||
|
// never be executed.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies that all expectations on this mock function have been
|
||||||
|
// satisfied. Reports one or more Google Test non-fatal failures
|
||||||
|
// and returns false if not.
|
||||||
|
bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
|
||||||
|
g_gmock_mutex.AssertHeld();
|
||||||
|
bool expectations_met = true;
|
||||||
|
for (UntypedExpectations::const_iterator it =
|
||||||
|
untyped_expectations_.begin();
|
||||||
|
it != untyped_expectations_.end(); ++it) {
|
||||||
|
ExpectationBase* const untyped_expectation = it->get();
|
||||||
|
if (untyped_expectation->IsOverSaturated()) {
|
||||||
|
// There was an upper-bound violation. Since the error was
|
||||||
|
// already reported when it occurred, there is no need to do
|
||||||
|
// anything here.
|
||||||
|
expectations_met = false;
|
||||||
|
} else if (!untyped_expectation->IsSatisfied()) {
|
||||||
|
expectations_met = false;
|
||||||
|
::std::stringstream ss;
|
||||||
|
ss << "Actual function call count doesn't match "
|
||||||
|
<< untyped_expectation->source_text() << "...\n";
|
||||||
|
// No need to show the source file location of the expectation
|
||||||
|
// in the description, as the Expect() call that follows already
|
||||||
|
// takes care of it.
|
||||||
|
untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
|
||||||
|
untyped_expectation->DescribeCallCountTo(&ss);
|
||||||
|
Expect(false, untyped_expectation->file(),
|
||||||
|
untyped_expectation->line(), ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleting our expectations may trigger other mock objects to be deleted, for
|
||||||
|
// example if an action contains a reference counted smart pointer to that
|
||||||
|
// mock object, and that is the last reference. So if we delete our
|
||||||
|
// expectations within the context of the global mutex we may deadlock when
|
||||||
|
// this method is called again. Instead, make a copy of the set of
|
||||||
|
// expectations to delete, clear our set within the mutex, and then clear the
|
||||||
|
// copied set outside of it.
|
||||||
|
UntypedExpectations expectations_to_delete;
|
||||||
|
untyped_expectations_.swap(expectations_to_delete);
|
||||||
|
|
||||||
|
g_gmock_mutex.Unlock();
|
||||||
|
expectations_to_delete.clear();
|
||||||
|
g_gmock_mutex.Lock();
|
||||||
|
|
||||||
|
return expectations_met;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Class Mock.
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers;
|
||||||
|
|
||||||
|
// The current state of a mock object. Such information is needed for
|
||||||
|
// detecting leaked mock objects and explicitly verifying a mock's
|
||||||
|
// expectations.
|
||||||
|
struct MockObjectState {
|
||||||
|
MockObjectState()
|
||||||
|
: first_used_file(NULL), first_used_line(-1), leakable(false) {}
|
||||||
|
|
||||||
|
// Where in the source file an ON_CALL or EXPECT_CALL is first
|
||||||
|
// invoked on this mock object.
|
||||||
|
const char* first_used_file;
|
||||||
|
int first_used_line;
|
||||||
|
::std::string first_used_test_case;
|
||||||
|
::std::string first_used_test;
|
||||||
|
bool leakable; // true iff it's OK to leak the object.
|
||||||
|
FunctionMockers function_mockers; // All registered methods of the object.
|
||||||
|
};
|
||||||
|
|
||||||
|
// A global registry holding the state of all mock objects that are
|
||||||
|
// alive. A mock object is added to this registry the first time
|
||||||
|
// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it. It
|
||||||
|
// is removed from the registry in the mock object's destructor.
|
||||||
|
class MockObjectRegistry {
|
||||||
|
public:
|
||||||
|
// Maps a mock object (identified by its address) to its state.
|
||||||
|
typedef std::map<const void*, MockObjectState> StateMap;
|
||||||
|
|
||||||
|
// This destructor will be called when a program exits, after all
|
||||||
|
// tests in it have been run. By then, there should be no mock
|
||||||
|
// object alive. Therefore we report any living object as test
|
||||||
|
// failure, unless the user explicitly asked us to ignore it.
|
||||||
|
~MockObjectRegistry() {
|
||||||
|
// "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
|
||||||
|
// a macro.
|
||||||
|
|
||||||
|
if (!GMOCK_FLAG(catch_leaked_mocks))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int leaked_count = 0;
|
||||||
|
for (StateMap::const_iterator it = states_.begin(); it != states_.end();
|
||||||
|
++it) {
|
||||||
|
if (it->second.leakable) // The user said it's fine to leak this object.
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO(wan@google.com): Print the type of the leaked object.
|
||||||
|
// This can help the user identify the leaked object.
|
||||||
|
std::cout << "\n";
|
||||||
|
const MockObjectState& state = it->second;
|
||||||
|
std::cout << internal::FormatFileLocation(state.first_used_file,
|
||||||
|
state.first_used_line);
|
||||||
|
std::cout << " ERROR: this mock object";
|
||||||
|
if (state.first_used_test != "") {
|
||||||
|
std::cout << " (used in test " << state.first_used_test_case << "."
|
||||||
|
<< state.first_used_test << ")";
|
||||||
|
}
|
||||||
|
std::cout << " should be deleted but never is. Its address is @"
|
||||||
|
<< it->first << ".";
|
||||||
|
leaked_count++;
|
||||||
|
}
|
||||||
|
if (leaked_count > 0) {
|
||||||
|
std::cout << "\nERROR: " << leaked_count
|
||||||
|
<< " leaked mock " << (leaked_count == 1 ? "object" : "objects")
|
||||||
|
<< " found at program exit.\n";
|
||||||
|
std::cout.flush();
|
||||||
|
::std::cerr.flush();
|
||||||
|
// RUN_ALL_TESTS() has already returned when this destructor is
|
||||||
|
// called. Therefore we cannot use the normal Google Test
|
||||||
|
// failure reporting mechanism.
|
||||||
|
_exit(1); // We cannot call exit() as it is not reentrant and
|
||||||
|
// may already have been called.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMap& states() { return states_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
StateMap states_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Protected by g_gmock_mutex.
|
||||||
|
MockObjectRegistry g_mock_object_registry;
|
||||||
|
|
||||||
|
// Maps a mock object to the reaction Google Mock should have when an
|
||||||
|
// uninteresting method is called. Protected by g_gmock_mutex.
|
||||||
|
std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction;
|
||||||
|
|
||||||
|
// Sets the reaction Google Mock should have when an uninteresting
|
||||||
|
// method of the given mock object is called.
|
||||||
|
void SetReactionOnUninterestingCalls(const void* mock_obj,
|
||||||
|
internal::CallReaction reaction)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_uninteresting_call_reaction[mock_obj] = reaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Tells Google Mock to allow uninteresting calls on the given mock
|
||||||
|
// object.
|
||||||
|
void Mock::AllowUninterestingCalls(const void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
SetReactionOnUninterestingCalls(mock_obj, internal::kAllow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock to warn the user about uninteresting calls on the
|
||||||
|
// given mock object.
|
||||||
|
void Mock::WarnUninterestingCalls(const void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
SetReactionOnUninterestingCalls(mock_obj, internal::kWarn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock to fail uninteresting calls on the given mock
|
||||||
|
// object.
|
||||||
|
void Mock::FailUninterestingCalls(const void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
SetReactionOnUninterestingCalls(mock_obj, internal::kFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock the given mock object is being destroyed and its
|
||||||
|
// entry in the call-reaction table should be removed.
|
||||||
|
void Mock::UnregisterCallReaction(const void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_uninteresting_call_reaction.erase(mock_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the reaction Google Mock will have on uninteresting calls
|
||||||
|
// made on the given mock object.
|
||||||
|
internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
||||||
|
const void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
return (g_uninteresting_call_reaction.count(mock_obj) == 0) ?
|
||||||
|
internal::kDefault : g_uninteresting_call_reaction[mock_obj];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock to ignore mock_obj when checking for leaked mock
|
||||||
|
// objects.
|
||||||
|
void Mock::AllowLeak(const void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_mock_object_registry.states()[mock_obj].leakable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies and clears all expectations on the given mock object. If
|
||||||
|
// the expectations aren't satisfied, generates one or more Google
|
||||||
|
// Test non-fatal failures and returns false.
|
||||||
|
bool Mock::VerifyAndClearExpectations(void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies all expectations on the given mock object and clears its
|
||||||
|
// default actions and expectations. Returns true iff the
|
||||||
|
// verification was successful.
|
||||||
|
bool Mock::VerifyAndClear(void* mock_obj)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
ClearDefaultActionsLocked(mock_obj);
|
||||||
|
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies and clears all expectations on the given mock object. If
|
||||||
|
// the expectations aren't satisfied, generates one or more Google
|
||||||
|
// Test non-fatal failures and returns false.
|
||||||
|
bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj)
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
|
||||||
|
internal::g_gmock_mutex.AssertHeld();
|
||||||
|
if (g_mock_object_registry.states().count(mock_obj) == 0) {
|
||||||
|
// No EXPECT_CALL() was set on the given mock object.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifies and clears the expectations on each mock method in the
|
||||||
|
// given mock object.
|
||||||
|
bool expectations_met = true;
|
||||||
|
FunctionMockers& mockers =
|
||||||
|
g_mock_object_registry.states()[mock_obj].function_mockers;
|
||||||
|
for (FunctionMockers::const_iterator it = mockers.begin();
|
||||||
|
it != mockers.end(); ++it) {
|
||||||
|
if (!(*it)->VerifyAndClearExpectationsLocked()) {
|
||||||
|
expectations_met = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't clear the content of mockers, as they may still be
|
||||||
|
// needed by ClearDefaultActionsLocked().
|
||||||
|
return expectations_met;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers a mock object and a mock method it owns.
|
||||||
|
void Mock::Register(const void* mock_obj,
|
||||||
|
internal::UntypedFunctionMockerBase* mocker)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tells Google Mock where in the source code mock_obj is used in an
|
||||||
|
// ON_CALL or EXPECT_CALL. In case mock_obj is leaked, this
|
||||||
|
// information helps the user identify which object it is.
|
||||||
|
void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
|
||||||
|
const char* file, int line)
|
||||||
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
|
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||||
|
MockObjectState& state = g_mock_object_registry.states()[mock_obj];
|
||||||
|
if (state.first_used_file == NULL) {
|
||||||
|
state.first_used_file = file;
|
||||||
|
state.first_used_line = line;
|
||||||
|
const TestInfo* const test_info =
|
||||||
|
UnitTest::GetInstance()->current_test_info();
|
||||||
|
if (test_info != NULL) {
|
||||||
|
// TODO(wan@google.com): record the test case name when the
|
||||||
|
// ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or
|
||||||
|
// TearDownTestCase().
|
||||||
|
state.first_used_test_case = test_info->test_case_name();
|
||||||
|
state.first_used_test = test_info->name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregisters a mock method; removes the owning mock object from the
|
||||||
|
// registry when the last mock method associated with it has been
|
||||||
|
// unregistered. This is called only in the destructor of
|
||||||
|
// FunctionMockerBase.
|
||||||
|
void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
|
||||||
|
internal::g_gmock_mutex.AssertHeld();
|
||||||
|
for (MockObjectRegistry::StateMap::iterator it =
|
||||||
|
g_mock_object_registry.states().begin();
|
||||||
|
it != g_mock_object_registry.states().end(); ++it) {
|
||||||
|
FunctionMockers& mockers = it->second.function_mockers;
|
||||||
|
if (mockers.erase(mocker) > 0) {
|
||||||
|
// mocker was in mockers and has been just removed.
|
||||||
|
if (mockers.empty()) {
|
||||||
|
g_mock_object_registry.states().erase(it);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears all ON_CALL()s set on the given mock object.
|
||||||
|
void Mock::ClearDefaultActionsLocked(void* mock_obj)
|
||||||
|
GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex) {
|
||||||
|
internal::g_gmock_mutex.AssertHeld();
|
||||||
|
|
||||||
|
if (g_mock_object_registry.states().count(mock_obj) == 0) {
|
||||||
|
// No ON_CALL() was set on the given mock object.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears the default actions for each mock method in the given mock
|
||||||
|
// object.
|
||||||
|
FunctionMockers& mockers =
|
||||||
|
g_mock_object_registry.states()[mock_obj].function_mockers;
|
||||||
|
for (FunctionMockers::const_iterator it = mockers.begin();
|
||||||
|
it != mockers.end(); ++it) {
|
||||||
|
(*it)->ClearDefaultActionsLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't clear the content of mockers, as they may still be
|
||||||
|
// needed by VerifyAndClearExpectationsLocked().
|
||||||
|
}
|
||||||
|
|
||||||
|
Expectation::Expectation() {}
|
||||||
|
|
||||||
|
Expectation::Expectation(
|
||||||
|
const internal::linked_ptr<internal::ExpectationBase>& an_expectation_base)
|
||||||
|
: expectation_base_(an_expectation_base) {}
|
||||||
|
|
||||||
|
Expectation::~Expectation() {}
|
||||||
|
|
||||||
|
// Adds an expectation to a sequence.
|
||||||
|
void Sequence::AddExpectation(const Expectation& expectation) const {
|
||||||
|
if (*last_expectation_ != expectation) {
|
||||||
|
if (last_expectation_->expectation_base() != NULL) {
|
||||||
|
expectation.expectation_base()->immediate_prerequisites_
|
||||||
|
+= *last_expectation_;
|
||||||
|
}
|
||||||
|
*last_expectation_ = expectation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the implicit sequence if there isn't one.
|
||||||
|
InSequence::InSequence() {
|
||||||
|
if (internal::g_gmock_implicit_sequence.get() == NULL) {
|
||||||
|
internal::g_gmock_implicit_sequence.set(new Sequence);
|
||||||
|
sequence_created_ = true;
|
||||||
|
} else {
|
||||||
|
sequence_created_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes the implicit sequence if it was created by the constructor
|
||||||
|
// of this object.
|
||||||
|
InSequence::~InSequence() {
|
||||||
|
if (sequence_created_) {
|
||||||
|
delete internal::g_gmock_implicit_sequence.get();
|
||||||
|
internal::g_gmock_implicit_sequence.set(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
182
gmock/src/gmock.cc
Normal file
182
gmock/src/gmock.cc
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
|
namespace testing {
|
||||||
|
|
||||||
|
// TODO(wan@google.com): support using environment variables to
|
||||||
|
// control the flag values, like what Google Test does.
|
||||||
|
|
||||||
|
GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
|
||||||
|
"true iff Google Mock should report leaked mock objects "
|
||||||
|
"as failures.");
|
||||||
|
|
||||||
|
GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity,
|
||||||
|
"Controls how verbose Google Mock's output is."
|
||||||
|
" Valid values:\n"
|
||||||
|
" info - prints all messages.\n"
|
||||||
|
" warning - prints warnings and errors.\n"
|
||||||
|
" error - prints errors only.");
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Parses a string as a command line flag. The string should have the
|
||||||
|
// format "--gmock_flag=value". When def_optional is true, the
|
||||||
|
// "=value" part can be omitted.
|
||||||
|
//
|
||||||
|
// Returns the value of the flag, or NULL if the parsing failed.
|
||||||
|
static const char* ParseGoogleMockFlagValue(const char* str,
|
||||||
|
const char* flag,
|
||||||
|
bool def_optional) {
|
||||||
|
// str and flag must not be NULL.
|
||||||
|
if (str == NULL || flag == NULL) return NULL;
|
||||||
|
|
||||||
|
// The flag must start with "--gmock_".
|
||||||
|
const std::string flag_str = std::string("--gmock_") + flag;
|
||||||
|
const size_t flag_len = flag_str.length();
|
||||||
|
if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
|
||||||
|
|
||||||
|
// Skips the flag name.
|
||||||
|
const char* flag_end = str + flag_len;
|
||||||
|
|
||||||
|
// When def_optional is true, it's OK to not have a "=value" part.
|
||||||
|
if (def_optional && (flag_end[0] == '\0')) {
|
||||||
|
return flag_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If def_optional is true and there are more characters after the
|
||||||
|
// flag name, or if def_optional is false, there must be a '=' after
|
||||||
|
// the flag name.
|
||||||
|
if (flag_end[0] != '=') return NULL;
|
||||||
|
|
||||||
|
// Returns the string after "=".
|
||||||
|
return flag_end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a string for a Google Mock bool flag, in the form of
|
||||||
|
// "--gmock_flag=value".
|
||||||
|
//
|
||||||
|
// On success, stores the value of the flag in *value, and returns
|
||||||
|
// true. On failure, returns false without changing *value.
|
||||||
|
static bool ParseGoogleMockBoolFlag(const char* str, const char* flag,
|
||||||
|
bool* value) {
|
||||||
|
// Gets the value of the flag as a string.
|
||||||
|
const char* const value_str = ParseGoogleMockFlagValue(str, flag, true);
|
||||||
|
|
||||||
|
// Aborts if the parsing failed.
|
||||||
|
if (value_str == NULL) return false;
|
||||||
|
|
||||||
|
// Converts the string value to a bool.
|
||||||
|
*value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a string for a Google Mock string flag, in the form of
|
||||||
|
// "--gmock_flag=value".
|
||||||
|
//
|
||||||
|
// On success, stores the value of the flag in *value, and returns
|
||||||
|
// true. On failure, returns false without changing *value.
|
||||||
|
static bool ParseGoogleMockStringFlag(const char* str, const char* flag,
|
||||||
|
std::string* value) {
|
||||||
|
// Gets the value of the flag as a string.
|
||||||
|
const char* const value_str = ParseGoogleMockFlagValue(str, flag, false);
|
||||||
|
|
||||||
|
// Aborts if the parsing failed.
|
||||||
|
if (value_str == NULL) return false;
|
||||||
|
|
||||||
|
// Sets *value to the value of the flag.
|
||||||
|
*value = value_str;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The internal implementation of InitGoogleMock().
|
||||||
|
//
|
||||||
|
// The type parameter CharType can be instantiated to either char or
|
||||||
|
// wchar_t.
|
||||||
|
template <typename CharType>
|
||||||
|
void InitGoogleMockImpl(int* argc, CharType** argv) {
|
||||||
|
// Makes sure Google Test is initialized. InitGoogleTest() is
|
||||||
|
// idempotent, so it's fine if the user has already called it.
|
||||||
|
InitGoogleTest(argc, argv);
|
||||||
|
if (*argc <= 0) return;
|
||||||
|
|
||||||
|
for (int i = 1; i != *argc; i++) {
|
||||||
|
const std::string arg_string = StreamableToString(argv[i]);
|
||||||
|
const char* const arg = arg_string.c_str();
|
||||||
|
|
||||||
|
// Do we see a Google Mock flag?
|
||||||
|
if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks",
|
||||||
|
&GMOCK_FLAG(catch_leaked_mocks)) ||
|
||||||
|
ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) {
|
||||||
|
// Yes. Shift the remainder of the argv list left by one. Note
|
||||||
|
// that argv has (*argc + 1) elements, the last one always being
|
||||||
|
// NULL. The following loop moves the trailing NULL element as
|
||||||
|
// well.
|
||||||
|
for (int j = i; j != *argc; j++) {
|
||||||
|
argv[j] = argv[j + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrements the argument count.
|
||||||
|
(*argc)--;
|
||||||
|
|
||||||
|
// We also need to decrement the iterator as we just removed
|
||||||
|
// an element.
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
// Initializes Google Mock. This must be called before running the
|
||||||
|
// tests. In particular, it parses a command line for the flags that
|
||||||
|
// Google Mock recognizes. Whenever a Google Mock flag is seen, it is
|
||||||
|
// removed from argv, and *argc is decremented.
|
||||||
|
//
|
||||||
|
// No value is returned. Instead, the Google Mock flag variables are
|
||||||
|
// updated.
|
||||||
|
//
|
||||||
|
// Since Google Test is needed for Google Mock to work, this function
|
||||||
|
// also initializes Google Test and parses its flags, if that hasn't
|
||||||
|
// been done.
|
||||||
|
GTEST_API_ void InitGoogleMock(int* argc, char** argv) {
|
||||||
|
internal::InitGoogleMockImpl(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This overloaded version can be used in Windows programs compiled in
|
||||||
|
// UNICODE mode.
|
||||||
|
GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv) {
|
||||||
|
internal::InitGoogleMockImpl(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace testing
|
||||||
54
gmock/src/gmock_main.cc
Normal file
54
gmock/src/gmock_main.cc
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2008, Google Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Author: wan@google.com (Zhanyong Wan)
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which
|
||||||
|
// causes a link error when _tmain is defined in a static library and UNICODE
|
||||||
|
// is enabled. For this reason instead of _tmain, main function is used on
|
||||||
|
// Windows. See the following link to track the current status of this bug:
|
||||||
|
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464 // NOLINT
|
||||||
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
|
# include <tchar.h> // NOLINT
|
||||||
|
|
||||||
|
GTEST_API_ int _tmain(int argc, TCHAR** argv) {
|
||||||
|
#else
|
||||||
|
GTEST_API_ int main(int argc, char** argv) {
|
||||||
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
std::cout << "Running main() from gmock_main.cc\n";
|
||||||
|
// Since Google Mock depends on Google Test, InitGoogleMock() is
|
||||||
|
// also responsible for initializing Google Test. Therefore there's
|
||||||
|
// no need for calling testing::InitGoogleTest() separately.
|
||||||
|
testing::InitGoogleMock(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,5 @@
|
|||||||
#Wed Jan 04 21:49:36 PST 2017
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
|
||||||
|
|||||||
6
gradlew
vendored
6
gradlew
vendored
@@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
|
|||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD="maximum"
|
||||||
|
|
||||||
warn ( ) {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
}
|
||||||
|
|
||||||
die ( ) {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
@@ -155,7 +155,7 @@ if $cygwin ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Escape application args
|
||||||
save ( ) {
|
save () {
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
echo " "
|
echo " "
|
||||||
}
|
}
|
||||||
|
|||||||
43
hal/.styleguide
Normal file
43
hal/.styleguide
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
cppHeaderFileInclude {
|
||||||
|
\.h$
|
||||||
|
\.hpp$
|
||||||
|
\.inc$
|
||||||
|
}
|
||||||
|
|
||||||
|
cppSrcFileInclude {
|
||||||
|
\.cpp$
|
||||||
|
}
|
||||||
|
|
||||||
|
generatedFileExclude {
|
||||||
|
gmock/
|
||||||
|
ni-libraries/include/
|
||||||
|
ni-libraries/lib/
|
||||||
|
hal/src/main/native/athena/ctre/
|
||||||
|
hal/src/main/native/athena/frccansae/
|
||||||
|
hal/src/main/native/athena/visa/
|
||||||
|
hal/src/main/native/include/ctre/
|
||||||
|
UsageReporting\.h$
|
||||||
|
}
|
||||||
|
|
||||||
|
modifiableFileExclude {
|
||||||
|
wpilibj/src/arm-linux-jni/
|
||||||
|
wpilibj/src/main/native/cpp/
|
||||||
|
\.patch$
|
||||||
|
\.png$
|
||||||
|
\.py$
|
||||||
|
\.so$
|
||||||
|
}
|
||||||
|
|
||||||
|
includeOtherLibs {
|
||||||
|
^FRC_FPGA_ChipObject/
|
||||||
|
^FRC_NetworkCommunication/
|
||||||
|
^i2clib/
|
||||||
|
^llvm/
|
||||||
|
^opencv2/
|
||||||
|
^spilib/
|
||||||
|
^support/
|
||||||
|
}
|
||||||
|
|
||||||
|
includeProject {
|
||||||
|
^ctre/
|
||||||
|
}
|
||||||
330
hal/build.gradle
330
hal/build.gradle
@@ -1,160 +1,222 @@
|
|||||||
// There are two hal libraries that are built
|
apply plugin: 'cpp'
|
||||||
// - desktop which is used by simulation (gcc/msvc)
|
apply plugin: 'google-test'
|
||||||
// - athena which is used by the roborio (arm)
|
apply plugin: 'visual-studio'
|
||||||
|
apply plugin: 'edu.wpi.first.NativeUtils'
|
||||||
|
|
||||||
plugins {
|
apply from: '../config.gradle'
|
||||||
id 'cpp'
|
|
||||||
id 'maven-publish'
|
ext.addHalToLinker = { binary->
|
||||||
|
if (binary.targetPlatform.architecture.name == 'athena') {
|
||||||
|
binary.lib project: ':hal', library: 'halAthena', linkage: 'shared'
|
||||||
|
} else {
|
||||||
|
binary.lib project: ':hal', library: 'halSim', linkage: 'shared'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineWpiUtilProperties()
|
|
||||||
|
|
||||||
debugStripSetup(project)
|
|
||||||
|
|
||||||
model {
|
model {
|
||||||
components {
|
dependencyConfigs {
|
||||||
HALAthena(NativeLibrarySpec) {
|
wpiutil(DependencyConfig) {
|
||||||
targetPlatform 'roborio-arm'
|
groupId = 'edu.wpi.first.wpiutil'
|
||||||
binaries.all {
|
artifactId = 'wpiutil-cpp'
|
||||||
tasks.withType(CppCompile) {
|
headerClassifier = 'headers'
|
||||||
addNiLibraryLinks(linker, targetPlatform)
|
ext = 'zip'
|
||||||
addWpiUtilLibraryLinks(it, linker, targetPlatform)
|
version = '3.+'
|
||||||
|
sharedConfigs = [ halAthena: [], halSim: [], halDev: [], halSimTestingBaseTest: [] ]
|
||||||
|
staticConfigs = [ halSimStaticDeps: [] ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL.
|
||||||
|
// This removes the need for DllExport on a library. However, the gradle C++ builder has a bug
|
||||||
|
// where some extra symbols are added that cannot be resolved at link time. This configuration
|
||||||
|
// lets you specify specific symbols to exlude from exporting.
|
||||||
|
exportsConfigs {
|
||||||
|
halSim(ExportsConfig) {
|
||||||
|
x86ExcludeSymbols = [ '_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||||
|
'_CT??_R0?AVbad_cast',
|
||||||
|
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||||
|
'_TI5?AVfailure' ]
|
||||||
|
x64ExcludeSymbols = [ '_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||||
|
'_CT??_R0?AVbad_cast',
|
||||||
|
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||||
|
'_TI5?AVfailure' ]
|
||||||
|
}
|
||||||
|
halSimStaticDeps(ExportsConfig) {
|
||||||
|
x86SymbolFilter = { symbols->
|
||||||
|
def retList = []
|
||||||
|
symbols.each { symbol->
|
||||||
|
if (symbol.startsWith('HAL_')) {
|
||||||
|
retList << symbol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return retList
|
||||||
}
|
}
|
||||||
sources {
|
x64SymbolFilter = { symbols->
|
||||||
cpp {
|
def retList = []
|
||||||
source {
|
symbols.each { symbol->
|
||||||
srcDirs = ["lib/athena", niLibraryHeadersRoot, "lib/shared"]
|
if (symbol.startsWith('HAL_')) {
|
||||||
includes = ["**/*.cpp"]
|
retList << symbol
|
||||||
}
|
|
||||||
exportedHeaders {
|
|
||||||
srcDirs = ["include", niLibraryHeadersRoot, wpiUtilInclude]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return retList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tasks { tasks ->
|
components {
|
||||||
tasks.halZip.dependsOn tasks.HALAthenaSharedLibrary
|
if (!project.hasProperty('skipAthena')) {
|
||||||
tasks.athenaRuntimeZip.dependsOn tasks.HALAthenaSharedLibrary
|
halAthena(NativeLibrarySpec) {
|
||||||
}
|
baseName = 'wpiHal'
|
||||||
}
|
sources {
|
||||||
|
cpp {
|
||||||
task halZip(type: Zip) {
|
source {
|
||||||
description = 'Zips the HAL'
|
srcDirs = [ 'src/main/native/shared', 'src/main/native/athena' ]
|
||||||
group = 'WPILib'
|
includes = ["**/*.cpp"]
|
||||||
baseName = 'hal'
|
}
|
||||||
destinationDir = project.buildDir
|
exportedHeaders {
|
||||||
duplicatesStrategy = 'exclude'
|
srcDirs = ["src/main/native/include"]
|
||||||
|
|
||||||
// Include the shared library file and header files from this project
|
|
||||||
model {
|
|
||||||
binaries {
|
|
||||||
withType(SharedLibraryBinarySpec) { spec ->
|
|
||||||
spec.headerDirs.each {
|
|
||||||
def normalizedIt = it.toString().replace('/', '\\')
|
|
||||||
def normalizedWPIUtil = wpiUtilInclude.toString().replace('/', '\\')
|
|
||||||
// exclude the wpiUtil library, and any NI libraries (NI libraries grabbed later)
|
|
||||||
if (normalizedIt != normalizedWPIUtil) {
|
|
||||||
from(it) {
|
|
||||||
into 'include'
|
|
||||||
// We don't want to include any of the .cpp files that are in some of the header directories
|
|
||||||
exclude '**/*.cpp'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
from(spec.sharedLibraryFile) {
|
binaries.all { binary->
|
||||||
into 'lib'
|
if (binary.targetPlatform.architecture.name != 'athena') {
|
||||||
}
|
binary.buildable = false
|
||||||
from(new File(spec.sharedLibraryFile.absolutePath + ".debug")) {
|
|
||||||
into 'lib'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, include all of the shared library objects from the ni directory
|
|
||||||
from(project.file('../ni-libraries/lib')) {
|
|
||||||
into 'lib'
|
|
||||||
exclude 'genlinks'
|
|
||||||
exclude 'genlinks.bat'
|
|
||||||
exclude 'libwpi.so'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task athenaRuntimeZip(type: Zip) {
|
|
||||||
description = 'Zips the Athena Runtime libraries'
|
|
||||||
group = 'WPILib'
|
|
||||||
baseName = 'athena-runtime'
|
|
||||||
destinationDir = project.buildDir
|
|
||||||
duplicatesStrategy = 'exclude'
|
|
||||||
|
|
||||||
// Include the static library file and header files from this project
|
|
||||||
model {
|
|
||||||
binaries {
|
|
||||||
withType(SharedLibraryBinarySpec) { spec ->
|
|
||||||
spec.headerDirs.each {
|
|
||||||
from(it) {
|
|
||||||
into 'include'
|
|
||||||
// We don't want to include any of the .cpp files that are in some of the header directories
|
|
||||||
exclude '**/*.cpp'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
from(spec.sharedLibraryFile) {
|
}
|
||||||
into 'lib'
|
}
|
||||||
|
if (!project.hasProperty('onlyAthena')) {
|
||||||
|
halSim(NativeLibrarySpec) {
|
||||||
|
baseName = 'wpiHal'
|
||||||
|
sources {
|
||||||
|
cpp {
|
||||||
|
source {
|
||||||
|
srcDirs = [ 'src/main/native/shared', 'src/main/native/sim' ]
|
||||||
|
includes = ["**/*.cpp"]
|
||||||
|
}
|
||||||
|
exportedHeaders {
|
||||||
|
srcDirs = ["src/main/native/include"]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
from(new File(spec.sharedLibraryFile.absolutePath + ".debug")) {
|
binaries.all { binary ->
|
||||||
into 'lib'
|
if (binary.targetPlatform.operatingSystem.linux) {
|
||||||
|
linker.args "-ldl"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (project.hasProperty('buildHalStaticDeps')) {
|
||||||
|
halSimStaticDeps(NativeLibrarySpec) {
|
||||||
|
baseName = 'wpiHal'
|
||||||
|
binaries {
|
||||||
|
withType(StaticLibraryBinarySpec) {
|
||||||
|
buildable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
cpp {
|
||||||
|
source {
|
||||||
|
srcDirs = [ 'src/main/native/shared', 'src/main/native/sim' ]
|
||||||
|
includes = ["**/*.cpp"]
|
||||||
|
}
|
||||||
|
exportedHeaders {
|
||||||
|
srcDirs = ["src/main/native/include"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The TestingBase library is a workaround for an issue with the GoogleTest plugin.
|
||||||
|
// The plugin by default will rebuild the entire test source set, which increases
|
||||||
|
// build time. By testing an empty library, and then just linking the already built component
|
||||||
|
// into the test, we save the extra build
|
||||||
|
halSimTestingBase(NativeLibrarySpec) { }
|
||||||
|
// By default, a development executable will be generated. This is to help the case of
|
||||||
|
// testing specific functionality of the library.
|
||||||
|
if (!project.hasProperty('skipDevExe')) {
|
||||||
|
halDev(NativeExecutableSpec) {
|
||||||
|
binaries.all {
|
||||||
|
project.addHalToLinker(it)
|
||||||
|
}
|
||||||
|
sources {
|
||||||
|
cpp {
|
||||||
|
source {
|
||||||
|
srcDirs 'src/dev/native/cpp'
|
||||||
|
include '**/*.cpp'
|
||||||
|
}
|
||||||
|
exportedHeaders {
|
||||||
|
srcDirs 'src/dev/native/include'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testSuites {
|
||||||
defineNetworkTablesProperties()
|
halSimTestingBaseTest {
|
||||||
dependsOn project(':').downloadNetworkTables
|
sources {
|
||||||
|
cpp.source.srcDir 'src/test/native/cpp'
|
||||||
from(project.file(netTablesInclude)) {
|
cpp.exportedHeaders.srcDir 'src/test/native/include'
|
||||||
into 'include'
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
binaries {
|
||||||
from (file(netSharedLib)) {
|
all {
|
||||||
into 'lib'
|
project(':ni-libraries').addNiLibrariesToLinker(it)
|
||||||
|
}
|
||||||
|
withType(GoogleTestTestSuiteBinarySpec) {
|
||||||
|
if (it.component.testedComponent.name.contains('TestingBase') && !project.hasProperty('onlyAthena')) {
|
||||||
|
project(':gmock').addGmockToLinker(it)
|
||||||
|
project.addHalToLinker(it)
|
||||||
|
} else {
|
||||||
|
it.buildable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
tasks {
|
||||||
from (file(netSharedLibDebug)) {
|
runCpp(Exec) {
|
||||||
into 'lib'
|
def found = false
|
||||||
}
|
$.components.each {
|
||||||
|
if (it in NativeExecutableSpec && it.name == 'halDev') {
|
||||||
from (file(wpiUtilSharedLib)) {
|
it.binaries.each {
|
||||||
into 'lib'
|
if (!found) {
|
||||||
}
|
def arch = it.targetPlatform.architecture.name
|
||||||
|
if (arch == 'x86-64' || arch == 'x86') {
|
||||||
from (file(wpiUtilSharedLibDebug)) {
|
dependsOn it.tasks.install
|
||||||
into 'lib'
|
commandLine it.tasks.install.runScript
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getHeaders(Task) {
|
||||||
|
def list = []
|
||||||
|
$.components.each {
|
||||||
|
if (it in NativeLibrarySpec && (it.name == 'halAthena' || it.name == 'halSim')) {
|
||||||
|
it.sources.each {
|
||||||
|
it.exportedHeaders.srcDirs.each {
|
||||||
|
list.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it.binaries.each {
|
||||||
|
it.libs.each {
|
||||||
|
it.includeRoots.each {
|
||||||
|
list.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list = list.unique(false)
|
||||||
|
doLast {
|
||||||
|
list.each {
|
||||||
|
print "WPIHEADER: "
|
||||||
|
println it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply from: 'publish.gradle'
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
hal(MavenPublication) {
|
|
||||||
artifact halZip
|
|
||||||
|
|
||||||
groupId 'edu.wpi.first.wpilib'
|
|
||||||
artifactId 'hal'
|
|
||||||
version WPILibVersion.version
|
|
||||||
}
|
|
||||||
athenaruntime(MavenPublication) {
|
|
||||||
artifact athenaRuntimeZip
|
|
||||||
|
|
||||||
groupId 'edu.wpi.first.wpilib'
|
|
||||||
artifactId 'athena-runtime'
|
|
||||||
version WPILibVersion.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setupWpilibRepo(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
build.dependsOn halZip
|
|
||||||
build.dependsOn athenaRuntimeZip
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "FRC_NetworkCommunication/CANSessionMux.h"
|
|
||||||
|
|
||||||
void canTxSend(uint32_t arbID, uint8_t length,
|
|
||||||
int32_t period = CAN_SEND_PERIOD_NO_REPEAT);
|
|
||||||
|
|
||||||
void canTxPackInt8(uint32_t arbID, uint8_t offset, uint8_t value);
|
|
||||||
void canTxPackInt16(uint32_t arbID, uint8_t offset, uint16_t value);
|
|
||||||
void canTxPackInt32(uint32_t arbID, uint8_t offset, uint32_t value);
|
|
||||||
void canTxPackFXP16(uint32_t arbID, uint8_t offset, double value);
|
|
||||||
void canTxPackFXP32(uint32_t arbID, uint8_t offset, double value);
|
|
||||||
|
|
||||||
uint8_t canTxUnpackInt8(uint32_t arbID, uint8_t offset);
|
|
||||||
uint32_t canTxUnpackInt32(uint32_t arbID, uint8_t offset);
|
|
||||||
uint16_t canTxUnpackInt16(uint32_t arbID, uint8_t offset);
|
|
||||||
double canTxUnpackFXP16(uint32_t arbID, uint8_t offset);
|
|
||||||
double canTxUnpackFXP32(uint32_t arbID, uint8_t offset);
|
|
||||||
|
|
||||||
bool canRxReceive(uint32_t arbID);
|
|
||||||
|
|
||||||
uint8_t canRxUnpackInt8(uint32_t arbID, uint8_t offset);
|
|
||||||
uint16_t canRxUnpackInt16(uint32_t arbID, uint8_t offset);
|
|
||||||
uint32_t canRxUnpackInt32(uint32_t arbID, uint8_t offset);
|
|
||||||
double canRxUnpackFXP16(uint32_t arbID, uint8_t offset);
|
|
||||||
double canRxUnpackFXP32(uint32_t arbID, uint8_t offset);
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2008-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
|
||||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "FRC_FPGA_ChipObject/RoboRIO_FRC_ChipObject_Aliases.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/nInterfaceGlobals.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAI.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAO.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccel.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAccumulator.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAlarm.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tAnalogTrigger.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tBIST.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tCounter.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDIO.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tDMA.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tEncoder.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tGlobal.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tInterrupt.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPWM.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tPower.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tRelay.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSPI.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/nRoboRIO_FPGANamespace/tSysWatchdog.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/tDMAChannelDescriptor.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/tDMAManager.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/tInterruptManager.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/tSystem.h"
|
|
||||||
#include "FRC_FPGA_ChipObject/tSystemInterface.h"
|
|
||||||
|
|
||||||
namespace hal {
|
|
||||||
using namespace nFPGA;
|
|
||||||
using namespace nRoboRIO_FPGANamespace;
|
|
||||||
} // namespace hal
|
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "HAL/Types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void HAL_InitializeSPI(int32_t port, int32_t* status);
|
|
||||||
int32_t HAL_TransactionSPI(int32_t port, uint8_t* dataToSend,
|
|
||||||
uint8_t* dataReceived, int32_t size);
|
|
||||||
int32_t HAL_WriteSPI(int32_t port, uint8_t* dataToSend, int32_t sendSize);
|
|
||||||
int32_t HAL_ReadSPI(int32_t port, uint8_t* buffer, int32_t count);
|
|
||||||
void HAL_CloseSPI(int32_t port);
|
|
||||||
void HAL_SetSPISpeed(int32_t port, int32_t speed);
|
|
||||||
void HAL_SetSPIOpts(int32_t port, HAL_Bool msbFirst, HAL_Bool sampleOnTrailing,
|
|
||||||
HAL_Bool clkIdleHigh);
|
|
||||||
void HAL_SetSPIChipSelectActiveHigh(int32_t port, int32_t* status);
|
|
||||||
void HAL_SetSPIChipSelectActiveLow(int32_t port, int32_t* status);
|
|
||||||
int32_t HAL_GetSPIHandle(int32_t port);
|
|
||||||
void HAL_SetSPIHandle(int32_t port, int32_t handle);
|
|
||||||
|
|
||||||
void HAL_InitSPIAccumulator(int32_t port, int32_t period, int32_t cmd,
|
|
||||||
int32_t xferSize, int32_t validMask,
|
|
||||||
int32_t validValue, int32_t dataShift,
|
|
||||||
int32_t dataSize, HAL_Bool isSigned,
|
|
||||||
HAL_Bool bigEndian, int32_t* status);
|
|
||||||
void HAL_FreeSPIAccumulator(int32_t port, int32_t* status);
|
|
||||||
void HAL_ResetSPIAccumulator(int32_t port, int32_t* status);
|
|
||||||
void HAL_SetSPIAccumulatorCenter(int32_t port, int32_t center, int32_t* status);
|
|
||||||
void HAL_SetSPIAccumulatorDeadband(int32_t port, int32_t deadband,
|
|
||||||
int32_t* status);
|
|
||||||
int32_t HAL_GetSPIAccumulatorLastValue(int32_t port, int32_t* status);
|
|
||||||
int64_t HAL_GetSPIAccumulatorValue(int32_t port, int32_t* status);
|
|
||||||
int64_t HAL_GetSPIAccumulatorCount(int32_t port, int32_t* status);
|
|
||||||
double HAL_GetSPIAccumulatorAverage(int32_t port, int32_t* status);
|
|
||||||
void HAL_GetSPIAccumulatorOutput(int32_t port, int64_t* value, int64_t* count,
|
|
||||||
int32_t* status);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
|
|
||||||
#include "HAL/cpp/priority_mutex.h"
|
|
||||||
#include "support/deprecated.h"
|
|
||||||
|
|
||||||
class WPI_DEPRECATED(
|
|
||||||
"Semaphore scheduled for removal in 2018. Recommended to replace with a "
|
|
||||||
"std::mutex and std::condition_variable") Semaphore {
|
|
||||||
public:
|
|
||||||
explicit Semaphore(int32_t count = 0);
|
|
||||||
Semaphore(Semaphore&&);
|
|
||||||
Semaphore& operator=(Semaphore&&);
|
|
||||||
|
|
||||||
void give();
|
|
||||||
void take();
|
|
||||||
|
|
||||||
// @return true if semaphore was locked successfully. false if not.
|
|
||||||
bool tryTake();
|
|
||||||
|
|
||||||
static const int32_t kNoWait = 0;
|
|
||||||
static const int32_t kWaitForever = -1;
|
|
||||||
|
|
||||||
static const int32_t kEmpty = 0;
|
|
||||||
static const int32_t kFull = 1;
|
|
||||||
|
|
||||||
private:
|
|
||||||
priority_mutex m_mutex;
|
|
||||||
std::condition_variable_any m_condition;
|
|
||||||
int32_t m_count = 0;
|
|
||||||
};
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/* std::condition_variable provides the native_handle() method to return its
|
|
||||||
* underlying pthread_cond_t*. WPILib uses this to interface with the FRC
|
|
||||||
* network communication library. Since WPILib uses a custom mutex class and
|
|
||||||
* not std::mutex, std::condition_variable_any must be used instead.
|
|
||||||
* std::condition_variable_any doesn't expose its internal handle, so this
|
|
||||||
* class provides the same interface and implementation in addition to a
|
|
||||||
* native_handle() method.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "priority_mutex.h"
|
|
||||||
|
|
||||||
class priority_condition_variable {
|
|
||||||
typedef std::chrono::system_clock clock;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef std::condition_variable::native_handle_type native_handle_type;
|
|
||||||
|
|
||||||
priority_condition_variable() : m_mutex(std::make_shared<std::mutex>()) {}
|
|
||||||
~priority_condition_variable() = default;
|
|
||||||
|
|
||||||
priority_condition_variable(const priority_condition_variable&) = delete;
|
|
||||||
priority_condition_variable& operator=(const priority_condition_variable&) =
|
|
||||||
delete;
|
|
||||||
|
|
||||||
void notify_one() noexcept {
|
|
||||||
std::lock_guard<std::mutex> lock(*m_mutex);
|
|
||||||
m_cond.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void notify_all() noexcept {
|
|
||||||
std::lock_guard<std::mutex> lock(*m_mutex);
|
|
||||||
m_cond.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lock>
|
|
||||||
void wait(Lock& _lock) {
|
|
||||||
std::shared_ptr<std::mutex> _mutex = m_mutex;
|
|
||||||
std::unique_lock<std::mutex> my_lock(*_mutex);
|
|
||||||
Unlock<Lock> unlock(_lock);
|
|
||||||
|
|
||||||
// *mutex must be unlocked before re-locking _lock so move
|
|
||||||
// ownership of *_mutex lock to an object with shorter lifetime.
|
|
||||||
std::unique_lock<std::mutex> my_lock2(std::move(my_lock));
|
|
||||||
m_cond.wait(my_lock2);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lock, typename Predicate>
|
|
||||||
void wait(Lock& lock, Predicate p) {
|
|
||||||
while (!p()) {
|
|
||||||
wait(lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lock, typename Clock, typename Duration>
|
|
||||||
std::cv_status wait_until(
|
|
||||||
Lock& _lock, const std::chrono::time_point<Clock, Duration>& atime) {
|
|
||||||
std::shared_ptr<std::mutex> _mutex = m_mutex;
|
|
||||||
std::unique_lock<std::mutex> my_lock(*_mutex);
|
|
||||||
Unlock<Lock> unlock(_lock);
|
|
||||||
|
|
||||||
// *_mutex must be unlocked before re-locking _lock so move
|
|
||||||
// ownership of *_mutex lock to an object with shorter lifetime.
|
|
||||||
std::unique_lock<std::mutex> my_lock2(std::move(my_lock));
|
|
||||||
return m_cond.wait_until(my_lock2, atime);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lock, typename Clock, typename Duration,
|
|
||||||
typename Predicate>
|
|
||||||
bool wait_until(Lock& lock,
|
|
||||||
const std::chrono::time_point<Clock, Duration>& atime,
|
|
||||||
Predicate p) {
|
|
||||||
while (!p()) {
|
|
||||||
if (wait_until(lock, atime) == std::cv_status::timeout) {
|
|
||||||
return p();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lock, typename Rep, typename Period>
|
|
||||||
std::cv_status wait_for(Lock& lock,
|
|
||||||
const std::chrono::duration<Rep, Period>& rtime) {
|
|
||||||
return wait_until(lock, clock::now() + rtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lock, typename Rep, typename Period, typename Predicate>
|
|
||||||
bool wait_for(Lock& lock, const std::chrono::duration<Rep, Period>& rtime,
|
|
||||||
Predicate p) {
|
|
||||||
return wait_until(lock, clock::now() + rtime, std::move(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
native_handle_type native_handle() { return m_cond.native_handle(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::condition_variable m_cond;
|
|
||||||
std::shared_ptr<std::mutex> m_mutex;
|
|
||||||
|
|
||||||
// scoped unlock - unlocks in ctor, re-locks in dtor
|
|
||||||
template <typename Lock>
|
|
||||||
struct Unlock {
|
|
||||||
explicit Unlock(Lock& lk) : m_lock(lk) { lk.unlock(); }
|
|
||||||
|
|
||||||
~Unlock() /*noexcept(false)*/ {
|
|
||||||
if (std::uncaught_exception()) {
|
|
||||||
try {
|
|
||||||
m_lock.lock();
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_lock.lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Unlock(const Unlock&) = delete;
|
|
||||||
Unlock& operator=(const Unlock&) = delete;
|
|
||||||
|
|
||||||
Lock& m_lock;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Allows usage with std::lock_guard without including <mutex> separately
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#if defined(FRC_SIMULATOR) || defined(_WIN32)
|
|
||||||
// We do not want to use pthreads if in the simulator; however, in the
|
|
||||||
// simulator, we do not care about priority inversion.
|
|
||||||
typedef std::mutex priority_mutex;
|
|
||||||
typedef std::recursive_mutex priority_recursive_mutex;
|
|
||||||
#else // Covers rest of file.
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
class priority_recursive_mutex {
|
|
||||||
public:
|
|
||||||
typedef pthread_mutex_t* native_handle_type;
|
|
||||||
|
|
||||||
constexpr priority_recursive_mutex() noexcept = default;
|
|
||||||
priority_recursive_mutex(const priority_recursive_mutex&) = delete;
|
|
||||||
priority_recursive_mutex& operator=(const priority_recursive_mutex&) = delete;
|
|
||||||
|
|
||||||
// Lock the mutex, blocking until it's available.
|
|
||||||
void lock();
|
|
||||||
|
|
||||||
// Unlock the mutex.
|
|
||||||
void unlock();
|
|
||||||
|
|
||||||
// Tries to lock the mutex.
|
|
||||||
bool try_lock() noexcept;
|
|
||||||
|
|
||||||
pthread_mutex_t* native_handle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Do the equivalent of setting PTHREAD_PRIO_INHERIT and
|
|
||||||
// PTHREAD_MUTEX_RECURSIVE_NP.
|
|
||||||
#if __WORDSIZE == 64
|
|
||||||
pthread_mutex_t m_mutex = {
|
|
||||||
{0, 0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, {0, 0}}};
|
|
||||||
#else
|
|
||||||
pthread_mutex_t m_mutex = {
|
|
||||||
{0, 0, 0, 0x20 | PTHREAD_MUTEX_RECURSIVE_NP, 0, {0}}};
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class priority_mutex {
|
|
||||||
public:
|
|
||||||
typedef pthread_mutex_t* native_handle_type;
|
|
||||||
|
|
||||||
constexpr priority_mutex() noexcept = default;
|
|
||||||
priority_mutex(const priority_mutex&) = delete;
|
|
||||||
priority_mutex& operator=(const priority_mutex&) = delete;
|
|
||||||
|
|
||||||
// Lock the mutex, blocking until it's available.
|
|
||||||
void lock();
|
|
||||||
|
|
||||||
// Unlock the mutex.
|
|
||||||
void unlock();
|
|
||||||
|
|
||||||
// Tries to lock the mutex.
|
|
||||||
bool try_lock() noexcept;
|
|
||||||
|
|
||||||
pthread_mutex_t* native_handle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Do the equivalent of setting PTHREAD_PRIO_INHERIT.
|
|
||||||
#if __WORDSIZE == 64
|
|
||||||
pthread_mutex_t m_mutex = {{0, 0, 0, 0, 0x20, 0, 0, {0, 0}}};
|
|
||||||
#else
|
|
||||||
pthread_mutex_t m_mutex = {{0, 0, 0, 0x20, 0, {0}}};
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // FRC_SIMULATOR
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file ctre_frames.h
|
|
||||||
* CAN Encoder/Decoder Structures for CTRE devices.
|
|
||||||
*/
|
|
||||||
#ifndef CTRE_FRAMES_H
|
|
||||||
#define CTRE_FRAMES_H
|
|
||||||
|
|
||||||
/** control */
|
|
||||||
typedef struct _TALON_Control_1_General_10ms_t {
|
|
||||||
unsigned TokenH:8;
|
|
||||||
unsigned TokenL:8;
|
|
||||||
unsigned DemandH:8;
|
|
||||||
unsigned DemandM:8;
|
|
||||||
unsigned DemandL:8;
|
|
||||||
unsigned ProfileSlotSelect:1;
|
|
||||||
unsigned FeedbackDeviceSelect:4;
|
|
||||||
unsigned OverrideLimitSwitchEn:3;
|
|
||||||
unsigned RevFeedbackSensor:1;
|
|
||||||
unsigned RevMotDuringCloseLoopEn:1;
|
|
||||||
unsigned OverrideBrakeType:2;
|
|
||||||
unsigned ModeSelect:4;
|
|
||||||
unsigned RampThrottle:8;
|
|
||||||
} TALON_Control_1_General_10ms_t ;
|
|
||||||
|
|
||||||
/* TALON_Control_2_Rates_OneShot_t removed since it has been deprecated */
|
|
||||||
|
|
||||||
typedef struct _TALON_Control_3_ClearFlags_OneShot_t {
|
|
||||||
unsigned ZeroFeedbackSensor:1;
|
|
||||||
unsigned ClearStickyFaults:1;
|
|
||||||
} TALON_Control_3_ClearFlags_OneShot_t ;
|
|
||||||
|
|
||||||
typedef struct _TALON_Control_5_General_10ms_t {
|
|
||||||
unsigned ThrottleBump_h3:3;
|
|
||||||
unsigned ReservedZero:5;
|
|
||||||
unsigned ThrottleBump_l8:8;
|
|
||||||
unsigned DemandH:8;
|
|
||||||
unsigned DemandM:8;
|
|
||||||
unsigned DemandL:8;
|
|
||||||
unsigned ProfileSlotSelect:1;
|
|
||||||
unsigned FeedbackDeviceSelect:4;
|
|
||||||
unsigned OverrideLimitSwitchEn:3;
|
|
||||||
unsigned RevFeedbackSensor:1;
|
|
||||||
unsigned RevMotDuringCloseLoopEn:1;
|
|
||||||
unsigned OverrideBrakeType:2;
|
|
||||||
unsigned ModeSelect:4;
|
|
||||||
unsigned RampThrottle:8;
|
|
||||||
} TALON_Control_5_General_10ms_t ;
|
|
||||||
|
|
||||||
typedef struct _TALON_Control_6_MotProfAddTrajPoint_t {
|
|
||||||
unsigned huffCode:2; //!< Compression coding
|
|
||||||
unsigned NextPt_VelOnly:1;
|
|
||||||
unsigned NextPt_IsLast:1;
|
|
||||||
unsigned reserved0:2;
|
|
||||||
unsigned NextPt_ZeroPosition:1;
|
|
||||||
unsigned NextPt_ProfileSlotSelect:1;
|
|
||||||
unsigned Idx:4;
|
|
||||||
unsigned reserved1:4;
|
|
||||||
unsigned restOfFrame0:8;
|
|
||||||
unsigned restOfFrame1:8;
|
|
||||||
unsigned restOfFrame2:8;
|
|
||||||
unsigned restOfFrame3:8;
|
|
||||||
unsigned restOfFrame4:8;
|
|
||||||
unsigned restOfFrame5:8;
|
|
||||||
} TALON_Control_6_MotProfAddTrajPoint_t;
|
|
||||||
|
|
||||||
typedef struct _TALON_Control_6_MotProfAddTrajPoint_huff0_t {
|
|
||||||
unsigned huffCode_expect_0:2; //!< Compression coding
|
|
||||||
unsigned NextPt_VelOnly:1;
|
|
||||||
unsigned NextPt_IsLast:1;
|
|
||||||
unsigned reserved0:2;
|
|
||||||
unsigned NextPt_ZeroPosition:1;
|
|
||||||
unsigned NextPt_ProfileSlotSelect:1;
|
|
||||||
unsigned Idx:4;
|
|
||||||
unsigned reserved1:4;
|
|
||||||
unsigned NextPt_DurationMs:8;
|
|
||||||
unsigned NextPt_VelocityH:8;
|
|
||||||
unsigned NextPt_VelocityL:8;
|
|
||||||
unsigned NextPt_PositionH:8;
|
|
||||||
unsigned NextPt_PositionM:8;
|
|
||||||
unsigned NextPt_PositionL:8;
|
|
||||||
} TALON_Control_6_MotProfAddTrajPoint_huff0_t;
|
|
||||||
|
|
||||||
typedef struct _TALON_Control_6_MotProfAddTrajPoint_huff1_t {
|
|
||||||
unsigned huffCode_expect_1:2; //!< Compression coding
|
|
||||||
unsigned NextPt_VelOnly:1;
|
|
||||||
unsigned NextPt_IsLast:1;
|
|
||||||
unsigned reserved0:2;
|
|
||||||
unsigned NextPt_ZeroPosition:1;
|
|
||||||
unsigned NextPt_ProfileSlotSelect:1;
|
|
||||||
unsigned Idx:4;
|
|
||||||
unsigned reserved1:4;
|
|
||||||
unsigned NextPt_DurationMs:8;
|
|
||||||
unsigned NextPt_SameVelocityH:8;
|
|
||||||
unsigned NextPt_SameVelocityL:8;
|
|
||||||
unsigned NextPt_DeltaPositionH:8;
|
|
||||||
unsigned NextPt_DeltaPositionL:8;
|
|
||||||
unsigned NextPt_Count:8;
|
|
||||||
} TALON_Control_6_MotProfAddTrajPoint_huff1_t;
|
|
||||||
|
|
||||||
/** status */
|
|
||||||
typedef struct _TALON_Status_1_General_10ms_t {
|
|
||||||
unsigned CloseLoopErrH:8;
|
|
||||||
unsigned CloseLoopErrM:8;
|
|
||||||
unsigned CloseLoopErrL:8;
|
|
||||||
unsigned AppliedThrottle_h3:3;
|
|
||||||
unsigned Fault_RevSoftLim:1;
|
|
||||||
unsigned Fault_ForSoftLim:1;
|
|
||||||
unsigned TokLocked:1;
|
|
||||||
unsigned LimitSwitchClosedRev:1;
|
|
||||||
unsigned LimitSwitchClosedFor:1;
|
|
||||||
unsigned AppliedThrottle_l8:8;
|
|
||||||
unsigned ModeSelect_h1:1;
|
|
||||||
unsigned FeedbackDeviceSelect:4;
|
|
||||||
unsigned LimitSwitchEn:3;
|
|
||||||
unsigned Fault_HardwareFailure:1;
|
|
||||||
unsigned Fault_RevLim:1;
|
|
||||||
unsigned Fault_ForLim:1;
|
|
||||||
unsigned Fault_UnderVoltage:1;
|
|
||||||
unsigned Fault_OverTemp:1;
|
|
||||||
unsigned ModeSelect_b3:3;
|
|
||||||
unsigned TokenSeed:8;
|
|
||||||
} TALON_Status_1_General_10ms_t ;
|
|
||||||
typedef struct _TALON_Status_2_Feedback_20ms_t {
|
|
||||||
unsigned SensorPositionH:8;
|
|
||||||
unsigned SensorPositionM:8;
|
|
||||||
unsigned SensorPositionL:8;
|
|
||||||
unsigned SensorVelocityH:8;
|
|
||||||
unsigned SensorVelocityL:8;
|
|
||||||
unsigned Current_h8:8;
|
|
||||||
unsigned StckyFault_RevSoftLim:1;
|
|
||||||
unsigned StckyFault_ForSoftLim:1;
|
|
||||||
unsigned StckyFault_RevLim:1;
|
|
||||||
unsigned StckyFault_ForLim:1;
|
|
||||||
unsigned StckyFault_UnderVoltage:1;
|
|
||||||
unsigned StckyFault_OverTemp:1;
|
|
||||||
unsigned Current_l2:2;
|
|
||||||
unsigned reserved:3;
|
|
||||||
unsigned Cmd5Allowed:1;
|
|
||||||
unsigned VelDiv4:1;
|
|
||||||
unsigned PosDiv8:1;
|
|
||||||
unsigned ProfileSlotSelect:1;
|
|
||||||
unsigned BrakeIsEnabled:1;
|
|
||||||
} TALON_Status_2_Feedback_20ms_t ;
|
|
||||||
typedef struct _TALON_Status_3_Enc_100ms_t {
|
|
||||||
unsigned EncPositionH:8;
|
|
||||||
unsigned EncPositionM:8;
|
|
||||||
unsigned EncPositionL:8;
|
|
||||||
unsigned EncVelH:8;
|
|
||||||
unsigned EncVelL:8;
|
|
||||||
unsigned EncIndexRiseEventsH:8;
|
|
||||||
unsigned EncIndexRiseEventsL:8;
|
|
||||||
unsigned reserved:3;
|
|
||||||
unsigned VelDiv4:1;
|
|
||||||
unsigned PosDiv8:1;
|
|
||||||
unsigned QuadIdxpin:1;
|
|
||||||
unsigned QuadBpin:1;
|
|
||||||
unsigned QuadApin:1;
|
|
||||||
} TALON_Status_3_Enc_100ms_t ;
|
|
||||||
typedef struct _TALON_Status_4_AinTempVbat_100ms_t {
|
|
||||||
unsigned AnalogInWithOvH:8;
|
|
||||||
unsigned AnalogInWithOvM:8;
|
|
||||||
unsigned AnalogInWithOvL:8;
|
|
||||||
unsigned AnalogInVelH:8;
|
|
||||||
unsigned AnalogInVelL:8;
|
|
||||||
unsigned Temp:8;
|
|
||||||
unsigned BatteryV:8;
|
|
||||||
unsigned reserved:6;
|
|
||||||
unsigned VelDiv4:1;
|
|
||||||
unsigned PosDiv8:1;
|
|
||||||
} TALON_Status_4_AinTempVbat_100ms_t ;
|
|
||||||
typedef struct _TALON_Status_5_Startup_OneShot_t {
|
|
||||||
unsigned ResetCountH:8;
|
|
||||||
unsigned ResetCountL:8;
|
|
||||||
unsigned ResetFlagsH:8;
|
|
||||||
unsigned ResetFlagsL:8;
|
|
||||||
unsigned FirmVersH:8;
|
|
||||||
unsigned FirmVersL:8;
|
|
||||||
} TALON_Status_5_Startup_OneShot_t ;
|
|
||||||
typedef struct _TALON_Status_6_Eol_t {
|
|
||||||
unsigned currentAdcUncal_h2:2;
|
|
||||||
unsigned reserved1:5;
|
|
||||||
unsigned SpiCsPin_GadgeteerPin6:1;
|
|
||||||
unsigned currentAdcUncal_l8:8;
|
|
||||||
unsigned tempAdcUncal_h2:2;
|
|
||||||
unsigned reserved2:6;
|
|
||||||
unsigned tempAdcUncal_l8:8;
|
|
||||||
unsigned vbatAdcUncal_h2:2;
|
|
||||||
unsigned reserved3:6;
|
|
||||||
unsigned vbatAdcUncal_l8:8;
|
|
||||||
unsigned analogAdcUncal_h2:2;
|
|
||||||
unsigned reserved4:6;
|
|
||||||
unsigned analogAdcUncal_l8:8;
|
|
||||||
} TALON_Status_6_Eol_t ;
|
|
||||||
typedef struct _TALON_Status_7_Debug_200ms_t {
|
|
||||||
unsigned TokenizationFails_h8:8;
|
|
||||||
unsigned TokenizationFails_l8:8;
|
|
||||||
unsigned LastFailedToken_h8:8;
|
|
||||||
unsigned LastFailedToken_l8:8;
|
|
||||||
unsigned TokenizationSucceses_h8:8;
|
|
||||||
unsigned TokenizationSucceses_l8:8;
|
|
||||||
} TALON_Status_7_Debug_200ms_t ;
|
|
||||||
typedef struct _TALON_Status_8_PulseWid_100ms_t {
|
|
||||||
unsigned PulseWidPositionH:8;
|
|
||||||
unsigned PulseWidPositionM:8;
|
|
||||||
unsigned PulseWidPositionL:8;
|
|
||||||
unsigned reserved:6;
|
|
||||||
unsigned VelDiv4:1;
|
|
||||||
unsigned PosDiv8:1;
|
|
||||||
unsigned PeriodUsM8:8;
|
|
||||||
unsigned PeriodUsL8:8;
|
|
||||||
unsigned PulseWidVelH:8;
|
|
||||||
unsigned PulseWidVelL:8;
|
|
||||||
} TALON_Status_8_PulseWid_100ms_t ;
|
|
||||||
typedef struct _TALON_Status_9_MotProfBuffer_100ms_t {
|
|
||||||
unsigned ActTraj_IsValid:1; //!< '1' if other ActTraj_* signals are valid. '0' if there is no active trajectory pt.
|
|
||||||
unsigned ActTraj_ProfileSlotSelect:1;
|
|
||||||
unsigned ActTraj_VelOnly:1;
|
|
||||||
unsigned ActTraj_IsLast:1;
|
|
||||||
unsigned OutputType:2;
|
|
||||||
unsigned HasUnderrun:1;
|
|
||||||
unsigned IsUnderrun:1;
|
|
||||||
unsigned NextID:4;
|
|
||||||
unsigned reserved1:3;
|
|
||||||
unsigned BufferIsFull:1;
|
|
||||||
unsigned Count:8;
|
|
||||||
unsigned ActTraj_VelocityH:8;
|
|
||||||
unsigned ActTraj_VelocityL:8;
|
|
||||||
unsigned ActTraj_PositionH:8;
|
|
||||||
unsigned ActTraj_PositionM:8;
|
|
||||||
unsigned ActTraj_PositionL:8;
|
|
||||||
} TALON_Status_9_MotProfBuffer_100ms_t ;
|
|
||||||
typedef struct _TALON_Param_Request_t {
|
|
||||||
unsigned ParamEnum:8;
|
|
||||||
} TALON_Param_Request_t ;
|
|
||||||
typedef struct _TALON_Param_Response_t {
|
|
||||||
unsigned ParamEnum:8;
|
|
||||||
unsigned ParamValueL:8;
|
|
||||||
unsigned ParamValueML:8;
|
|
||||||
unsigned ParamValueMH:8;
|
|
||||||
unsigned ParamValueH:8;
|
|
||||||
} TALON_Param_Response_t ;
|
|
||||||
|
|
||||||
#endif /* CTRE_FRAMES_H */
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "HAL/I2C.h"
|
|
||||||
|
|
||||||
#include "DigitalInternal.h"
|
|
||||||
#include "HAL/DIO.h"
|
|
||||||
#include "HAL/HAL.h"
|
|
||||||
#include "i2clib/i2c-lib.h"
|
|
||||||
|
|
||||||
using namespace hal;
|
|
||||||
|
|
||||||
static priority_recursive_mutex digitalI2COnBoardMutex;
|
|
||||||
static priority_recursive_mutex digitalI2CMXPMutex;
|
|
||||||
|
|
||||||
static uint8_t i2COnboardObjCount = 0;
|
|
||||||
static uint8_t i2CMXPObjCount = 0;
|
|
||||||
static uint8_t i2COnBoardHandle = 0;
|
|
||||||
static uint8_t i2CMXPHandle = 0;
|
|
||||||
|
|
||||||
static HAL_DigitalHandle i2CMXPDigitalHandle1 = HAL_kInvalidHandle;
|
|
||||||
static HAL_DigitalHandle i2CMXPDigitalHandle2 = HAL_kInvalidHandle;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
/*
|
|
||||||
* Initialize the I2C port. Opens the port if necessary and saves the handle.
|
|
||||||
* If opening the MXP port, also sets up the channel functions appropriately
|
|
||||||
* @param port The port to open, 0 for the on-board, 1 for the MXP.
|
|
||||||
*/
|
|
||||||
void HAL_InitializeI2C(int32_t port, int32_t* status) {
|
|
||||||
initializeDigital(status);
|
|
||||||
if (*status != 0) return;
|
|
||||||
|
|
||||||
if (port > 1) {
|
|
||||||
// Set port out of range error here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
priority_recursive_mutex& lock =
|
|
||||||
port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
|
||||||
{
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(lock);
|
|
||||||
if (port == 0) {
|
|
||||||
i2COnboardObjCount++;
|
|
||||||
if (i2COnBoardHandle > 0) return;
|
|
||||||
i2COnBoardHandle = i2clib_open("/dev/i2c-2");
|
|
||||||
} else if (port == 1) {
|
|
||||||
i2CMXPObjCount++;
|
|
||||||
if (i2CMXPHandle > 0) return;
|
|
||||||
if ((i2CMXPDigitalHandle1 = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(24), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((i2CMXPDigitalHandle2 = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(25), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
HAL_FreeDIOPort(i2CMXPDigitalHandle1); // free the first port allocated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
digitalSystem->writeEnableMXPSpecialFunction(
|
|
||||||
digitalSystem->readEnableMXPSpecialFunction(status) | 0xC000, status);
|
|
||||||
i2CMXPHandle = i2clib_open("/dev/i2c-1");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic transaction.
|
|
||||||
*
|
|
||||||
* This is a lower-level interface to the I2C hardware giving you more control
|
|
||||||
* over each transaction.
|
|
||||||
*
|
|
||||||
* @param dataToSend Buffer of data to send as part of the transaction.
|
|
||||||
* @param sendSize Number of bytes to send as part of the transaction.
|
|
||||||
* @param dataReceived Buffer to read data into.
|
|
||||||
* @param receiveSize Number of bytes to read from the device.
|
|
||||||
* @return The number of bytes read (>= 0) or -1 on transfer abort.
|
|
||||||
*/
|
|
||||||
int32_t HAL_TransactionI2C(int32_t port, int32_t deviceAddress,
|
|
||||||
uint8_t* dataToSend, int32_t sendSize,
|
|
||||||
uint8_t* dataReceived, int32_t receiveSize) {
|
|
||||||
if (port > 1) {
|
|
||||||
// Set port out of range error here
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
|
||||||
priority_recursive_mutex& lock =
|
|
||||||
port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(lock);
|
|
||||||
return i2clib_writeread(
|
|
||||||
handle, deviceAddress, reinterpret_cast<const char*>(dataToSend),
|
|
||||||
static_cast<int32_t>(sendSize), reinterpret_cast<char*>(dataReceived),
|
|
||||||
static_cast<int32_t>(receiveSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a write transaction with the device.
|
|
||||||
*
|
|
||||||
* Write a single byte to a register on a device and wait until the
|
|
||||||
* transaction is complete.
|
|
||||||
*
|
|
||||||
* @param registerAddress The address of the register on the device to be
|
|
||||||
* written.
|
|
||||||
* @param data The byte to write to the register on the device.
|
|
||||||
* @return The number of bytes written (>= 0) or -1 on transfer abort.
|
|
||||||
*/
|
|
||||||
int32_t HAL_WriteI2C(int32_t port, int32_t deviceAddress, uint8_t* dataToSend,
|
|
||||||
int32_t sendSize) {
|
|
||||||
if (port > 1) {
|
|
||||||
// Set port out of range error here
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
|
||||||
priority_recursive_mutex& lock =
|
|
||||||
port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
|
||||||
{
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(lock);
|
|
||||||
return i2clib_write(handle, deviceAddress,
|
|
||||||
reinterpret_cast<const char*>(dataToSend), sendSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a read transaction with the device.
|
|
||||||
*
|
|
||||||
* Read bytes from a device.
|
|
||||||
* Most I2C devices will auto-increment the register pointer internally allowing
|
|
||||||
* you to read consecutive registers on a device in a single transaction.
|
|
||||||
*
|
|
||||||
* @param registerAddress The register to read first in the transaction.
|
|
||||||
* @param count The number of bytes to read in the transaction.
|
|
||||||
* @param buffer A pointer to the array of bytes to store the data read from the
|
|
||||||
* device.
|
|
||||||
* @return The number of bytes read (>= 0) or -1 on transfer abort.
|
|
||||||
*/
|
|
||||||
int32_t HAL_ReadI2C(int32_t port, int32_t deviceAddress, uint8_t* buffer,
|
|
||||||
int32_t count) {
|
|
||||||
if (port > 1) {
|
|
||||||
// Set port out of range error here
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
|
||||||
priority_recursive_mutex& lock =
|
|
||||||
port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
|
||||||
{
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(lock);
|
|
||||||
return i2clib_read(handle, deviceAddress, reinterpret_cast<char*>(buffer),
|
|
||||||
static_cast<int32_t>(count));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_CloseI2C(int32_t port) {
|
|
||||||
if (port > 1) {
|
|
||||||
// Set port out of range error here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
priority_recursive_mutex& lock =
|
|
||||||
port == 0 ? digitalI2COnBoardMutex : digitalI2CMXPMutex;
|
|
||||||
{
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(lock);
|
|
||||||
if ((port == 0 ? i2COnboardObjCount-- : i2CMXPObjCount--) == 0) {
|
|
||||||
int32_t handle = port == 0 ? i2COnBoardHandle : i2CMXPHandle;
|
|
||||||
i2clib_close(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (port == 1) {
|
|
||||||
HAL_FreeDIOPort(i2CMXPDigitalHandle1);
|
|
||||||
HAL_FreeDIOPort(i2CMXPDigitalHandle2);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,299 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "HAL/Notifier.h"
|
|
||||||
|
|
||||||
// For std::atexit()
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "HAL/ChipObject.h"
|
|
||||||
#include "HAL/Errors.h"
|
|
||||||
#include "HAL/HAL.h"
|
|
||||||
#include "HAL/cpp/make_unique.h"
|
|
||||||
#include "HAL/cpp/priority_mutex.h"
|
|
||||||
#include "HAL/handles/UnlimitedHandleResource.h"
|
|
||||||
#include "support/SafeThread.h"
|
|
||||||
|
|
||||||
using namespace hal;
|
|
||||||
|
|
||||||
static const int32_t kTimerInterruptNumber = 28;
|
|
||||||
|
|
||||||
static priority_mutex notifierInterruptMutex;
|
|
||||||
static priority_recursive_mutex notifierMutex;
|
|
||||||
static std::unique_ptr<tAlarm> notifierAlarm;
|
|
||||||
static std::unique_ptr<tInterruptManager> notifierManager;
|
|
||||||
static uint64_t closestTrigger = UINT64_MAX;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct Notifier {
|
|
||||||
std::shared_ptr<Notifier> prev, next;
|
|
||||||
void* param;
|
|
||||||
HAL_NotifierProcessFunction process;
|
|
||||||
uint64_t triggerTime = UINT64_MAX;
|
|
||||||
HAL_NotifierHandle handle;
|
|
||||||
bool threaded;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Safe thread to allow callbacks to run on their own thread
|
|
||||||
class NotifierThread : public wpi::SafeThread {
|
|
||||||
public:
|
|
||||||
void Main() {
|
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
|
||||||
while (m_active) {
|
|
||||||
m_cond.wait(lock, [&] { return !m_active || m_notify; });
|
|
||||||
if (!m_active) break;
|
|
||||||
m_notify = false;
|
|
||||||
uint64_t currentTime = m_currentTime;
|
|
||||||
HAL_NotifierHandle handle = m_handle;
|
|
||||||
HAL_NotifierProcessFunction process = m_process;
|
|
||||||
lock.unlock(); // don't hold mutex during callback execution
|
|
||||||
process(currentTime, handle);
|
|
||||||
lock.lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool m_notify = false;
|
|
||||||
HAL_NotifierHandle m_handle = HAL_kInvalidHandle;
|
|
||||||
HAL_NotifierProcessFunction m_process;
|
|
||||||
uint64_t m_currentTime;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NotifierThreadOwner : public wpi::SafeThreadOwner<NotifierThread> {
|
|
||||||
public:
|
|
||||||
void SetFunc(HAL_NotifierProcessFunction process, void* param) {
|
|
||||||
auto thr = GetThread();
|
|
||||||
if (!thr) return;
|
|
||||||
thr->m_process = process;
|
|
||||||
m_param = param;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notify(uint64_t currentTime, HAL_NotifierHandle handle) {
|
|
||||||
auto thr = GetThread();
|
|
||||||
if (!thr) return;
|
|
||||||
thr->m_currentTime = currentTime;
|
|
||||||
thr->m_handle = handle;
|
|
||||||
thr->m_notify = true;
|
|
||||||
thr->m_cond.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void* m_param;
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
static std::shared_ptr<Notifier> notifiers;
|
|
||||||
static std::atomic_flag notifierAtexitRegistered = ATOMIC_FLAG_INIT;
|
|
||||||
static std::atomic_int notifierRefCount{0};
|
|
||||||
|
|
||||||
using namespace hal;
|
|
||||||
|
|
||||||
static UnlimitedHandleResource<HAL_NotifierHandle, Notifier,
|
|
||||||
HAL_HandleEnum::Notifier>
|
|
||||||
notifierHandles;
|
|
||||||
|
|
||||||
// internal version of updateAlarm used during the alarmCallback when we know
|
|
||||||
// that the pointer is a valid pointer.
|
|
||||||
void updateNotifierAlarmInternal(std::shared_ptr<Notifier> notifierPointer,
|
|
||||||
uint64_t triggerTime, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
|
|
||||||
|
|
||||||
auto notifier = notifierPointer;
|
|
||||||
// no need for a null check, as this must always be a valid pointer.
|
|
||||||
notifier->triggerTime = triggerTime;
|
|
||||||
bool wasActive = (closestTrigger != UINT64_MAX);
|
|
||||||
|
|
||||||
if (!notifierInterruptMutex.try_lock() || notifierRefCount == 0 ||
|
|
||||||
!notifierAlarm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Update alarm time if closer than current.
|
|
||||||
if (triggerTime < closestTrigger) {
|
|
||||||
closestTrigger = triggerTime;
|
|
||||||
// Simply truncate the hardware trigger time to 32-bit.
|
|
||||||
notifierAlarm->writeTriggerTime(static_cast<uint32_t>(triggerTime), status);
|
|
||||||
}
|
|
||||||
// Enable the alarm. The hardware disables itself after each alarm.
|
|
||||||
if (!wasActive) notifierAlarm->writeEnable(true, status);
|
|
||||||
|
|
||||||
notifierInterruptMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void alarmCallback(uint32_t, void*) {
|
|
||||||
std::unique_lock<priority_recursive_mutex> sync(notifierMutex);
|
|
||||||
|
|
||||||
int32_t status = 0;
|
|
||||||
uint64_t currentTime = 0;
|
|
||||||
|
|
||||||
// the hardware disables itself after each alarm
|
|
||||||
closestTrigger = UINT64_MAX;
|
|
||||||
|
|
||||||
// process all notifiers
|
|
||||||
std::shared_ptr<Notifier> notifier = notifiers;
|
|
||||||
while (notifier) {
|
|
||||||
if (notifier->triggerTime != UINT64_MAX) {
|
|
||||||
if (currentTime == 0) currentTime = HAL_GetFPGATime(&status);
|
|
||||||
if (notifier->triggerTime < currentTime) {
|
|
||||||
notifier->triggerTime = UINT64_MAX;
|
|
||||||
auto process = notifier->process;
|
|
||||||
auto handle = notifier->handle;
|
|
||||||
sync.unlock();
|
|
||||||
process(currentTime, handle);
|
|
||||||
sync.lock();
|
|
||||||
} else if (notifier->triggerTime < closestTrigger) {
|
|
||||||
updateNotifierAlarmInternal(notifier, notifier->triggerTime, &status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
notifier = notifier->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanupNotifierAtExit() {
|
|
||||||
notifierAlarm = nullptr;
|
|
||||||
notifierManager = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void threadedNotifierHandler(uint64_t currentTimeInt,
|
|
||||||
HAL_NotifierHandle handle) {
|
|
||||||
// Grab notifier and get handler param
|
|
||||||
auto notifier = notifierHandles.Get(handle);
|
|
||||||
if (!notifier) return;
|
|
||||||
auto notifierPointer = notifier->param;
|
|
||||||
if (notifierPointer == nullptr) return;
|
|
||||||
NotifierThreadOwner* owner =
|
|
||||||
static_cast<NotifierThreadOwner*>(notifierPointer);
|
|
||||||
owner->Notify(currentTimeInt, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
HAL_NotifierHandle HAL_InitializeNotifier(HAL_NotifierProcessFunction process,
|
|
||||||
void* param, int32_t* status) {
|
|
||||||
if (!process) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!notifierAtexitRegistered.test_and_set())
|
|
||||||
std::atexit(cleanupNotifierAtExit);
|
|
||||||
if (notifierRefCount.fetch_add(1) == 0) {
|
|
||||||
std::lock_guard<priority_mutex> sync(notifierInterruptMutex);
|
|
||||||
// create manager and alarm if not already created
|
|
||||||
if (!notifierManager) {
|
|
||||||
notifierManager = std::make_unique<tInterruptManager>(
|
|
||||||
1 << kTimerInterruptNumber, false, status);
|
|
||||||
notifierManager->registerHandler(alarmCallback, nullptr, status);
|
|
||||||
notifierManager->enable(status);
|
|
||||||
}
|
|
||||||
if (!notifierAlarm) notifierAlarm.reset(tAlarm::create(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
|
|
||||||
std::shared_ptr<Notifier> notifier = std::make_shared<Notifier>();
|
|
||||||
HAL_NotifierHandle handle = notifierHandles.Allocate(notifier);
|
|
||||||
if (handle == HAL_kInvalidHandle) {
|
|
||||||
*status = HAL_HANDLE_ERROR;
|
|
||||||
return HAL_kInvalidHandle;
|
|
||||||
}
|
|
||||||
// create notifier structure and add to list
|
|
||||||
notifier->next = notifiers;
|
|
||||||
if (notifier->next) notifier->next->prev = notifier;
|
|
||||||
notifier->param = param;
|
|
||||||
notifier->process = process;
|
|
||||||
notifier->handle = handle;
|
|
||||||
notifier->threaded = false;
|
|
||||||
notifiers = notifier;
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
HAL_NotifierHandle HAL_InitializeNotifierThreaded(
|
|
||||||
HAL_NotifierProcessFunction process, void* param, int32_t* status) {
|
|
||||||
NotifierThreadOwner* notify = new NotifierThreadOwner;
|
|
||||||
notify->Start();
|
|
||||||
notify->SetFunc(process, param);
|
|
||||||
|
|
||||||
auto notifierHandle =
|
|
||||||
HAL_InitializeNotifier(threadedNotifierHandler, notify, status);
|
|
||||||
|
|
||||||
if (notifierHandle == HAL_kInvalidHandle || *status != 0) {
|
|
||||||
delete notify;
|
|
||||||
return HAL_kInvalidHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto notifier = notifierHandles.Get(notifierHandle);
|
|
||||||
if (!notifier) {
|
|
||||||
return HAL_kInvalidHandle;
|
|
||||||
}
|
|
||||||
notifier->threaded = true;
|
|
||||||
|
|
||||||
return notifierHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
|
|
||||||
{
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
|
|
||||||
auto notifier = notifierHandles.Get(notifierHandle);
|
|
||||||
if (!notifier) return;
|
|
||||||
|
|
||||||
// remove from list
|
|
||||||
if (notifier->prev) notifier->prev->next = notifier->next;
|
|
||||||
if (notifier->next) notifier->next->prev = notifier->prev;
|
|
||||||
if (notifiers == notifier) notifiers = notifier->next;
|
|
||||||
notifierHandles.Free(notifierHandle);
|
|
||||||
|
|
||||||
if (notifier->threaded) {
|
|
||||||
NotifierThreadOwner* owner =
|
|
||||||
static_cast<NotifierThreadOwner*>(notifier->param);
|
|
||||||
delete owner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notifierRefCount.fetch_sub(1) == 1) {
|
|
||||||
std::lock_guard<priority_mutex> sync(notifierInterruptMutex);
|
|
||||||
// if this was the last notifier, clean up alarm and manager
|
|
||||||
if (notifierAlarm) {
|
|
||||||
notifierAlarm->writeEnable(false, status);
|
|
||||||
notifierAlarm = nullptr;
|
|
||||||
}
|
|
||||||
if (notifierManager) {
|
|
||||||
notifierManager->disable(status);
|
|
||||||
notifierManager = nullptr;
|
|
||||||
}
|
|
||||||
closestTrigger = UINT64_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void* HAL_GetNotifierParam(HAL_NotifierHandle notifierHandle, int32_t* status) {
|
|
||||||
auto notifier = notifierHandles.Get(notifierHandle);
|
|
||||||
if (!notifier) return nullptr;
|
|
||||||
if (notifier->threaded) {
|
|
||||||
// If threaded, return thread param rather then notifier param
|
|
||||||
NotifierThreadOwner* owner =
|
|
||||||
static_cast<NotifierThreadOwner*>(notifier->param);
|
|
||||||
return owner->m_param;
|
|
||||||
}
|
|
||||||
return notifier->param;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_UpdateNotifierAlarm(HAL_NotifierHandle notifierHandle,
|
|
||||||
uint64_t triggerTime, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
|
|
||||||
|
|
||||||
auto notifier = notifierHandles.Get(notifierHandle);
|
|
||||||
if (!notifier) return;
|
|
||||||
updateNotifierAlarmInternal(notifier, triggerTime, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_StopNotifierAlarm(HAL_NotifierHandle notifierHandle, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(notifierMutex);
|
|
||||||
auto notifier = notifierHandles.Get(notifierHandle);
|
|
||||||
if (!notifier) return;
|
|
||||||
notifier->triggerTime = UINT64_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // extern "C"
|
|
||||||
@@ -1,665 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "HAL/SPI.h"
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include "DigitalInternal.h"
|
|
||||||
#include "HAL/DIO.h"
|
|
||||||
#include "HAL/HAL.h"
|
|
||||||
#include "HAL/Notifier.h"
|
|
||||||
#include "HAL/cpp/make_unique.h"
|
|
||||||
#include "HAL/cpp/priority_mutex.h"
|
|
||||||
#include "HAL/handles/HandlesInternal.h"
|
|
||||||
#include "spilib/spi-lib.h"
|
|
||||||
|
|
||||||
using namespace hal;
|
|
||||||
|
|
||||||
static int32_t m_spiCS0Handle = 0;
|
|
||||||
static int32_t m_spiCS1Handle = 0;
|
|
||||||
static int32_t m_spiCS2Handle = 0;
|
|
||||||
static int32_t m_spiCS3Handle = 0;
|
|
||||||
static int32_t m_spiMXPHandle = 0;
|
|
||||||
static priority_recursive_mutex spiOnboardMutex;
|
|
||||||
static priority_recursive_mutex spiMXPMutex;
|
|
||||||
|
|
||||||
// MXP SPI does not count towards this
|
|
||||||
std::atomic<int32_t> spiPortCount{0};
|
|
||||||
|
|
||||||
static HAL_DigitalHandle digitalHandles[9]{HAL_kInvalidHandle};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the semaphore for a SPI port
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
* @return The semaphore for the SPI port.
|
|
||||||
*/
|
|
||||||
static priority_recursive_mutex& spiGetMutex(int32_t port) {
|
|
||||||
if (port < 4)
|
|
||||||
return spiOnboardMutex;
|
|
||||||
else
|
|
||||||
return spiMXPMutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
struct SPIAccumulator {
|
|
||||||
std::atomic<HAL_NotifierHandle> notifier{0};
|
|
||||||
uint64_t triggerTime;
|
|
||||||
int32_t period;
|
|
||||||
|
|
||||||
int64_t value = 0;
|
|
||||||
uint32_t count = 0;
|
|
||||||
int32_t lastValue = 0;
|
|
||||||
|
|
||||||
int32_t center = 0;
|
|
||||||
int32_t deadband = 0;
|
|
||||||
|
|
||||||
uint8_t cmd[4]; // command to send (up to 4 bytes)
|
|
||||||
int32_t validMask;
|
|
||||||
int32_t validValue;
|
|
||||||
int32_t dataMax; // one more than max data value
|
|
||||||
int32_t dataMsbMask; // data field MSB mask (for signed)
|
|
||||||
uint8_t dataShift; // data field shift right amount, in bits
|
|
||||||
uint8_t xferSize; // SPI transfer size, in bytes (up to 4)
|
|
||||||
uint8_t port;
|
|
||||||
bool isSigned; // is data field signed?
|
|
||||||
bool bigEndian; // is response big endian?
|
|
||||||
};
|
|
||||||
std::unique_ptr<SPIAccumulator> spiAccumulators[5];
|
|
||||||
|
|
||||||
static void CommonSPIPortInit(int32_t* status) {
|
|
||||||
// All false cases will set
|
|
||||||
if (spiPortCount.fetch_add(1) == 0) {
|
|
||||||
// Have not been initialized yet
|
|
||||||
initializeDigital(status);
|
|
||||||
if (*status != 0) return;
|
|
||||||
// MISO
|
|
||||||
if ((digitalHandles[3] = HAL_InitializeDIOPort(createPortHandleForSPI(29),
|
|
||||||
false, status)) ==
|
|
||||||
HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 29 (MISO)\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// MOSI
|
|
||||||
if ((digitalHandles[4] = HAL_InitializeDIOPort(createPortHandleForSPI(30),
|
|
||||||
false, status)) ==
|
|
||||||
HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 30 (MOSI)\n");
|
|
||||||
HAL_FreeDIOPort(digitalHandles[3]); // free the first port allocated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CommonSPIPortFree() {
|
|
||||||
if (spiPortCount.fetch_sub(1) == 1) {
|
|
||||||
// Clean up SPI Handles
|
|
||||||
HAL_FreeDIOPort(digitalHandles[3]);
|
|
||||||
HAL_FreeDIOPort(digitalHandles[4]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the spi port. Opens the port if necessary and saves the handle.
|
|
||||||
* If opening the MXP port, also sets up the channel functions appropriately
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS3, 4 for MXP
|
|
||||||
*/
|
|
||||||
void HAL_InitializeSPI(int32_t port, int32_t* status) {
|
|
||||||
if (HAL_GetSPIHandle(port) != 0) return;
|
|
||||||
switch (port) {
|
|
||||||
case 0:
|
|
||||||
CommonSPIPortInit(status);
|
|
||||||
if (*status != 0) return;
|
|
||||||
// CS0 is not a DIO port, so nothing to allocate
|
|
||||||
HAL_SetSPIHandle(0, spilib_open("/dev/spidev0.0"));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
CommonSPIPortInit(status);
|
|
||||||
if (*status != 0) return;
|
|
||||||
// CS1, Allocate
|
|
||||||
if ((digitalHandles[0] = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(26), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 26 (CS1)\n");
|
|
||||||
CommonSPIPortFree();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HAL_SetSPIHandle(1, spilib_open("/dev/spidev0.1"));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
CommonSPIPortInit(status);
|
|
||||||
if (*status != 0) return;
|
|
||||||
// CS2, Allocate
|
|
||||||
if ((digitalHandles[1] = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(27), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 27 (CS2)\n");
|
|
||||||
CommonSPIPortFree();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HAL_SetSPIHandle(2, spilib_open("/dev/spidev0.2"));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
CommonSPIPortInit(status);
|
|
||||||
if (*status != 0) return;
|
|
||||||
// CS3, Allocate
|
|
||||||
if ((digitalHandles[2] = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(28), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 28 (CS3)\n");
|
|
||||||
CommonSPIPortFree();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HAL_SetSPIHandle(3, spilib_open("/dev/spidev0.3"));
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
initializeDigital(status);
|
|
||||||
if (*status != 0) return;
|
|
||||||
if ((digitalHandles[5] = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(14), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 14\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((digitalHandles[6] = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(15), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 15\n");
|
|
||||||
HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((digitalHandles[7] = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(16), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 16\n");
|
|
||||||
HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated
|
|
||||||
HAL_FreeDIOPort(digitalHandles[6]); // free the second port allocated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((digitalHandles[8] = HAL_InitializeDIOPort(
|
|
||||||
HAL_GetPort(17), false, status)) == HAL_kInvalidHandle) {
|
|
||||||
std::printf("Failed to allocate DIO 17\n");
|
|
||||||
HAL_FreeDIOPort(digitalHandles[5]); // free the first port allocated
|
|
||||||
HAL_FreeDIOPort(digitalHandles[6]); // free the second port allocated
|
|
||||||
HAL_FreeDIOPort(digitalHandles[7]); // free the third port allocated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
digitalSystem->writeEnableMXPSpecialFunction(
|
|
||||||
digitalSystem->readEnableMXPSpecialFunction(status) | 0x00F0, status);
|
|
||||||
HAL_SetSPIHandle(4, spilib_open("/dev/spidev1.0"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*status = PARAMETER_OUT_OF_RANGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic transaction.
|
|
||||||
*
|
|
||||||
* This is a lower-level interface to the spi hardware giving you more control
|
|
||||||
* over each transaction.
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
* @param dataToSend Buffer of data to send as part of the transaction.
|
|
||||||
* @param dataReceived Buffer to read data into.
|
|
||||||
* @param size Number of bytes to transfer. [0..7]
|
|
||||||
* @return Number of bytes transferred, -1 for error
|
|
||||||
*/
|
|
||||||
int32_t HAL_TransactionSPI(int32_t port, uint8_t* dataToSend,
|
|
||||||
uint8_t* dataReceived, int32_t size) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
return spilib_writeread(
|
|
||||||
HAL_GetSPIHandle(port), reinterpret_cast<const char*>(dataToSend),
|
|
||||||
reinterpret_cast<char*>(dataReceived), static_cast<int32_t>(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a write transaction with the device.
|
|
||||||
*
|
|
||||||
* Write to a device and wait until the transaction is complete.
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
* @param datToSend The data to write to the register on the device.
|
|
||||||
* @param sendSize The number of bytes to be written
|
|
||||||
* @return The number of bytes written. -1 for an error
|
|
||||||
*/
|
|
||||||
int32_t HAL_WriteSPI(int32_t port, uint8_t* dataToSend, int32_t sendSize) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
return spilib_write(HAL_GetSPIHandle(port),
|
|
||||||
reinterpret_cast<const char*>(dataToSend),
|
|
||||||
static_cast<int32_t>(sendSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a read from the device.
|
|
||||||
*
|
|
||||||
* This method does not write any data out to the device
|
|
||||||
* Most spi devices will require a register address to be written before
|
|
||||||
* they begin returning data
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
* @param buffer A pointer to the array of bytes to store the data read from the
|
|
||||||
* device.
|
|
||||||
* @param count The number of bytes to read in the transaction. [1..7]
|
|
||||||
* @return Number of bytes read. -1 for error.
|
|
||||||
*/
|
|
||||||
int32_t HAL_ReadSPI(int32_t port, uint8_t* buffer, int32_t count) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
return spilib_read(HAL_GetSPIHandle(port), reinterpret_cast<char*>(buffer),
|
|
||||||
static_cast<int32_t>(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the SPI port
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
*/
|
|
||||||
void HAL_CloseSPI(int32_t port) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
if (spiAccumulators[port]) {
|
|
||||||
int32_t status = 0;
|
|
||||||
HAL_FreeSPIAccumulator(port, &status);
|
|
||||||
}
|
|
||||||
spilib_close(HAL_GetSPIHandle(port));
|
|
||||||
HAL_SetSPIHandle(port, 0);
|
|
||||||
if (port < 4) {
|
|
||||||
CommonSPIPortFree();
|
|
||||||
}
|
|
||||||
switch (port) {
|
|
||||||
// Case 0 does not need to do anything
|
|
||||||
case 1:
|
|
||||||
HAL_FreeDIOPort(digitalHandles[0]);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
HAL_FreeDIOPort(digitalHandles[1]);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
HAL_FreeDIOPort(digitalHandles[2]);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
HAL_FreeDIOPort(digitalHandles[5]);
|
|
||||||
HAL_FreeDIOPort(digitalHandles[6]);
|
|
||||||
HAL_FreeDIOPort(digitalHandles[7]);
|
|
||||||
HAL_FreeDIOPort(digitalHandles[8]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the clock speed for the SPI bus.
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
* @param speed The speed in Hz (0-1MHz)
|
|
||||||
*/
|
|
||||||
void HAL_SetSPISpeed(int32_t port, int32_t speed) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
spilib_setspeed(HAL_GetSPIHandle(port), speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the SPI options
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
* @param msbFirst True to write the MSB first, False for LSB first
|
|
||||||
* @param sampleOnTrailing True to sample on the trailing edge, False to sample
|
|
||||||
* on the leading edge
|
|
||||||
* @param clkIdleHigh True to set the clock to active low, False to set the
|
|
||||||
* clock active high
|
|
||||||
*/
|
|
||||||
void HAL_SetSPIOpts(int32_t port, HAL_Bool msbFirst, HAL_Bool sampleOnTrailing,
|
|
||||||
HAL_Bool clkIdleHigh) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
spilib_setopts(HAL_GetSPIHandle(port), msbFirst, sampleOnTrailing,
|
|
||||||
clkIdleHigh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the CS Active high for a SPI port
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
*/
|
|
||||||
void HAL_SetSPIChipSelectActiveHigh(int32_t port, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
if (port < 4) {
|
|
||||||
spiSystem->writeChipSelectActiveHigh_Hdr(
|
|
||||||
spiSystem->readChipSelectActiveHigh_Hdr(status) | (1 << port), status);
|
|
||||||
} else {
|
|
||||||
spiSystem->writeChipSelectActiveHigh_MXP(1, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the CS Active low for a SPI port
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
*/
|
|
||||||
void HAL_SetSPIChipSelectActiveLow(int32_t port, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
if (port < 4) {
|
|
||||||
spiSystem->writeChipSelectActiveHigh_Hdr(
|
|
||||||
spiSystem->readChipSelectActiveHigh_Hdr(status) & ~(1 << port), status);
|
|
||||||
} else {
|
|
||||||
spiSystem->writeChipSelectActiveHigh_MXP(0, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the stored handle for a SPI port
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for MXP
|
|
||||||
* @return The stored handle for the SPI port. 0 represents no stored handle.
|
|
||||||
*/
|
|
||||||
int32_t HAL_GetSPIHandle(int32_t port) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
switch (port) {
|
|
||||||
case 0:
|
|
||||||
return m_spiCS0Handle;
|
|
||||||
case 1:
|
|
||||||
return m_spiCS1Handle;
|
|
||||||
case 2:
|
|
||||||
return m_spiCS2Handle;
|
|
||||||
case 3:
|
|
||||||
return m_spiCS3Handle;
|
|
||||||
case 4:
|
|
||||||
return m_spiMXPHandle;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the stored handle for a SPI port
|
|
||||||
*
|
|
||||||
* @param port The number of the port to use. 0-3 for Onboard CS0-CS2, 4 for
|
|
||||||
* MXP.
|
|
||||||
* @param handle The value of the handle for the port.
|
|
||||||
*/
|
|
||||||
void HAL_SetSPIHandle(int32_t port, int32_t handle) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
switch (port) {
|
|
||||||
case 0:
|
|
||||||
m_spiCS0Handle = handle;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
m_spiCS1Handle = handle;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
m_spiCS2Handle = handle;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
m_spiCS3Handle = handle;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
m_spiMXPHandle = handle;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spiAccumulatorProcess(uint64_t currentTime,
|
|
||||||
HAL_NotifierHandle handle) {
|
|
||||||
int32_t status = 0;
|
|
||||||
auto param = HAL_GetNotifierParam(handle, &status);
|
|
||||||
if (param == nullptr) return;
|
|
||||||
SPIAccumulator* accum = static_cast<SPIAccumulator*>(param);
|
|
||||||
|
|
||||||
// perform SPI transaction
|
|
||||||
uint8_t resp_b[4];
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(accum->port));
|
|
||||||
spilib_writeread(
|
|
||||||
HAL_GetSPIHandle(accum->port), reinterpret_cast<const char*>(accum->cmd),
|
|
||||||
reinterpret_cast<char*>(resp_b), static_cast<int32_t>(accum->xferSize));
|
|
||||||
|
|
||||||
// convert from bytes
|
|
||||||
uint32_t resp = 0;
|
|
||||||
if (accum->bigEndian) {
|
|
||||||
for (int32_t i = 0; i < accum->xferSize; ++i) {
|
|
||||||
resp <<= 8;
|
|
||||||
resp |= resp_b[i] & 0xff;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int32_t i = accum->xferSize - 1; i >= 0; --i) {
|
|
||||||
resp <<= 8;
|
|
||||||
resp |= resp_b[i] & 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process response
|
|
||||||
if ((resp & accum->validMask) == static_cast<uint32_t>(accum->validValue)) {
|
|
||||||
// valid sensor data; extract data field
|
|
||||||
int32_t data = static_cast<int32_t>(resp >> accum->dataShift);
|
|
||||||
data &= accum->dataMax - 1;
|
|
||||||
// 2s complement conversion if signed MSB is set
|
|
||||||
if (accum->isSigned && (data & accum->dataMsbMask) != 0)
|
|
||||||
data -= accum->dataMax;
|
|
||||||
// center offset
|
|
||||||
data -= accum->center;
|
|
||||||
// only accumulate if outside deadband
|
|
||||||
if (data < -accum->deadband || data > accum->deadband) accum->value += data;
|
|
||||||
++accum->count;
|
|
||||||
accum->lastValue = data;
|
|
||||||
} else {
|
|
||||||
// no data from the sensor; just clear the last value
|
|
||||||
accum->lastValue = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reschedule timer
|
|
||||||
accum->triggerTime += accum->period;
|
|
||||||
// handle timer slip
|
|
||||||
if (accum->triggerTime < currentTime)
|
|
||||||
accum->triggerTime = currentTime + accum->period;
|
|
||||||
status = 0;
|
|
||||||
HAL_UpdateNotifierAlarm(accum->notifier, accum->triggerTime, &status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a SPI accumulator.
|
|
||||||
*
|
|
||||||
* @param port SPI port
|
|
||||||
* @param period Time between reads, in us
|
|
||||||
* @param cmd SPI command to send to request data
|
|
||||||
* @param xferSize SPI transfer size, in bytes
|
|
||||||
* @param validMask Mask to apply to received data for validity checking
|
|
||||||
* @param valid_data After validMask is applied, required matching value for
|
|
||||||
* validity checking
|
|
||||||
* @param dataShift Bit shift to apply to received data to get actual data
|
|
||||||
* value
|
|
||||||
* @param dataSize Size (in bits) of data field
|
|
||||||
* @param isSigned Is data field signed?
|
|
||||||
* @param bigEndian Is device big endian?
|
|
||||||
*/
|
|
||||||
void HAL_InitSPIAccumulator(int32_t port, int32_t period, int32_t cmd,
|
|
||||||
int32_t xferSize, int32_t validMask,
|
|
||||||
int32_t validValue, int32_t dataShift,
|
|
||||||
int32_t dataSize, HAL_Bool isSigned,
|
|
||||||
HAL_Bool bigEndian, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
if (port > 4) return;
|
|
||||||
if (!spiAccumulators[port])
|
|
||||||
spiAccumulators[port] = std::make_unique<SPIAccumulator>();
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (bigEndian) {
|
|
||||||
for (int32_t i = xferSize - 1; i >= 0; --i) {
|
|
||||||
accum->cmd[i] = cmd & 0xff;
|
|
||||||
cmd >>= 8;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
accum->cmd[0] = cmd & 0xff;
|
|
||||||
cmd >>= 8;
|
|
||||||
accum->cmd[1] = cmd & 0xff;
|
|
||||||
cmd >>= 8;
|
|
||||||
accum->cmd[2] = cmd & 0xff;
|
|
||||||
cmd >>= 8;
|
|
||||||
accum->cmd[3] = cmd & 0xff;
|
|
||||||
}
|
|
||||||
accum->period = period;
|
|
||||||
accum->xferSize = xferSize;
|
|
||||||
accum->validMask = validMask;
|
|
||||||
accum->validValue = validValue;
|
|
||||||
accum->dataShift = dataShift;
|
|
||||||
accum->dataMax = (1 << dataSize);
|
|
||||||
accum->dataMsbMask = (1 << (dataSize - 1));
|
|
||||||
accum->isSigned = isSigned;
|
|
||||||
accum->bigEndian = bigEndian;
|
|
||||||
if (!accum->notifier) {
|
|
||||||
accum->notifier =
|
|
||||||
HAL_InitializeNotifier(spiAccumulatorProcess, accum, status);
|
|
||||||
accum->triggerTime = HAL_GetFPGATime(status) + period;
|
|
||||||
if (*status != 0) return;
|
|
||||||
HAL_UpdateNotifierAlarm(accum->notifier, accum->triggerTime, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Frees a SPI accumulator.
|
|
||||||
*/
|
|
||||||
void HAL_FreeSPIAccumulator(int32_t port, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HAL_NotifierHandle handle = accum->notifier.exchange(0);
|
|
||||||
HAL_CleanNotifier(handle, status);
|
|
||||||
spiAccumulators[port] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the accumulator to zero.
|
|
||||||
*/
|
|
||||||
void HAL_ResetSPIAccumulator(int32_t port, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
accum->value = 0;
|
|
||||||
accum->count = 0;
|
|
||||||
accum->lastValue = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the center value of the accumulator.
|
|
||||||
*
|
|
||||||
* The center value is subtracted from each value before it is added to the
|
|
||||||
* accumulator. This
|
|
||||||
* is used for the center value of devices like gyros and accelerometers to make
|
|
||||||
* integration work
|
|
||||||
* and to take the device offset into account when integrating.
|
|
||||||
*/
|
|
||||||
void HAL_SetSPIAccumulatorCenter(int32_t port, int32_t center,
|
|
||||||
int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
accum->center = center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the accumulator's deadband.
|
|
||||||
*/
|
|
||||||
void HAL_SetSPIAccumulatorDeadband(int32_t port, int32_t deadband,
|
|
||||||
int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
accum->deadband = deadband;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the last value read by the accumulator engine.
|
|
||||||
*/
|
|
||||||
int32_t HAL_GetSPIAccumulatorLastValue(int32_t port, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return accum->lastValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the accumulated value.
|
|
||||||
*
|
|
||||||
* @return The 64-bit value accumulated since the last Reset().
|
|
||||||
*/
|
|
||||||
int64_t HAL_GetSPIAccumulatorValue(int32_t port, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return accum->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the number of accumulated values.
|
|
||||||
*
|
|
||||||
* Read the count of the accumulated values since the accumulator was last
|
|
||||||
* Reset().
|
|
||||||
*
|
|
||||||
* @return The number of times samples from the channel were accumulated.
|
|
||||||
*/
|
|
||||||
int64_t HAL_GetSPIAccumulatorCount(int32_t port, int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return accum->count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the average of the accumulated value.
|
|
||||||
*
|
|
||||||
* @return The accumulated average value (value / count).
|
|
||||||
*/
|
|
||||||
double HAL_GetSPIAccumulatorAverage(int32_t port, int32_t* status) {
|
|
||||||
int64_t value;
|
|
||||||
int64_t count;
|
|
||||||
HAL_GetSPIAccumulatorOutput(port, &value, &count, status);
|
|
||||||
if (count == 0) return 0.0;
|
|
||||||
return static_cast<double>(value) / count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the accumulated value and the number of accumulated values atomically.
|
|
||||||
*
|
|
||||||
* This function reads the value and count atomically.
|
|
||||||
* This can be used for averaging.
|
|
||||||
*
|
|
||||||
* @param value Pointer to the 64-bit accumulated output.
|
|
||||||
* @param count Pointer to the number of accumulation cycles.
|
|
||||||
*/
|
|
||||||
void HAL_GetSPIAccumulatorOutput(int32_t port, int64_t* value, int64_t* count,
|
|
||||||
int32_t* status) {
|
|
||||||
std::lock_guard<priority_recursive_mutex> sync(spiGetMutex(port));
|
|
||||||
SPIAccumulator* accum = spiAccumulators[port].get();
|
|
||||||
if (!accum) {
|
|
||||||
*status = NULL_PARAMETER;
|
|
||||||
*value = 0;
|
|
||||||
*count = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*value = accum->value;
|
|
||||||
*count = accum->count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2015-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "HAL/cpp/Semaphore.h"
|
|
||||||
|
|
||||||
Semaphore::Semaphore(int32_t count) { m_count = count; }
|
|
||||||
|
|
||||||
void Semaphore::give() {
|
|
||||||
std::lock_guard<priority_mutex> lock(m_mutex);
|
|
||||||
++m_count;
|
|
||||||
m_condition.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Semaphore::take() {
|
|
||||||
std::unique_lock<priority_mutex> lock(m_mutex);
|
|
||||||
m_condition.wait(lock, [this] { return m_count; });
|
|
||||||
--m_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Semaphore::tryTake() {
|
|
||||||
std::lock_guard<priority_mutex> lock(m_mutex);
|
|
||||||
if (m_count) {
|
|
||||||
--m_count;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
||||||
/* the project. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "HAL/cpp/priority_mutex.h"
|
|
||||||
|
|
||||||
void priority_recursive_mutex::lock() { pthread_mutex_lock(&m_mutex); }
|
|
||||||
|
|
||||||
void priority_recursive_mutex::unlock() { pthread_mutex_unlock(&m_mutex); }
|
|
||||||
|
|
||||||
bool priority_recursive_mutex::try_lock() noexcept {
|
|
||||||
return !pthread_mutex_trylock(&m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_t* priority_recursive_mutex::native_handle() { return &m_mutex; }
|
|
||||||
|
|
||||||
void priority_mutex::lock() { pthread_mutex_lock(&m_mutex); }
|
|
||||||
|
|
||||||
void priority_mutex::unlock() { pthread_mutex_unlock(&m_mutex); }
|
|
||||||
|
|
||||||
bool priority_mutex::try_lock() noexcept {
|
|
||||||
return !pthread_mutex_trylock(&m_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_t* priority_mutex::native_handle() { return &m_mutex; }
|
|
||||||
125
hal/publish.gradle
Normal file
125
hal/publish.gradle
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
apply plugin: 'maven-publish'
|
||||||
|
apply plugin: 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin'
|
||||||
|
|
||||||
|
if (!hasProperty('releaseType')) {
|
||||||
|
WPILibVersion {
|
||||||
|
releaseType = 'dev'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def pubVersion = ''
|
||||||
|
if (project.hasProperty("publishVersion")) {
|
||||||
|
pubVersion = project.publishVersion
|
||||||
|
} else {
|
||||||
|
pubVersion = WPILibVersion.version
|
||||||
|
}
|
||||||
|
|
||||||
|
def baseArtifactId = 'hal'
|
||||||
|
def artifactGroupId = 'edu.wpi.first.hal'
|
||||||
|
|
||||||
|
def outputsFolder = file("$project.buildDir/outputs")
|
||||||
|
|
||||||
|
task cppSourcesZip(type: Zip) {
|
||||||
|
destinationDir = outputsFolder
|
||||||
|
baseName = 'hal'
|
||||||
|
classifier = "sources"
|
||||||
|
|
||||||
|
from(licenseFile) {
|
||||||
|
into '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
from('src/main/native/athena') {
|
||||||
|
into '/athena'
|
||||||
|
}
|
||||||
|
|
||||||
|
from('src/main/native/sim') {
|
||||||
|
into '/sim'
|
||||||
|
}
|
||||||
|
|
||||||
|
from('src/main/native/shared') {
|
||||||
|
into '/shared'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task cppHeadersZip(type: Zip) {
|
||||||
|
destinationDir = outputsFolder
|
||||||
|
baseName = 'hal'
|
||||||
|
classifier = "headers"
|
||||||
|
|
||||||
|
from(licenseFile) {
|
||||||
|
into '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
from('src/main/native/include') {
|
||||||
|
into '/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.dependsOn cppHeadersZip
|
||||||
|
build.dependsOn cppSourcesZip
|
||||||
|
|
||||||
|
|
||||||
|
model {
|
||||||
|
publishing {
|
||||||
|
def halAthenaTaskList = []
|
||||||
|
if (!project.hasProperty('skipAthena')) {
|
||||||
|
halAthenaTaskList = createComponentZipTasks($.components, 'halAthena', 'zipcpp', Zip, project, includeStandardZipFormat)
|
||||||
|
}
|
||||||
|
def halSimTaskList = []
|
||||||
|
if (!project.hasProperty('onlyAthena')) {
|
||||||
|
halSimTaskList = createComponentZipTasks($.components, 'halSim', 'zipcpp', Zip, project, includeStandardZipFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
def allTask
|
||||||
|
if (!project.hasProperty('jenkinsBuild')) {
|
||||||
|
def combinedList = []
|
||||||
|
halAthenaTaskList.each {
|
||||||
|
combinedList.add(it)
|
||||||
|
}
|
||||||
|
halSimTaskList.each {
|
||||||
|
combinedList.add(it)
|
||||||
|
}
|
||||||
|
allTask = createAllCombined(combinedList, 'hal', 'zipcpp', Zip, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
def halSimStaticDepsTaskList = []
|
||||||
|
if (project.hasProperty('buildHalStaticDeps')) {
|
||||||
|
halSimStaticDepsTaskList = createComponentZipTasks($.components, 'halSimStaticDeps', 'zipcpp', Zip, project, includeStandardZipFormat)
|
||||||
|
if (!project.hasProperty('jenkinsBuild')) {
|
||||||
|
def staticAllTask = createAllCombined(halSimStaticDepsTaskList, 'halSimStaticDeps', 'zipcpp', Zip, project)
|
||||||
|
halSimStaticDepsTaskList.add(staticAllTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publications {
|
||||||
|
cpp(MavenPublication) {
|
||||||
|
halAthenaTaskList.each {
|
||||||
|
artifact it
|
||||||
|
}
|
||||||
|
halSimTaskList.each {
|
||||||
|
artifact it
|
||||||
|
}
|
||||||
|
if (!project.hasProperty('jenkinsBuild')) {
|
||||||
|
artifact allTask
|
||||||
|
}
|
||||||
|
artifact cppHeadersZip
|
||||||
|
artifact cppSourcesZip
|
||||||
|
|
||||||
|
artifactId = baseArtifactId
|
||||||
|
groupId artifactGroupId
|
||||||
|
version pubVersion
|
||||||
|
}
|
||||||
|
if (project.hasProperty('buildHalStaticDeps')) {
|
||||||
|
cppStaticDeps(MavenPublication) {
|
||||||
|
halSimStaticDepsTaskList.each {
|
||||||
|
artifact it
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactId = baseArtifactId + 'StaticDeps'
|
||||||
|
groupId artifactGroupId
|
||||||
|
version pubVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||||
/* the project. */
|
/* the project. */
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
package org.gazebosim.transport;
|
#include <iostream>
|
||||||
|
|
||||||
import java.io.IOException;
|
#include "HAL/HAL.h"
|
||||||
|
|
||||||
public interface ServerCallback {
|
int main() {
|
||||||
void handle(Connection conn) throws IOException;
|
std::cout << "Hello World" << std::endl;
|
||||||
|
std::cout << HAL_GetRuntimeType() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||||
/* the project. */
|
/* the project. */
|
||||||
@@ -19,14 +19,14 @@
|
|||||||
using namespace hal;
|
using namespace hal;
|
||||||
|
|
||||||
// The 7-bit I2C address with a 0 "send" bit
|
// The 7-bit I2C address with a 0 "send" bit
|
||||||
static const uint8_t kSendAddress = (0x1c << 1) | 0;
|
static constexpr uint8_t kSendAddress = (0x1c << 1) | 0;
|
||||||
|
|
||||||
// The 7-bit I2C address with a 1 "receive" bit
|
// The 7-bit I2C address with a 1 "receive" bit
|
||||||
static const uint8_t kReceiveAddress = (0x1c << 1) | 1;
|
static constexpr uint8_t kReceiveAddress = (0x1c << 1) | 1;
|
||||||
|
|
||||||
static const uint8_t kControlTxRx = 1;
|
static constexpr uint8_t kControlTxRx = 1;
|
||||||
static const uint8_t kControlStart = 2;
|
static constexpr uint8_t kControlStart = 2;
|
||||||
static const uint8_t kControlStop = 4;
|
static constexpr uint8_t kControlStop = 4;
|
||||||
|
|
||||||
static std::unique_ptr<tAccel> accel;
|
static std::unique_ptr<tAccel> accel;
|
||||||
static HAL_AccelerometerRange accelerometerRange;
|
static HAL_AccelerometerRange accelerometerRange;
|
||||||
@@ -77,6 +77,14 @@ enum Register {
|
|||||||
kReg_OffZ = 0x31
|
kReg_OffZ = 0x31
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace hal {
|
||||||
|
namespace init {
|
||||||
|
void InitializeAccelerometer() {}
|
||||||
|
} // namespace init
|
||||||
|
} // namespace hal
|
||||||
|
|
||||||
|
namespace hal {
|
||||||
|
|
||||||
static void writeRegister(Register reg, uint8_t data);
|
static void writeRegister(Register reg, uint8_t data);
|
||||||
static uint8_t readRegister(Register reg);
|
static uint8_t readRegister(Register reg);
|
||||||
|
|
||||||
@@ -89,6 +97,8 @@ static void initializeAccelerometer() {
|
|||||||
if (!accel) {
|
if (!accel) {
|
||||||
accel.reset(tAccel::create(&status));
|
accel.reset(tAccel::create(&status));
|
||||||
|
|
||||||
|
accelerometerRange = HAL_AccelerometerRange::HAL_AccelerometerRange_k2G;
|
||||||
|
|
||||||
// Enable I2C
|
// Enable I2C
|
||||||
accel->writeCNFG(1, &status);
|
accel->writeCNFG(1, &status);
|
||||||
|
|
||||||
@@ -182,6 +192,8 @@ static double unpackAxis(int16_t raw) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace hal
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,7 +227,7 @@ void HAL_SetAccelerometerRange(HAL_AccelerometerRange range) {
|
|||||||
*
|
*
|
||||||
* This is a floating point value in units of 1 g-force
|
* This is a floating point value in units of 1 g-force
|
||||||
*/
|
*/
|
||||||
double HAL_GetAccelerometerX() {
|
double HAL_GetAccelerometerX(void) {
|
||||||
initializeAccelerometer();
|
initializeAccelerometer();
|
||||||
|
|
||||||
int32_t raw =
|
int32_t raw =
|
||||||
@@ -228,7 +240,7 @@ double HAL_GetAccelerometerX() {
|
|||||||
*
|
*
|
||||||
* This is a floating point value in units of 1 g-force
|
* This is a floating point value in units of 1 g-force
|
||||||
*/
|
*/
|
||||||
double HAL_GetAccelerometerY() {
|
double HAL_GetAccelerometerY(void) {
|
||||||
initializeAccelerometer();
|
initializeAccelerometer();
|
||||||
|
|
||||||
int32_t raw =
|
int32_t raw =
|
||||||
@@ -241,7 +253,7 @@ double HAL_GetAccelerometerY() {
|
|||||||
*
|
*
|
||||||
* This is a floating point value in units of 1 g-force
|
* This is a floating point value in units of 1 g-force
|
||||||
*/
|
*/
|
||||||
double HAL_GetAccelerometerZ() {
|
double HAL_GetAccelerometerZ(void) {
|
||||||
initializeAccelerometer();
|
initializeAccelerometer();
|
||||||
|
|
||||||
int32_t raw =
|
int32_t raw =
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
|
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||||
/* the project. */
|
/* the project. */
|
||||||
@@ -12,7 +12,14 @@
|
|||||||
|
|
||||||
using namespace hal;
|
using namespace hal;
|
||||||
|
|
||||||
|
namespace hal {
|
||||||
|
namespace init {
|
||||||
|
void InitializeAnalogAccumulator() {}
|
||||||
|
} // namespace init
|
||||||
|
} // namespace hal
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the channel attached to an accumulator.
|
* Is the channel attached to an accumulator.
|
||||||
*
|
*
|
||||||
@@ -21,7 +28,7 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
HAL_Bool HAL_IsAccumulatorChannel(HAL_AnalogInputHandle analogPortHandle,
|
HAL_Bool HAL_IsAccumulatorChannel(HAL_AnalogInputHandle analogPortHandle,
|
||||||
int32_t* status) {
|
int32_t* status) {
|
||||||
auto port = analogInputHandles.Get(analogPortHandle);
|
auto port = analogInputHandles->Get(analogPortHandle);
|
||||||
if (port == nullptr) {
|
if (port == nullptr) {
|
||||||
*status = HAL_HANDLE_ERROR;
|
*status = HAL_HANDLE_ERROR;
|
||||||
return false;
|
return false;
|
||||||
@@ -54,7 +61,7 @@ void HAL_InitAccumulator(HAL_AnalogInputHandle analogPortHandle,
|
|||||||
*/
|
*/
|
||||||
void HAL_ResetAccumulator(HAL_AnalogInputHandle analogPortHandle,
|
void HAL_ResetAccumulator(HAL_AnalogInputHandle analogPortHandle,
|
||||||
int32_t* status) {
|
int32_t* status) {
|
||||||
auto port = analogInputHandles.Get(analogPortHandle);
|
auto port = analogInputHandles->Get(analogPortHandle);
|
||||||
if (port == nullptr) {
|
if (port == nullptr) {
|
||||||
*status = HAL_HANDLE_ERROR;
|
*status = HAL_HANDLE_ERROR;
|
||||||
return;
|
return;
|
||||||
@@ -83,7 +90,7 @@ void HAL_ResetAccumulator(HAL_AnalogInputHandle analogPortHandle,
|
|||||||
*/
|
*/
|
||||||
void HAL_SetAccumulatorCenter(HAL_AnalogInputHandle analogPortHandle,
|
void HAL_SetAccumulatorCenter(HAL_AnalogInputHandle analogPortHandle,
|
||||||
int32_t center, int32_t* status) {
|
int32_t center, int32_t* status) {
|
||||||
auto port = analogInputHandles.Get(analogPortHandle);
|
auto port = analogInputHandles->Get(analogPortHandle);
|
||||||
if (port == nullptr) {
|
if (port == nullptr) {
|
||||||
*status = HAL_HANDLE_ERROR;
|
*status = HAL_HANDLE_ERROR;
|
||||||
return;
|
return;
|
||||||
@@ -103,7 +110,7 @@ void HAL_SetAccumulatorCenter(HAL_AnalogInputHandle analogPortHandle,
|
|||||||
*/
|
*/
|
||||||
void HAL_SetAccumulatorDeadband(HAL_AnalogInputHandle analogPortHandle,
|
void HAL_SetAccumulatorDeadband(HAL_AnalogInputHandle analogPortHandle,
|
||||||
int32_t deadband, int32_t* status) {
|
int32_t deadband, int32_t* status) {
|
||||||
auto port = analogInputHandles.Get(analogPortHandle);
|
auto port = analogInputHandles->Get(analogPortHandle);
|
||||||
if (port == nullptr) {
|
if (port == nullptr) {
|
||||||
*status = HAL_HANDLE_ERROR;
|
*status = HAL_HANDLE_ERROR;
|
||||||
return;
|
return;
|
||||||
@@ -126,7 +133,7 @@ void HAL_SetAccumulatorDeadband(HAL_AnalogInputHandle analogPortHandle,
|
|||||||
*/
|
*/
|
||||||
int64_t HAL_GetAccumulatorValue(HAL_AnalogInputHandle analogPortHandle,
|
int64_t HAL_GetAccumulatorValue(HAL_AnalogInputHandle analogPortHandle,
|
||||||
int32_t* status) {
|
int32_t* status) {
|
||||||
auto port = analogInputHandles.Get(analogPortHandle);
|
auto port = analogInputHandles->Get(analogPortHandle);
|
||||||
if (port == nullptr) {
|
if (port == nullptr) {
|
||||||
*status = HAL_HANDLE_ERROR;
|
*status = HAL_HANDLE_ERROR;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -150,7 +157,7 @@ int64_t HAL_GetAccumulatorValue(HAL_AnalogInputHandle analogPortHandle,
|
|||||||
*/
|
*/
|
||||||
int64_t HAL_GetAccumulatorCount(HAL_AnalogInputHandle analogPortHandle,
|
int64_t HAL_GetAccumulatorCount(HAL_AnalogInputHandle analogPortHandle,
|
||||||
int32_t* status) {
|
int32_t* status) {
|
||||||
auto port = analogInputHandles.Get(analogPortHandle);
|
auto port = analogInputHandles->Get(analogPortHandle);
|
||||||
if (port == nullptr) {
|
if (port == nullptr) {
|
||||||
*status = HAL_HANDLE_ERROR;
|
*status = HAL_HANDLE_ERROR;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -174,7 +181,7 @@ int64_t HAL_GetAccumulatorCount(HAL_AnalogInputHandle analogPortHandle,
|
|||||||
*/
|
*/
|
||||||
void HAL_GetAccumulatorOutput(HAL_AnalogInputHandle analogPortHandle,
|
void HAL_GetAccumulatorOutput(HAL_AnalogInputHandle analogPortHandle,
|
||||||
int64_t* value, int64_t* count, int32_t* status) {
|
int64_t* value, int64_t* count, int32_t* status) {
|
||||||
auto port = analogInputHandles.Get(analogPortHandle);
|
auto port = analogInputHandles->Get(analogPortHandle);
|
||||||
if (port == nullptr) {
|
if (port == nullptr) {
|
||||||
*status = HAL_HANDLE_ERROR;
|
*status = HAL_HANDLE_ERROR;
|
||||||
return;
|
return;
|
||||||
@@ -193,4 +200,5 @@ void HAL_GetAccumulatorOutput(HAL_AnalogInputHandle analogPortHandle,
|
|||||||
*value = output.Value;
|
*value = output.Value;
|
||||||
*count = output.Count;
|
*count = output.Count;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // extern "C"
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user