mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-03 03:01:44 +00:00
Compare commits
665 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5a292dadd | ||
|
|
77d6c11743 | ||
|
|
67f9c9a5b3 | ||
|
|
f720cbb121 | ||
|
|
64a7e57fe0 | ||
|
|
5ca00dddbe | ||
|
|
120ceb3427 | ||
|
|
5cbafc1382 | ||
|
|
39d1650d51 | ||
|
|
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 | ||
|
|
e375b4a9ff | ||
|
|
ff141ab1ff | ||
|
|
b8537be219 | ||
|
|
8f1b034b2f | ||
|
|
71d0a07e0a | ||
|
|
d322342494 | ||
|
|
bc7ab17692 | ||
|
|
7a049c29bd | ||
|
|
1fc375b31a | ||
|
|
eee7f3991c | ||
|
|
2e3503517d | ||
|
|
15e58acc76 | ||
|
|
5aa5e3e09e | ||
|
|
25ae7b2c2b | ||
|
|
4b6dc9583a | ||
|
|
64eab1f7b3 | ||
|
|
182f57216f | ||
|
|
65b091a39a | ||
|
|
ed1a94531a | ||
|
|
4e12ffb0ae | ||
|
|
4800c201e4 | ||
|
|
dc9a9e5d96 | ||
|
|
6844f05c3d | ||
|
|
8f67f2c24c | ||
|
|
cc246bb9ac | ||
|
|
bf9f0a9e6d | ||
|
|
c3160bad44 | ||
|
|
94b8ac42ca | ||
|
|
a03e3d7eb9 | ||
|
|
a42ec08d16 | ||
|
|
fddb6cd9d8 | ||
|
|
841f016017 | ||
|
|
8e4afc95c7 | ||
|
|
8cec948699 | ||
|
|
31ae7c942c | ||
|
|
d0900626da | ||
|
|
0ee4cadca0 | ||
|
|
24b5a9c389 | ||
|
|
626220e9f3 | ||
|
|
323d68d460 | ||
|
|
db2091dd94 | ||
|
|
8216d85e52 | ||
|
|
a705eb1c61 | ||
|
|
77f664a6b1 | ||
|
|
c30057e923 | ||
|
|
06108b9479 | ||
|
|
16181523c9 | ||
|
|
7e0706cf83 | ||
|
|
bff67887fd | ||
|
|
351ff5eb48 | ||
|
|
051df14046 | ||
|
|
ee0318f697 | ||
|
|
a6fb1efcbe | ||
|
|
31fecc28a4 | ||
|
|
30b1efc354 | ||
|
|
7d721eb569 | ||
|
|
d48aac5beb | ||
|
|
14b56db99e | ||
|
|
bfe429de51 | ||
|
|
57ef5cfd07 | ||
|
|
4bbb7c0bcc | ||
|
|
4de70bff5e | ||
|
|
687f0c7dc0 | ||
|
|
f3d66e92ec | ||
|
|
9a91ae54d6 | ||
|
|
69422dc063 | ||
|
|
7bcd243ec3 | ||
|
|
8f70bea899 | ||
|
|
948c4275ad | ||
|
|
03a1159915 | ||
|
|
1c8fb298b4 | ||
|
|
b25a7cb370 | ||
|
|
140c365e4b | ||
|
|
8c93ceb728 | ||
|
|
ac50d7cf8a | ||
|
|
ecb873ff45 | ||
|
|
78baa04ecc | ||
|
|
b78f580d47 | ||
|
|
b115c75226 | ||
|
|
6bc092f3ae | ||
|
|
f99a266ce4 | ||
|
|
1f724d58e0 | ||
|
|
de4a246bb4 | ||
|
|
412b80da30 | ||
|
|
47319960a5 | ||
|
|
b22d218236 | ||
|
|
6eb82bc314 | ||
|
|
a06dd25d56 | ||
|
|
e1bb05bc52 | ||
|
|
8694a020ac | ||
|
|
1efb2e4d3d | ||
|
|
861726cefa | ||
|
|
81212d80c6 | ||
|
|
2235a809c4 | ||
|
|
3fe0f49ac0 | ||
|
|
03d8f9193b | ||
|
|
5e54969f6b | ||
|
|
18ef5eb1bf | ||
|
|
b5e3d92e9d | ||
|
|
ba8761e39e | ||
|
|
78f0b1562c | ||
|
|
5c28b30028 | ||
|
|
59267da72b | ||
|
|
36ad45c07d | ||
|
|
ecb2add791 | ||
|
|
9bbdaf300b | ||
|
|
bc492bb40e | ||
|
|
81221c4874 | ||
|
|
137b3d81fb | ||
|
|
6741f47ef1 | ||
|
|
e75e9092a8 | ||
|
|
247cef5ec2 | ||
|
|
29f999e2b2 | ||
|
|
5e3755493d | ||
|
|
70343c0b3f | ||
|
|
60e199b0bd | ||
|
|
1071686d81 | ||
|
|
fdebdd520a | ||
|
|
5ca5583fc3 | ||
|
|
75463a249f | ||
|
|
7280d241f0 | ||
|
|
963391cf39 | ||
|
|
4f4c52d6d5 | ||
|
|
499da6d08d | ||
|
|
39e4d11f8e | ||
|
|
df4a2c07f0 | ||
|
|
c46c490376 | ||
|
|
f2751db5c2 | ||
|
|
2bff276adb | ||
|
|
e5e1a1a4d1 | ||
|
|
0613f1d182 | ||
|
|
8b94e0933a | ||
|
|
23ef57561d | ||
|
|
33b95816ee | ||
|
|
4c1e4fd80c | ||
|
|
3784b665de | ||
|
|
567ea1d58d | ||
|
|
55346e28d0 | ||
|
|
49b8c4ba78 | ||
|
|
f1c2b66569 | ||
|
|
27bf94fd06 | ||
|
|
4896a77c86 | ||
|
|
d1d3f049f2 | ||
|
|
c313dde03a | ||
|
|
8d1c51b7e9 | ||
|
|
a59e00e901 | ||
|
|
7070162b98 | ||
|
|
9859c14ca1 | ||
|
|
64ebe7f5e5 | ||
|
|
8b2345a706 | ||
|
|
e65f9908d7 | ||
|
|
fd52912d74 | ||
|
|
9e7993905f | ||
|
|
a656207220 | ||
|
|
81e63ea3a5 | ||
|
|
5dfae8d6bd | ||
|
|
107a4cc1e2 | ||
|
|
35d51d68f7 | ||
|
|
049fec470b | ||
|
|
659dbef751 | ||
|
|
ac9b6f7b18 | ||
|
|
425ed464ed | ||
|
|
2c15bb247e | ||
|
|
28e178b1a8 | ||
|
|
5d2a08443b | ||
|
|
087eeec760 | ||
|
|
dbe03afb9a | ||
|
|
2ecb939b35 | ||
|
|
1416fb8f67 | ||
|
|
aeb6c4889b | ||
|
|
c2fc6711d8 | ||
|
|
f271185cbc | ||
|
|
4fc7daedc9 | ||
|
|
6bfc008673 | ||
|
|
2c94d0ba2f | ||
|
|
0cd05d1a42 | ||
|
|
ff93050b31 | ||
|
|
05626cfafe | ||
|
|
59ec54887d | ||
|
|
028efff50d | ||
|
|
2499771cf4 | ||
|
|
c989ae808b | ||
|
|
93b486b6ba | ||
|
|
2ec6132fcb | ||
|
|
8aba2b2850 | ||
|
|
32c95fa0da | ||
|
|
40365faeda | ||
|
|
776cb915bc | ||
|
|
5e9fe2f5cb | ||
|
|
7501ae65a1 | ||
|
|
63469c00c4 | ||
|
|
3df257cdbb | ||
|
|
45b8e9ab4f | ||
|
|
227fdc1a60 | ||
|
|
d347cebf67 | ||
|
|
3819cd0768 | ||
|
|
e8f1fdda44 | ||
|
|
fd4719cb87 | ||
|
|
6ef4745d86 | ||
|
|
62a980d3c8 | ||
|
|
866046edd1 | ||
|
|
8ac7e44f19 | ||
|
|
a831978cce | ||
|
|
8da577b56f | ||
|
|
512ecf6490 | ||
|
|
0901ae0808 | ||
|
|
1ca291f20b | ||
|
|
75eabfee1c | ||
|
|
f7c3f13a7f | ||
|
|
57efd13f7f | ||
|
|
7ddc153623 | ||
|
|
f9ebd3bde6 | ||
|
|
2c911b0f7a | ||
|
|
1bf2d58db1 | ||
|
|
c93b5bedf9 | ||
|
|
dffaa0abb9 | ||
|
|
20c6525b1d | ||
|
|
fe7165a8f7 | ||
|
|
d2aa168f66 | ||
|
|
05c00430b3 | ||
|
|
5305087162 | ||
|
|
6251697f60 | ||
|
|
ea1a1e6bc3 | ||
|
|
edf5ecd4a0 | ||
|
|
1b1ee7f9f3 | ||
|
|
3fade171f9 | ||
|
|
c99e89dfca | ||
|
|
b51e85ae26 | ||
|
|
4a98e68815 | ||
|
|
0cb288ffba | ||
|
|
e44a6e227a | ||
|
|
aafca4ed7f | ||
|
|
ea6876e81f | ||
|
|
aa9c2b2c92 | ||
|
|
43a2eccdc9 | ||
|
|
b637b9ee4c | ||
|
|
5ad28d58ec | ||
|
|
be2647d44e | ||
|
|
4a3e3a6324 | ||
|
|
7597e3c274 | ||
|
|
0a983eeeb8 | ||
|
|
b036bf2e34 | ||
|
|
73602e6cb4 | ||
|
|
72455280a9 | ||
|
|
ea95bb85aa | ||
|
|
fb865d3ee7 | ||
|
|
36ac37db8c | ||
|
|
b45e0917ae | ||
|
|
0e127679c1 | ||
|
|
2f36d508c4 | ||
|
|
cf29d4560b | ||
|
|
8c4ad62422 | ||
|
|
62c217cd01 | ||
|
|
0f105a26f7 | ||
|
|
47694ef810 | ||
|
|
f77a976fbb | ||
|
|
3593ecb17e | ||
|
|
9b2af0d090 | ||
|
|
e8e052712e | ||
|
|
77a1af44c4 | ||
|
|
5e2a76147c | ||
|
|
e1d4845ccd | ||
|
|
95d40ed01f | ||
|
|
aa22d4c33b | ||
|
|
046e043c4e | ||
|
|
74fc10999b | ||
|
|
cee9b2609d | ||
|
|
daa0260a4e | ||
|
|
d66c61a36e | ||
|
|
ecc210f99a | ||
|
|
3cacc2aba6 | ||
|
|
085c47b671 | ||
|
|
039515082a | ||
|
|
c3908660b1 | ||
|
|
fc515f4572 | ||
|
|
5a82f73d9b | ||
|
|
776a991d61 | ||
|
|
8527f2c2a1 | ||
|
|
c85b72b952 | ||
|
|
f0d9e19b5c | ||
|
|
c7c011813f | ||
|
|
d76f0d4022 | ||
|
|
de7678f2fc | ||
|
|
2f7eff7091 | ||
|
|
7a402b4170 | ||
|
|
10b4814e60 | ||
|
|
613309c0a2 | ||
|
|
c622c03eff | ||
|
|
ed7d2d6aa6 | ||
|
|
51ff9e9f69 | ||
|
|
9f2f301fa4 | ||
|
|
fa8bb3fa91 | ||
|
|
4af0bbddee | ||
|
|
4aca3c2022 | ||
|
|
753ab85efb | ||
|
|
da6b8c7ae1 | ||
|
|
305ab08f1c | ||
|
|
e9718fc7bf | ||
|
|
8566878af4 | ||
|
|
62812faf62 | ||
|
|
d82635bbe1 | ||
|
|
a598e2d09b | ||
|
|
b5b2f0c7d8 | ||
|
|
e6f6d24780 | ||
|
|
21b2aabf18 | ||
|
|
74f9da9da1 | ||
|
|
e63830ed21 | ||
|
|
eb51de65e5 | ||
|
|
565a125dad | ||
|
|
3af8e7e9fd | ||
|
|
e3eae023da | ||
|
|
6d9b3b0aaa | ||
|
|
9e99df1cf7 | ||
|
|
e842ff7ad5 | ||
|
|
21b1e39b2a | ||
|
|
8fc55c80a9 | ||
|
|
248ca0c4a0 | ||
|
|
0d655d7cec | ||
|
|
e71f454b9d | ||
|
|
54092378e9 | ||
|
|
a4f0c4fbe0 | ||
|
|
0965d60a71 | ||
|
|
f2d601d834 | ||
|
|
e14e45da76 | ||
|
|
68690643d2 | ||
|
|
00b2902102 | ||
|
|
975568c774 | ||
|
|
a834fff7b2 | ||
|
|
64ab6e51fe | ||
|
|
05a2089816 | ||
|
|
b827f484be | ||
|
|
000a98f193 | ||
|
|
bb64dd3546 | ||
|
|
d0c40b5ce2 | ||
|
|
6794ff9ce8 | ||
|
|
083362bd86 | ||
|
|
0f228e7b7d | ||
|
|
686f5d9fef | ||
|
|
ad8763fc8d | ||
|
|
1011b56b4c | ||
|
|
5904314a75 | ||
|
|
e852547344 | ||
|
|
fa8b68419f | ||
|
|
ec13d00b18 | ||
|
|
36447d86d8 | ||
|
|
1e14403b3b | ||
|
|
bee507eda8 |
107
.clang-format
Normal file
107
.clang-format
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Auto
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
50
.gitignore
vendored
50
.gitignore
vendored
@@ -1,13 +1,10 @@
|
|||||||
# WPIlib Specific
|
# WPIlib Specific
|
||||||
|
|
||||||
dependency-reduced-pom.xml
|
dependency-reduced-pom.xml
|
||||||
/wpilibj/src/athena/cpp/nivision/*.c
|
/wpilibj/src/shared/java/edu/wpi/first/wpilibj/util/WPILibVersion.java
|
||||||
/wpilibj/src/athena/cpp/nivision/*.cpp
|
/wpilibc/shared/src/WPILibVersion.cpp
|
||||||
/wpilibj/src/athena/cpp/nivision/*.s
|
/wpilibj/src/main/java/edu/wpi/first/wpilibj/util/WPILibVersion.java
|
||||||
/wpilibj/src/athena/cpp/nivision/*_arm.ini
|
/wpilibc/src/main/native/cpp/WPILibVersion.cpp
|
||||||
/wpilibj/src/athena/cpp/nivision/*.java
|
|
||||||
/wpilibj/src/athena/cpp/nivision/nivision_funcs.txt
|
|
||||||
/wpilibj/src/athena/cpp/nivision/imaqdx_funcs.txt
|
|
||||||
doxygen.log
|
doxygen.log
|
||||||
|
|
||||||
# Created by the jenkins test script
|
# Created by the jenkins test script
|
||||||
@@ -15,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
|
||||||
@@ -155,6 +154,9 @@ local.properties
|
|||||||
*.pyc
|
*.pyc
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
||||||
|
# Gradle wrapper
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
# External tool builders
|
# External tool builders
|
||||||
.externalToolBuilders/
|
.externalToolBuilders/
|
||||||
|
|
||||||
@@ -181,3 +183,37 @@ NO
|
|||||||
|
|
||||||
# Simulation folder stuff
|
# Simulation folder stuff
|
||||||
!simulation/install_resources/*
|
!simulation/install_resources/*
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
#classpaths and projects
|
||||||
|
.project
|
||||||
|
.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/
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
[gerrit]
|
|
||||||
host=usfirst.collab.net
|
|
||||||
port=29418
|
|
||||||
project=allwpilib
|
|
||||||
defaultbranch=master
|
|
||||||
41
.styleguide
Normal file
41
.styleguide
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
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 {
|
||||||
|
^HAL/
|
||||||
|
^llvm/
|
||||||
|
^networktables/
|
||||||
|
^opencv2/
|
||||||
|
^support/
|
||||||
|
}
|
||||||
|
|
||||||
|
includeProject {
|
||||||
|
^ctre/
|
||||||
|
}
|
||||||
6
.styleguide-license
Normal file
6
.styleguide-license
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/* Copyright (c) {year} FIRST. All Rights Reserved.{padding}*/
|
||||||
|
/* 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. */
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
40
.travis.yml
Normal file
40
.travis.yml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
sudo: true
|
||||||
|
dist: trusty
|
||||||
|
language: java
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- deadsnakes
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-6
|
||||||
|
- python3.5
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- sudo sh -c 'echo "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main" > /etc/apt/sources.list.d/llvm.list'
|
||||||
|
- wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
|
||||||
|
- sudo apt-get update -q || true
|
||||||
|
- sudo apt-get install clang-format-5.0 -y
|
||||||
|
|
||||||
|
install:
|
||||||
|
- 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:
|
||||||
|
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.gradle/caches/
|
||||||
|
- $HOME/.gradle/wrapper/
|
||||||
|
|
||||||
|
script:
|
||||||
|
- python3.5 -m wpiformat -y 2018 -clang 5.0
|
||||||
|
- git --no-pager diff --exit-code HEAD # Ensure formatter made no changes
|
||||||
|
- ./gradlew --no-daemon --console=plain -PskipAthena :hal:halSimSharedLibrary :wpilibc:wpilibcSharedLibrary :wpilibj:wpilibJNISharedSharedLibrary :wpilibj:jar
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
* Copyright (c) 2009-2016 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.
|
|
||||||
@@ -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/simulation)
|
|
||||||
add_subdirectory(simulation/frc_gazebo_plugins)
|
|
||||||
56
CONTRIBUTING.md
Normal file
56
CONTRIBUTING.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Contributing to WPILib
|
||||||
|
|
||||||
|
So you want to contribute your changes back to WPILib. Great! We have a few contributing rules that will help you make sure your changes will be accepted into the project. Please remember to follow the rules written here, and behave with Gracious Professionalism.
|
||||||
|
|
||||||
|
- [General Contribution Rules](#general-contribution-rules)
|
||||||
|
- [What to Contribute](#what-to-contribute)
|
||||||
|
- [Coding Guidelines](#coding-guidelines)
|
||||||
|
- [Submitting Changes](#submitting-changes)
|
||||||
|
- [Pull Request Format](#pull-request-format)
|
||||||
|
- [Merge Process](#merge-process)
|
||||||
|
- [Licensing](#licensing)
|
||||||
|
|
||||||
|
## General Contribution Rules
|
||||||
|
|
||||||
|
- Everything in the library must work for the 3000+ teams that will be using it.
|
||||||
|
- We need to be able to maintain submitted changes, even if you are no longer working on the project.
|
||||||
|
- Tool suite changes must be generally useful to a broad range of teams
|
||||||
|
- Excluding bug fixes, changes in one language generally need to have corresponding changes in other languages.
|
||||||
|
- Some features, such the addition of C++11 for WPILibC or Functional Interfaces for WPILibJ, are specific to that version of WPILib only.
|
||||||
|
- Substantial changes often need to have corresponding LabVIEW changes. To do this, we will work with NI on these large changes.
|
||||||
|
- Changes should have tests.
|
||||||
|
- Code should be well documented.
|
||||||
|
- This often involves ScreenSteps. To add content to ScreenSteps, we will work with you to get the appropriate articles written.
|
||||||
|
|
||||||
|
## What to Contribute
|
||||||
|
|
||||||
|
- Bug reports and fixes
|
||||||
|
- We will generally accept bug fixes without too much question. If they are only implemented for one language, we will implement them for any other necessary languages. Bug reports are also welcome, please submit them to our GitHub issue tracker.
|
||||||
|
- While we do welcome improvements to the API, there are a few important rules to consider:
|
||||||
|
- Features must be added to both WPILibC and WPILibJ, with rare exceptions.
|
||||||
|
- During competition season, we will not merge any new feature additions. We want to ensure that the API is stable during the season to help minimize issues for teams.
|
||||||
|
- Ask about large changes before spending a bunch of time on them! You can create a new issue on our GitHub tracker for feature request/discussion and talk about it with us there.
|
||||||
|
- Features that make it easier for teams with less experience to be more successful are more likely to be accepted.
|
||||||
|
- Features in WPILib should be broadly applicable to all teams. Anything that is team specific should not be submitted.
|
||||||
|
- As a rule, we are happy with the general structure of WPILib. We are not interested in major rewrites of all of WPILib. We are open to talking about ideas, but backwards compatibility is very important for WPILib, so be sure to keep this in mind when proposing major changes.
|
||||||
|
- Generally speaking, we do not accept code for specific sensors. We have to be able to test the sensor in hardware on the WPILib test bed. Additionally, hardware availability for teams is important. Therefore, as a general rule, the library only directly supports hardware that is in the Kit of Parts. If you are a company interested in getting a sensor into the Kit of Parts, please contact FIRST directly at frcparts@firstinspires.org.
|
||||||
|
|
||||||
|
## Coding Guidelines
|
||||||
|
|
||||||
|
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system.
|
||||||
|
|
||||||
|
While the library should be fully formatted according to the styles, additional elements of the style guide were not followed when the library was initially created. All new code should follow the guidelines. If you are looking for some easy ramp-up tasks, finding areas that don't follow the style guide and fixing them is very welcome.
|
||||||
|
|
||||||
|
## Submitting Changes
|
||||||
|
|
||||||
|
### Pull Request Format
|
||||||
|
|
||||||
|
Changes should be submitted as a Pull Request against the master branch of WPILib. For most changes, we ask that you squash your changes down to a single commit. For particularly large changes, multiple commits are ok, but assume one commit unless asked otherwise. No change will be merged unless it is up to date with the current master. We will also not merge any changes with merge commits in them; please rebase off of master before submitting a pull request. We do this to make sure that the git history isn't too cluttered.
|
||||||
|
|
||||||
|
### Merge Process
|
||||||
|
|
||||||
|
When you first submit changes, Travis-CI will attempt to run `./gradlew check` on your change. If this fails, you will need to fix any issues that it sees. Once Travis passes, we will begin the review process in more earnest. One or more WPILib team members will review your change. This will be a back-and-forth process with the WPILib team and the greater community. Once we are satisfied that your change is ready, we will allow our Jenkins instance to test it. This will run the full gamut of checks, including integration tests on actual hardware. Once all tests have passed and the team is satisfied, we will merge your change into the WPILib repository.
|
||||||
|
|
||||||
|
## Licensing
|
||||||
|
|
||||||
|
By contributing to WPILib, you agree that your code will be distributed with WPILib, and licensed under the license for the WPILib project. You should not contribute code that you do not have permission to relicense in this manner. This includes code that is licensed under the GPL that you do not have permission to relicense, as WPILib is not released under a copyleft license. Our license is the 3-clause BSD license, which you can find [here](license.txt).
|
||||||
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.
|
||||||
71
README.md
71
README.md
@@ -1,36 +1,70 @@
|
|||||||
|
# WPILib Project
|
||||||
|
|
||||||
|
[](https://travis-ci.org/wpilibsuite/allwpilib)
|
||||||
|
|
||||||
|
Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WPILibC projects. These are the core libraries for creating robot programs for the roboRIO.
|
||||||
|
|
||||||
|
- [WPILib Mission](#wpilib-mission)
|
||||||
|
- [Building WPILib](#building-wpilib)
|
||||||
|
- [Requirements](#requirements)
|
||||||
|
- [Setup](#setup)
|
||||||
|
- [Building](#building)
|
||||||
|
- [Publishing](#publishing)
|
||||||
|
- [Structure and Organization](#structure-and-organization)
|
||||||
|
- [Contributing to WPILib](#contributing-to-wpilib)
|
||||||
|
|
||||||
|
## WPILib Mission
|
||||||
|
|
||||||
|
The WPILib Mission is to enable FIRST Robotics teams to focus on writing game-specific software rather than focussing on hardware details - "raise the floor, don't lower the ceiling". We work to enable teams with limited programming knowledge and/or mentor experience to be as successful as possible, while not hampering the abilities of teams with more advanced programming capabilities. We support Kit of Parts control system components directly in the library. We also strive to keep parity between major features of each language (Java, C++, and NI's LabVIEW), so that teams aren't at a disadvantage for choosing a specific programming language. WPILib is an open source project, licensed under the BSD 3-clause license. You can find a copy of the license [here](license.txt).
|
||||||
|
|
||||||
# Building WPILib
|
# Building WPILib
|
||||||
|
|
||||||
Building WPILib is very straightforward. WPILib uses Gradle to compile. It only has a few dependencies on outside tools, including the ARM cross compiler.
|
Using Gradle makes building WPILib very straightforward. It only has a few dependencies on outside tools, such as the ARM cross compiler for creating roboRIO binaries.
|
||||||
|
|
||||||
## 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)
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
Clone the WPILib Repo. If the toolchains are not installed, install them, and make sure they are available on the system PATH.
|
|
||||||
|
Clone the WPILib repository. If the toolchains are not installed, install them, and make sure they are available on the system PATH.
|
||||||
|
|
||||||
|
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/master/README.md) for wpiformat setup instructions.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
All build steps are executed using the Gradle wrapper, `gradlew`. Each target that Gradle can build is referred to as a task. The most common Gradle task to use is `build`. This will build all of the outputs created by WPILib. To run, open a console and cd into the cloned WPILib directory. Then:
|
|
||||||
|
All build steps are executed using the Gradle wrapper, `gradlew`. Each target that Gradle can build is referred to as a task. The most common Gradle task to use is `build`. This will build all the outputs created by WPILib. To run, open a console and cd into the cloned WPILib directory. Then:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gradlew build
|
./gradlew build
|
||||||
```
|
```
|
||||||
|
|
||||||
To build a specific subproject, such as wpilibc, you must access the subproject and run the build task only on that project. Accessing a subproject in Gradle is quite easy. Simply use `:subproject_name:task_name` with the Gradle wrapper. For example, building just wpilibc:
|
To build a specific subproject, such as WPILibC, you must access the subproject and run the build task only on that project. Accessing a subproject in Gradle is quite easy. Simply use `:subproject_name:task_name` with the Gradle wrapper. For example, building just WPILibC:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gradlew :wpilibc:build
|
./gradlew :wpilibc:build
|
||||||
```
|
```
|
||||||
|
|
||||||
If you also want simulation to be build, add -PmakeSim. This requires gazebo_transport. We have tested on 14.04 and 15.05, but any correct install of gazebo should work, even on windows if you build from source. Correct means cmake needs to be able to find gazebo-config.cmake, which you get for free with ubuntu installs.
|
If you have installed the FRC Toolchain to a directory other than the default, or if the Toolchain location is not on your System PATH, you can pass the `toolChainPath` property to specify where it is located. Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew build -PtoolChainPath=some/path/to/frc/toolchain/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
If you also want simulation to be built, add -PmakeSim. This requires gazebo_transport. We have tested on 14.04 and 15.05, but any correct install of Gazebo should work, even on Windows if you build Gazebo from source. Correct means CMake needs to be able to find gazebo-config.cmake. See [The Gazebo website](https://gazebosim.org/) for installation instructions.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gradlew build -PmakeSim
|
./gradlew build -PmakeSim
|
||||||
```
|
```
|
||||||
|
|
||||||
C++ simulation tasks (including plugins, gz_msgs, and wpilibcSim) all depend on gazebo_transport. In order for this to build you must have installed gazebo. See [The Gazebo website](https://gazebosim.org/) for installation instructions.
|
|
||||||
If you prefer to use CMake directly, the you can still do so.
|
If you prefer to use CMake directly, the you can still do so.
|
||||||
The common cmake tasks are wpilibcSim, frc_gazebo_plugins, and gz_msgs
|
The common CMake tasks are wpilibcSim, frc_gazebo_plugins, and gz_msgs
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir build #run this in the root of allwpilib
|
mkdir build #run this in the root of allwpilib
|
||||||
@@ -39,13 +73,15 @@ cmake ..
|
|||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The gradlew wrapper only exists in the root of the main project, so be sure to run all commands from there. All of the subprojects have build tasks that can be run. Gradle automatically determines and rebuilds dependencies, so if you make a change in the HAL and then run `./gradlew :wpilibc:build`, the HAL will be rebuilt, then WPILibC.
|
||||||
The gradlew wrapper only exists in the root of the main project, so be sure to run all commands from there. All of the subprojects have build tasks that can be run. Gradle automatically determines and rebuilds dependencies, so if you make a change to the HAL and then run `:wpilibc:build`, the HAL will be rebuilt, then wpilibc.
|
|
||||||
|
|
||||||
There are a few tasks other than `build` available. To see them, run the meta-task `tasks`. This will print a list of all available tasks, with a description of each task.
|
There are a few tasks other than `build` available. To see them, run the meta-task `tasks`. This will print a list of all available tasks, with a description of each task.
|
||||||
|
|
||||||
|
wpiformat can be executed anywhere in the repository via `py -3 -m wpiformat` on Windows or `python3 -m wpiformat` on other platforms.
|
||||||
|
|
||||||
## Publishing
|
## Publishing
|
||||||
If you are building to test with the eclipse plugins or just want to export the build as a Maven-style dependency, simply run the `publish` task. This task will publish all available packages to ~/releases/maven/development. If you need to publish the project to a different repo, you can specify it with `-Prepo=repo_name`. Valid options are:
|
|
||||||
|
If you are building to test with the Eclipse plugins or just want to export the build as a Maven-style dependency, simply run the `publish` task. This task will publish all available packages to ~/releases/maven/development. If you need to publish the project to a different repo, you can specify it with `-Prepo=repo_name`. Valid options are:
|
||||||
|
|
||||||
- development - The default repo.
|
- development - The default repo.
|
||||||
- beta - Publishes to ~/releases/maven/beta.
|
- beta - Publishes to ~/releases/maven/beta.
|
||||||
@@ -54,20 +90,25 @@ If you are building to test with the eclipse plugins or just want to export the
|
|||||||
|
|
||||||
The following maven targets a published by this task:
|
The following maven targets a published by this task:
|
||||||
|
|
||||||
- edu.wpi.first.wpilib.cmake:cpp-root:1.0.0 - RoboRIO C++
|
- edu.wpi.first.wpilib.cmake:cpp-root:1.0.0 - roboRIO C++
|
||||||
- edu.wpi.first.wpilibc.simulation:WPILibCSim:0.1.0 - Simulation C++
|
- edu.wpi.first.wpilibc.simulation:WPILibCSim:0.1.0 - Simulation C++
|
||||||
- edu.wpi.first.wpilibj:wpilibJavaFinal:0.1.0-SNAPSHOT - RoboRIO Java
|
- edu.wpi.first.wpilibj:wpilibJavaFinal:0.1.0-SNAPSHOT - roboRIO Java
|
||||||
- edu.wpi.first.wpilibj:wpilibJavaSim:0.1.0-SNAPSHOT - Simulation Java
|
- edu.wpi.first.wpilibj:wpilibJavaSim:0.1.0-SNAPSHOT - Simulation Java
|
||||||
- edu.wpi.first.wpilibj.simulation:SimDS:0.1.0-SNAPSHOT - The driverstation for controlling simulation.
|
- edu.wpi.first.wpilibj.simulation:SimDS:0.1.0-SNAPSHOT - The driverstation for controlling simulation.
|
||||||
- org.gazebosim:JavaGazebo:0.1.0-SNAPSHOT - Gazebo protocol for Java.
|
- org.gazebosim:JavaGazebo:0.1.0-SNAPSHOT - Gazebo protocol for Java.
|
||||||
|
|
||||||
## Structure and Organization
|
## Structure and Organization
|
||||||
The main wpilib code you're probably looking for is in wpilibj and wpilibc. Those directories are split into shared, sim, and athena. Athena contains the wpilib code meant to run on your RoboRIO. Sim is wpilib code meant to run on your computer with gazebo, and shared is code shared between the two. Shared code must be platform-independent, since it will be compiled with both the ARM cross-compiler and whatever desktop compiler you are using (g++, msvc, etc...).
|
|
||||||
|
The main WPILib code you're probably looking for is in WPILibJ and WPILibC. Those directories are split into shared, sim, and athena. Athena contains the WPILib code meant to run on your roboRIO. Sim is WPILib code meant to run on your computer with Gazebo, and shared is code shared between the two. Shared code must be platform-independent, since it will be compiled with both the ARM cross-compiler and whatever desktop compiler you are using (g++, msvc, etc...).
|
||||||
|
|
||||||
The Simulation directory contains extra simulation tools and libraries, such as gz_msgs and JavaGazebo. See sub-directories for more information.
|
The Simulation directory contains extra simulation tools and libraries, such as gz_msgs and JavaGazebo. See sub-directories for more information.
|
||||||
|
|
||||||
The integration test directories for C++ and Java contain test code that runs on our test-system. When you submit code for review, it is tested by those programs. If you add new functionality you should make sure to write tests for it so we don't break it in the future.
|
The integration test directories for C++ and Java contain test code that runs on our test-system. When you submit code for review, it is tested by those programs. If you add new functionality you should make sure to write tests for it so we don't break it in the future.
|
||||||
|
|
||||||
The hal directory contains more C++ code meant to run on the RoboRIO. HAL is an acronym for "Hardware Abstraction Layer", and it interfaces with the NI Libraries. The NI Libraries contain the low-level code for controlling devices on your robot. The NI Libraries are found in the ni-libraries folder.
|
The hal directory contains more C++ code meant to run on the roboRIO. HAL is an acronym for "Hardware Abstraction Layer", and it interfaces with the NI Libraries. The NI Libraries contain the low-level code for controlling devices on your robot. The NI Libraries are found in the ni-libraries folder.
|
||||||
|
|
||||||
The styleguide directory contains the styleguide for C++ and Java code. Anything submitted to the wpilib project needs to follow the code style guides outlined in there.
|
The [styleguide repository](https://github.com/wpilibsuite/styleguide) contains our style guides for C++ and Java code. Anything submitted to the WPILib project needs to follow the code style guides outlined in there. For details about the style, please see the contributors document [here](CONTRIBUTING.md#coding-guidelines).
|
||||||
|
|
||||||
|
# Contributing to WPILib
|
||||||
|
|
||||||
|
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||||
|
|||||||
@@ -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?
|
|
||||||
201
build.gradle
201
build.gradle
@@ -1,34 +1,188 @@
|
|||||||
def enableSimulation = hasProperty('enableSimulation')
|
import edu.wpi.first.nativeutils.NativeUtils
|
||||||
|
import edu.wpi.first.nativeutils.tasks.JNIHeaders
|
||||||
if (!hasProperty('repo')) {
|
|
||||||
ext.repo = 'development'
|
|
||||||
}
|
|
||||||
|
|
||||||
def repoBaseUrl = "http://first.wpi.edu/FRC/roborio/maven/${repo}"
|
|
||||||
def publishUrl = "${System.getProperty('user.home')}/releases/maven/${repo}"
|
|
||||||
|
|
||||||
ext.simulationInstallDir = "$rootDir/build/install/simulation"
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
ext.enableSimulation = enableSimulation
|
|
||||||
ext.repo = repo
|
|
||||||
|
|
||||||
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenLocal()
|
||||||
maven {
|
maven {
|
||||||
url publishUrl
|
url "https://plugins.gradle.org/m2/"
|
||||||
}
|
|
||||||
maven {
|
|
||||||
url repoBaseUrl
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'gradle.plugin.edu.wpi.first:native-utils:1.5.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'net.ltgt.errorprone' version '0.0.10'
|
||||||
|
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
|
||||||
|
// already specified on the command line
|
||||||
|
if (!hasProperty('releaseType')) {
|
||||||
|
WPILibVersion {
|
||||||
|
releaseType = 'dev'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def pubVersion
|
||||||
|
if (project.hasProperty("publishVersion")) {
|
||||||
|
pubVersion = project.publishVersion
|
||||||
|
} else {
|
||||||
|
pubVersion = WPILibVersion.version
|
||||||
|
}
|
||||||
|
|
||||||
|
def outputsFolder = file("$buildDir/outputs")
|
||||||
|
|
||||||
|
def versionFile = file("$outputsFolder/version.txt")
|
||||||
|
|
||||||
|
task outputVersions() {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
versionFile.write pubVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task build() {}
|
||||||
|
|
||||||
|
build.dependsOn outputVersions
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
apply plugin: 'eclipse'
|
apply plugin: 'eclipse'
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
|
apply plugin: 'checkstyle'
|
||||||
|
|
||||||
ext.armBuild = true
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
@@ -36,12 +190,13 @@ subprojects {
|
|||||||
options.addStringOption('Xdoclint:none', '-quiet')
|
options.addStringOption('Xdoclint:none', '-quiet')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.setupWpilibRepo = { publishing ->
|
ext.setupWpilibRepo = { publishing ->
|
||||||
publishing.repositories.maven {
|
publishing.repositories.maven {
|
||||||
url = "${System.getProperty('user.home')}/releases/maven/${repo}"
|
url = WPILibVersion.mavenLocalUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: 'cppSettings.gradle'
|
task wrapper(type: Wrapper) {
|
||||||
|
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,194 +0,0 @@
|
|||||||
// This regex matches either a Windows or Unix style file separator, then the lib part of the library,
|
|
||||||
// then the name of the library itself, and finally the .so extension at the end. The name of the library
|
|
||||||
// is in the libName capture group, which is extracted and used for the linker flags
|
|
||||||
def libPattern = /.*((\\/|\\).*)+lib(?<libName>.+).so$/
|
|
||||||
def niLibraryArgs = []
|
|
||||||
def niLibraryPath = file('ni-libraries').path
|
|
||||||
|
|
||||||
// The NI Library tree includes all non-wpi libraries, which is everything that doesn't have libwpi in the name
|
|
||||||
def niLibraryTree = fileTree(niLibraryPath)
|
|
||||||
niLibraryTree.include '*.so'
|
|
||||||
niLibraryTree.exclude '*wpi*.so'
|
|
||||||
|
|
||||||
// This adds all linker flags to the list of ni library linker flags
|
|
||||||
niLibraryTree.each { lib ->
|
|
||||||
def nameMatcher = (lib.path =~ libPattern)
|
|
||||||
if (nameMatcher[0].size() > 1) {
|
|
||||||
def name = nameMatcher.group('libName')
|
|
||||||
niLibraryArgs << '-l' + name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def armNtDependency =
|
|
||||||
project.dependencies.create("edu.wpi.first.wpilib.networktables.cpp:NetworkTables:3.0.0-SNAPSHOT:arm@zip")
|
|
||||||
def armConfig = project.configurations.detachedConfiguration(armNtDependency)
|
|
||||||
armConfig.setTransitive(false)
|
|
||||||
def armNetTables = armConfig.files[0].canonicalFile
|
|
||||||
|
|
||||||
def desktopNetTables
|
|
||||||
if (project.hasProperty('makeSim')){
|
|
||||||
def desktopNtDependency =
|
|
||||||
project.dependencies.create("edu.wpi.first.wpilib.networktables.cpp:NetworkTables:3.0.0-SNAPSHOT:desktop@zip")
|
|
||||||
def desktopConfig = project.configurations.detachedConfiguration(desktopNtDependency)
|
|
||||||
desktopConfig.setTransitive(false)
|
|
||||||
desktopNetTables = desktopConfig.files[0].canonicalFile
|
|
||||||
}
|
|
||||||
|
|
||||||
def netTablesUnzipLocation = "$buildDir/networktables"
|
|
||||||
|
|
||||||
// Create a task that will unzip the networktables files into a temporary build directory
|
|
||||||
task unzipNetworkTables(type: Copy) {
|
|
||||||
description = 'Unzips the networktables maven dependency so that the include files and libraries can be used'
|
|
||||||
group = 'WPILib'
|
|
||||||
if (project.hasProperty('makeSim')){
|
|
||||||
from zipTree(desktopNetTables)
|
|
||||||
}
|
|
||||||
from zipTree(armNetTables)
|
|
||||||
into netTablesUnzipLocation
|
|
||||||
}
|
|
||||||
|
|
||||||
task clean(type: Delete) {
|
|
||||||
description = "Deletes the build directory"
|
|
||||||
group = "Build"
|
|
||||||
delete buildDir
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
|
||||||
plugins.withType(CppPlugin).whenPluginAdded {
|
|
||||||
// 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 (project.hasProperty('makeSim')){
|
|
||||||
ext.netLibDesktopLocation = "$netTablesUnzipLocation/Linux/amd64"
|
|
||||||
}
|
|
||||||
ext.netSharedLib = "$netLibArmLocation/libntcore.so"
|
|
||||||
ext.netStaticLib = "$netLibArmLocation/libntcore.a"
|
|
||||||
|
|
||||||
task addNetworkTablesLibraryLinks() {
|
|
||||||
description = 'Adds the linker flags for the networktables libraries retreived from maven'
|
|
||||||
group = 'WPILib'
|
|
||||||
dependsOn project(':').unzipNetworkTables
|
|
||||||
doLast {
|
|
||||||
binaries.all {
|
|
||||||
tasks.withType(CppCompile) {
|
|
||||||
// desktop version doesn't use all the NI libraries
|
|
||||||
// so only do this for arm libraries
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')){
|
|
||||||
linker.args netStaticLib
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
model {
|
|
||||||
buildTypes {
|
|
||||||
debug
|
|
||||||
}
|
|
||||||
// Adds a custom toolchain for our compiler prefix and options
|
|
||||||
toolChains {
|
|
||||||
gcc(Gcc) {
|
|
||||||
target('arm') {
|
|
||||||
// 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
|
|
||||||
def compilerPrefix = 'arm-frc-linux-gnueabi-'
|
|
||||||
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' << '-O0' << '-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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Workaround for OS X. Macs for some reason want to use Xcode's gcc
|
|
||||||
// (which just wraps Clang), so we have to explicitly make it so
|
|
||||||
// that trying to compile with Clang will call gcc instead
|
|
||||||
macGcc(Clang) {
|
|
||||||
target('arm') {
|
|
||||||
// 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
|
|
||||||
def compilerPrefix = 'arm-frc-linux-gnueabi-'
|
|
||||||
cppCompiler.executable = compilerPrefix + 'g++'
|
|
||||||
linker.executable = compilerPrefix + 'g++'
|
|
||||||
assembler.executable = compilerPrefix + 'gcc'
|
|
||||||
// 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' << '-O0' << '-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 + 'ar'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The only platform is arm linux
|
|
||||||
platforms {
|
|
||||||
arm {
|
|
||||||
architecture 'arm'
|
|
||||||
operatingSystem 'linux'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This task adds the appropriate linker flags for the NI libraries
|
|
||||||
task addNiLibraryLinks() {
|
|
||||||
description = 'Adds the linker flags for the NI libraries in the ni-library folders'
|
|
||||||
group = 'WPILib'
|
|
||||||
doLast {
|
|
||||||
binaries.all {
|
|
||||||
tasks.withType(CppCompile) {
|
|
||||||
// desktop version doesn't use all the NI libraries
|
|
||||||
// so only do this for arm libraries
|
|
||||||
String architecture = targetPlatform.architecture
|
|
||||||
if (architecture.contains('arm')){
|
|
||||||
linker.args << '-L' + niLibraryPath
|
|
||||||
linker.args.addAll(niLibraryArgs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model {
|
|
||||||
repositories {
|
|
||||||
libs(PrebuiltLibraries) { libs ->
|
|
||||||
// Loops through all .so files (except files matching *libwpi*.so) in ../ni-libraries
|
|
||||||
// and includes them for linking
|
|
||||||
niLibraryTree.each { niLib ->
|
|
||||||
libs.create(niLib) {
|
|
||||||
binaries.withType(SharedLibraryBinary) {
|
|
||||||
sharedLibraryFile = file(niLib.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
178
gen/wpilibj_frcnetcomm.py
Executable file
178
gen/wpilibj_frcnetcomm.py
Executable file
@@ -0,0 +1,178 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# This script generates the network communication interface for wpilibj.
|
||||||
|
#
|
||||||
|
# This script takes no arguments and should be invoked from either the gen
|
||||||
|
# directory or the root directory of the project.
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
# Check that the current directory is part of a Git repository
|
||||||
|
def inGitRepo(directory):
|
||||||
|
ret = subprocess.run(["git", "rev-parse"], stderr = subprocess.DEVNULL)
|
||||||
|
return ret.returncode == 0
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not inGitRepo("."):
|
||||||
|
print("Error: not invoked within a Git repository", file = sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Handle running in either the root or gen directories
|
||||||
|
configPath = "."
|
||||||
|
if os.getcwd().rpartition(os.sep)[2] == "gen":
|
||||||
|
configPath = ".."
|
||||||
|
|
||||||
|
outputName = configPath + \
|
||||||
|
"/wpilibj/src/athena/java/edu/wpi/first/wpilibj/hal/FRCNetComm.java"
|
||||||
|
|
||||||
|
# Set initial copyright year and get current year
|
||||||
|
year = "2016"
|
||||||
|
currentYear = str(date.today().year)
|
||||||
|
|
||||||
|
# Start writing output file
|
||||||
|
with open(outputName + ".tmp", "w") as temp:
|
||||||
|
# Write first line of comment
|
||||||
|
temp.write("/*")
|
||||||
|
for i in range(0, 76):
|
||||||
|
temp.write("-")
|
||||||
|
temp.write("*/\n")
|
||||||
|
|
||||||
|
# Write second line of comment
|
||||||
|
temp.write("/* Copyright (c) FIRST ")
|
||||||
|
if year != currentYear:
|
||||||
|
temp.write(year)
|
||||||
|
temp.write("-")
|
||||||
|
temp.write(currentYear)
|
||||||
|
temp.write(". All Rights Reserved.")
|
||||||
|
for i in range(0, 24):
|
||||||
|
temp.write(" ")
|
||||||
|
if year == currentYear:
|
||||||
|
for i in range(0, 5):
|
||||||
|
temp.write(" ")
|
||||||
|
temp.write("*/\n")
|
||||||
|
|
||||||
|
# Write rest of lines of comment
|
||||||
|
temp.write("""\
|
||||||
|
/* 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. */
|
||||||
|
/*""")
|
||||||
|
for i in range(0, 76):
|
||||||
|
temp.write("-")
|
||||||
|
temp.write("*/\n")
|
||||||
|
|
||||||
|
# Write preamble
|
||||||
|
temp.write("""
|
||||||
|
package edu.wpi.first.wpilibj.hal;
|
||||||
|
|
||||||
|
import edu.wpi.first.wpilibj.hal.JNIWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JNI wrapper for library <b>FRC_NetworkCommunication</b><br>.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings(\"MethodName\")
|
||||||
|
public class FRCNetComm extends JNIWrapper {
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Read enums from C++ source files
|
||||||
|
firstEnum = True
|
||||||
|
for fileName in ["LoadOut.h", "UsageReporting.h"]:
|
||||||
|
with open(configPath + "/hal/include/FRC_NetworkCommunication/" + \
|
||||||
|
fileName, "r") as cppSource:
|
||||||
|
while True:
|
||||||
|
# Read until an enum is encountered
|
||||||
|
line = ""
|
||||||
|
pos = -1
|
||||||
|
while line.find("enum") == -1:
|
||||||
|
line = cppSource.readline()
|
||||||
|
if line == "":
|
||||||
|
break
|
||||||
|
|
||||||
|
if line == "":
|
||||||
|
break
|
||||||
|
|
||||||
|
# If "{" is on next line, read next line
|
||||||
|
if line.find("{") == -1:
|
||||||
|
line = cppSource.readline()
|
||||||
|
|
||||||
|
# Write enum to output file as interface
|
||||||
|
values = []
|
||||||
|
line = cppSource.readline()
|
||||||
|
while line.find("}") == -1:
|
||||||
|
if line == "\n":
|
||||||
|
values.append("")
|
||||||
|
else:
|
||||||
|
if line[0] != "#":
|
||||||
|
line = line.strip()
|
||||||
|
if line[len(line) - 1] == ",":
|
||||||
|
values.append(line[0:len(line) - 1])
|
||||||
|
else:
|
||||||
|
values.append(line)
|
||||||
|
line = cppSource.readline()
|
||||||
|
|
||||||
|
# Extract enum name
|
||||||
|
nameStart = 0
|
||||||
|
for i, c in enumerate(line):
|
||||||
|
if c != " " and c != "}":
|
||||||
|
nameStart = i
|
||||||
|
break
|
||||||
|
enumName = line[nameStart:len(line) - 2]
|
||||||
|
|
||||||
|
# Write comment for interface name
|
||||||
|
# Only add newline if not the first enum
|
||||||
|
if firstEnum == True:
|
||||||
|
firstEnum = False
|
||||||
|
else:
|
||||||
|
temp.write("\n")
|
||||||
|
temp.write(" /**\n"
|
||||||
|
" * ")
|
||||||
|
|
||||||
|
# Splits camelcase string into words
|
||||||
|
enumCamel = re.findall(r'[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))',
|
||||||
|
enumName)
|
||||||
|
temp.write(enumCamel[0] + " ")
|
||||||
|
for i in range(1, len(enumCamel)):
|
||||||
|
temp.write(enumCamel[i][0].lower() + \
|
||||||
|
enumCamel[i][1:len(enumCamel[i])] + " ")
|
||||||
|
temp.write("from " + fileName + "\n"
|
||||||
|
" */\n"
|
||||||
|
" @SuppressWarnings(\"TypeName\")\n"
|
||||||
|
" public interface " + enumName + " {\n")
|
||||||
|
|
||||||
|
# Write enum values
|
||||||
|
count = 0
|
||||||
|
for value in values:
|
||||||
|
# Pass through empty lines
|
||||||
|
if value == "":
|
||||||
|
temp.write("\n")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if value.find("=") == -1:
|
||||||
|
value = value + " = " + str(count)
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
# Add scoping for values from a different enum
|
||||||
|
if enumName != "tModuleType" and \
|
||||||
|
value.find("kModuleType") != -1:
|
||||||
|
value = value.replace("kModuleType",
|
||||||
|
"tModuleType.kModuleType")
|
||||||
|
temp.write(" int " + value[0:len(value)] + ";\n")
|
||||||
|
|
||||||
|
# Write end of enum
|
||||||
|
temp.write(" }\n")
|
||||||
|
|
||||||
|
# Write closing brace for file
|
||||||
|
temp.write("}\n")
|
||||||
|
|
||||||
|
# Replace old output file
|
||||||
|
try:
|
||||||
|
os.remove(outputName)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
os.rename(outputName + ".tmp", outputName)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
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()
|
||||||
@@ -103,10 +103,6 @@
|
|||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
#include "gtest/internal/gtest-internal.h"
|
#include "gtest/internal/gtest-internal.h"
|
||||||
|
|
||||||
#if GTEST_HAS_STD_TUPLE_
|
|
||||||
# include <tuple>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// Definitions in the 'internal' and 'internal2' name spaces are
|
// Definitions in the 'internal' and 'internal2' name spaces are
|
||||||
@@ -484,16 +480,14 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
|||||||
}
|
}
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
#if GTEST_HAS_TR1_TUPLE
|
||||||
|
// Overload for ::std::tr1::tuple. Needed for printing function arguments,
|
||||||
|
// which are packed as tuples.
|
||||||
|
|
||||||
// Helper function for printing a tuple. T must be instantiated with
|
// Helper function for printing a tuple. T must be instantiated with
|
||||||
// a tuple type.
|
// a tuple type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void PrintTupleTo(const T& t, ::std::ostream* os);
|
void PrintTupleTo(const T& t, ::std::ostream* os);
|
||||||
#endif // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE
|
|
||||||
// Overload for ::std::tr1::tuple. Needed for printing function arguments,
|
|
||||||
// which are packed as tuples.
|
|
||||||
|
|
||||||
// Overloaded PrintTo() for tuples of various arities. We support
|
// Overloaded PrintTo() for tuples of various arities. We support
|
||||||
// tuples of up-to 10 fields. The following implementation works
|
// tuples of up-to 10 fields. The following implementation works
|
||||||
@@ -567,13 +561,6 @@ void PrintTo(
|
|||||||
}
|
}
|
||||||
#endif // GTEST_HAS_TR1_TUPLE
|
#endif // GTEST_HAS_TR1_TUPLE
|
||||||
|
|
||||||
#if GTEST_HAS_STD_TUPLE_
|
|
||||||
template <typename... Types>
|
|
||||||
void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
|
|
||||||
PrintTupleTo(t, os);
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_STD_TUPLE_
|
|
||||||
|
|
||||||
// Overload for std::pair.
|
// Overload for std::pair.
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
|
void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
|
||||||
@@ -593,7 +580,10 @@ class UniversalPrinter {
|
|||||||
public:
|
public:
|
||||||
// MSVC warns about adding const to a function type, so we want to
|
// MSVC warns about adding const to a function type, so we want to
|
||||||
// disable the warning.
|
// disable the warning.
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4180) // Temporarily disables warning 4180.
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// Note: we deliberately don't call this PrintTo(), as that name
|
// Note: we deliberately don't call this PrintTo(), as that name
|
||||||
// conflicts with ::testing::internal::PrintTo in the body of the
|
// conflicts with ::testing::internal::PrintTo in the body of the
|
||||||
@@ -610,7 +600,9 @@ class UniversalPrinter {
|
|||||||
PrintTo(value, os);
|
PrintTo(value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif // _MSC_VER
|
||||||
};
|
};
|
||||||
|
|
||||||
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
||||||
@@ -662,7 +654,10 @@ class UniversalPrinter<T&> {
|
|||||||
public:
|
public:
|
||||||
// MSVC warns about adding const to a function type, so we want to
|
// MSVC warns about adding const to a function type, so we want to
|
||||||
// disable the warning.
|
// disable the warning.
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4180) // Temporarily disables warning 4180.
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
static void Print(const T& value, ::std::ostream* os) {
|
static void Print(const T& value, ::std::ostream* os) {
|
||||||
// Prints the address of the value. We use reinterpret_cast here
|
// Prints the address of the value. We use reinterpret_cast here
|
||||||
@@ -673,7 +668,9 @@ class UniversalPrinter<T&> {
|
|||||||
UniversalPrint(value, os);
|
UniversalPrint(value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif // _MSC_VER
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prints a value tersely: for a reference type, the referenced value
|
// Prints a value tersely: for a reference type, the referenced value
|
||||||
@@ -759,65 +756,16 @@ void UniversalPrint(const T& value, ::std::ostream* os) {
|
|||||||
UniversalPrinter<T1>::Print(value, os);
|
UniversalPrinter<T1>::Print(value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GTEST_HAS_TR1_TUPLE
|
||||||
typedef ::std::vector<string> Strings;
|
typedef ::std::vector<string> Strings;
|
||||||
|
|
||||||
// TuplePolicy<TupleT> must provide:
|
|
||||||
// - tuple_size
|
|
||||||
// size of tuple TupleT.
|
|
||||||
// - get<size_t I>(const TupleT& t)
|
|
||||||
// static function extracting element I of tuple TupleT.
|
|
||||||
// - tuple_element<size_t I>::type
|
|
||||||
// type of element I of tuple TupleT.
|
|
||||||
template <typename TupleT>
|
|
||||||
struct TuplePolicy;
|
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE
|
|
||||||
template <typename TupleT>
|
|
||||||
struct TuplePolicy {
|
|
||||||
typedef TupleT Tuple;
|
|
||||||
static const size_t tuple_size = ::std::tr1::tuple_size<Tuple>::value;
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
struct tuple_element : ::std::tr1::tuple_element<I, Tuple> {};
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
static typename AddReference<
|
|
||||||
const typename ::std::tr1::tuple_element<I, Tuple>::type>::type get(
|
|
||||||
const Tuple& tuple) {
|
|
||||||
return ::std::tr1::get<I>(tuple);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename TupleT>
|
|
||||||
const size_t TuplePolicy<TupleT>::tuple_size;
|
|
||||||
#endif // GTEST_HAS_TR1_TUPLE
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_TUPLE_
|
|
||||||
template <typename... Types>
|
|
||||||
struct TuplePolicy< ::std::tuple<Types...> > {
|
|
||||||
typedef ::std::tuple<Types...> Tuple;
|
|
||||||
static const size_t tuple_size = ::std::tuple_size<Tuple>::value;
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
struct tuple_element : ::std::tuple_element<I, Tuple> {};
|
|
||||||
|
|
||||||
template <size_t I>
|
|
||||||
static const typename ::std::tuple_element<I, Tuple>::type& get(
|
|
||||||
const Tuple& tuple) {
|
|
||||||
return ::std::get<I>(tuple);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <typename... Types>
|
|
||||||
const size_t TuplePolicy< ::std::tuple<Types...> >::tuple_size;
|
|
||||||
#endif // GTEST_HAS_STD_TUPLE_
|
|
||||||
|
|
||||||
#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
|
||||||
// This helper template allows PrintTo() for tuples and
|
// This helper template allows PrintTo() for tuples and
|
||||||
// UniversalTersePrintTupleFieldsToStrings() to be defined by
|
// UniversalTersePrintTupleFieldsToStrings() to be defined by
|
||||||
// induction on the number of tuple fields. The idea is that
|
// induction on the number of tuple fields. The idea is that
|
||||||
// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
|
// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
|
||||||
// fields in tuple t, and can be defined in terms of
|
// fields in tuple t, and can be defined in terms of
|
||||||
// TuplePrefixPrinter<N - 1>.
|
// TuplePrefixPrinter<N - 1>.
|
||||||
//
|
|
||||||
// The inductive case.
|
// The inductive case.
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
struct TuplePrefixPrinter {
|
struct TuplePrefixPrinter {
|
||||||
@@ -825,14 +773,9 @@ struct TuplePrefixPrinter {
|
|||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
|
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
|
||||||
TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
|
TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
|
||||||
GTEST_INTENTIONAL_CONST_COND_PUSH_()
|
*os << ", ";
|
||||||
if (N > 1) {
|
UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
|
||||||
GTEST_INTENTIONAL_CONST_COND_POP_()
|
::Print(::std::tr1::get<N - 1>(t), os);
|
||||||
*os << ", ";
|
|
||||||
}
|
|
||||||
UniversalPrinter<
|
|
||||||
typename TuplePolicy<Tuple>::template tuple_element<N - 1>::type>
|
|
||||||
::Print(TuplePolicy<Tuple>::template get<N - 1>(t), os);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tersely prints the first N fields of a tuple to a string vector,
|
// Tersely prints the first N fields of a tuple to a string vector,
|
||||||
@@ -841,12 +784,12 @@ struct TuplePrefixPrinter {
|
|||||||
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
|
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
|
||||||
TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
|
TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
|
||||||
::std::stringstream ss;
|
::std::stringstream ss;
|
||||||
UniversalTersePrint(TuplePolicy<Tuple>::template get<N - 1>(t), &ss);
|
UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
|
||||||
strings->push_back(ss.str());
|
strings->push_back(ss.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base case.
|
// Base cases.
|
||||||
template <>
|
template <>
|
||||||
struct TuplePrefixPrinter<0> {
|
struct TuplePrefixPrinter<0> {
|
||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
@@ -855,13 +798,34 @@ struct TuplePrefixPrinter<0> {
|
|||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
|
static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
|
||||||
};
|
};
|
||||||
|
// We have to specialize the entire TuplePrefixPrinter<> class
|
||||||
|
// template here, even though the definition of
|
||||||
|
// TersePrintPrefixToStrings() is the same as the generic version, as
|
||||||
|
// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
|
||||||
|
// support specializing a method template of a class template.
|
||||||
|
template <>
|
||||||
|
struct TuplePrefixPrinter<1> {
|
||||||
|
template <typename Tuple>
|
||||||
|
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
|
||||||
|
UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
|
||||||
|
Print(::std::tr1::get<0>(t), os);
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function for printing a tuple.
|
template <typename Tuple>
|
||||||
// Tuple must be either std::tr1::tuple or std::tuple type.
|
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
|
||||||
template <typename Tuple>
|
::std::stringstream ss;
|
||||||
void PrintTupleTo(const Tuple& t, ::std::ostream* os) {
|
UniversalTersePrint(::std::tr1::get<0>(t), &ss);
|
||||||
|
strings->push_back(ss.str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function for printing a tuple. T must be instantiated with
|
||||||
|
// a tuple type.
|
||||||
|
template <typename T>
|
||||||
|
void PrintTupleTo(const T& t, ::std::ostream* os) {
|
||||||
*os << "(";
|
*os << "(";
|
||||||
TuplePrefixPrinter<TuplePolicy<Tuple>::tuple_size>::PrintPrefixTo(t, os);
|
TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
|
||||||
|
PrintPrefixTo(t, os);
|
||||||
*os << ")";
|
*os << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,11 +835,11 @@ void PrintTupleTo(const Tuple& t, ::std::ostream* os) {
|
|||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
||||||
Strings result;
|
Strings result;
|
||||||
TuplePrefixPrinter<TuplePolicy<Tuple>::tuple_size>::
|
TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
|
||||||
TersePrintPrefixToStrings(value, &result);
|
TersePrintPrefixToStrings(value, &result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_
|
#endif // GTEST_HAS_TR1_TUPLE
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
@@ -258,31 +258,8 @@ class GTEST_API_ AssertionResult {
|
|||||||
// Copy constructor.
|
// Copy constructor.
|
||||||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||||
AssertionResult(const AssertionResult& other);
|
AssertionResult(const AssertionResult& other);
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
|
|
||||||
|
|
||||||
// Used in the EXPECT_TRUE/FALSE(bool_expression).
|
// Used in the EXPECT_TRUE/FALSE(bool_expression).
|
||||||
//
|
explicit AssertionResult(bool success) : success_(success) {}
|
||||||
// T must be contextually convertible to bool.
|
|
||||||
//
|
|
||||||
// The second parameter prevents this overload from being considered if
|
|
||||||
// the argument is implicitly convertible to AssertionResult. In that case
|
|
||||||
// we want AssertionResult's copy constructor to be used.
|
|
||||||
template <typename T>
|
|
||||||
explicit AssertionResult(
|
|
||||||
const T& success,
|
|
||||||
typename internal::EnableIf<
|
|
||||||
!internal::ImplicitlyConvertible<T, AssertionResult>::value>::type*
|
|
||||||
/*enabler*/ = NULL)
|
|
||||||
: success_(success) {}
|
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
|
||||||
|
|
||||||
// Assignment operator.
|
|
||||||
AssertionResult& operator=(AssertionResult other) {
|
|
||||||
swap(other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true iff the assertion succeeded.
|
// Returns true iff the assertion succeeded.
|
||||||
operator bool() const { return success_; } // NOLINT
|
operator bool() const { return success_; } // NOLINT
|
||||||
@@ -323,9 +300,6 @@ class GTEST_API_ AssertionResult {
|
|||||||
message_->append(a_message.GetString().c_str());
|
message_->append(a_message.GetString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap the contents of this AssertionResult with other.
|
|
||||||
void swap(AssertionResult& other);
|
|
||||||
|
|
||||||
// Stores result of the assertion predicate.
|
// Stores result of the assertion predicate.
|
||||||
bool success_;
|
bool success_;
|
||||||
// Stores the message describing the condition in case the expectation
|
// Stores the message describing the condition in case the expectation
|
||||||
@@ -333,6 +307,8 @@ class GTEST_API_ AssertionResult {
|
|||||||
// Referenced via a pointer to avoid taking too much stack frame space
|
// Referenced via a pointer to avoid taking too much stack frame space
|
||||||
// with test assertions.
|
// with test assertions.
|
||||||
internal::scoped_ptr< ::std::string> message_;
|
internal::scoped_ptr< ::std::string> message_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_ASSIGN_(AssertionResult);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Makes a successful assertion result.
|
// Makes a successful assertion result.
|
||||||
@@ -1463,11 +1439,19 @@ AssertionResult CmpHelperEQ(const char* expected_expression,
|
|||||||
const char* actual_expression,
|
const char* actual_expression,
|
||||||
const T1& expected,
|
const T1& expected,
|
||||||
const T2& actual) {
|
const T2& actual) {
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4389 /* signed/unsigned mismatch */)
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4389) // Temporarily disables warning on
|
||||||
|
// signed/unsigned mismatch.
|
||||||
|
#endif
|
||||||
|
|
||||||
if (expected == actual) {
|
if (expected == actual) {
|
||||||
return AssertionSuccess();
|
return AssertionSuccess();
|
||||||
}
|
}
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif
|
||||||
|
|
||||||
return EqFailure(expected_expression,
|
return EqFailure(expected_expression,
|
||||||
actual_expression,
|
actual_expression,
|
||||||
@@ -784,7 +784,7 @@ class ImplicitlyConvertible {
|
|||||||
// MakeFrom() is an expression whose type is From. We cannot simply
|
// MakeFrom() is an expression whose type is From. We cannot simply
|
||||||
// use From(), as the type From may not have a public default
|
// use From(), as the type From may not have a public default
|
||||||
// constructor.
|
// constructor.
|
||||||
static typename AddReference<From>::type MakeFrom();
|
static From MakeFrom();
|
||||||
|
|
||||||
// These two functions are overloaded. Given an expression
|
// These two functions are overloaded. Given an expression
|
||||||
// Helper(x), the compiler will pick the first version if x can be
|
// Helper(x), the compiler will pick the first version if x can be
|
||||||
@@ -802,20 +802,25 @@ class ImplicitlyConvertible {
|
|||||||
// We have to put the 'public' section after the 'private' section,
|
// We have to put the 'public' section after the 'private' section,
|
||||||
// or MSVC refuses to compile the code.
|
// or MSVC refuses to compile the code.
|
||||||
public:
|
public:
|
||||||
#if defined(__BORLANDC__)
|
// MSVC warns about implicitly converting from double to int for
|
||||||
|
// possible loss of data, so we need to temporarily disable the
|
||||||
|
// warning.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4244) // Temporarily disables warning 4244.
|
||||||
|
|
||||||
|
static const bool value =
|
||||||
|
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
|
||||||
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
// C++Builder cannot use member overload resolution during template
|
// C++Builder cannot use member overload resolution during template
|
||||||
// instantiation. The simplest workaround is to use its C++0x type traits
|
// instantiation. The simplest workaround is to use its C++0x type traits
|
||||||
// functions (C++Builder 2009 and above only).
|
// functions (C++Builder 2009 and above only).
|
||||||
static const bool value = __is_convertible(From, To);
|
static const bool value = __is_convertible(From, To);
|
||||||
#else
|
#else
|
||||||
// MSVC warns about implicitly converting from double to int for
|
|
||||||
// possible loss of data, so we need to temporarily disable the
|
|
||||||
// warning.
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244)
|
|
||||||
static const bool value =
|
static const bool value =
|
||||||
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
|
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
#endif // _MSV_VER
|
||||||
#endif // __BORLANDC__
|
|
||||||
};
|
};
|
||||||
template <typename From, typename To>
|
template <typename From, typename To>
|
||||||
const bool ImplicitlyConvertible<From, To>::value;
|
const bool ImplicitlyConvertible<From, To>::value;
|
||||||
@@ -941,10 +946,11 @@ void CopyArray(const T* from, size_t size, U* to) {
|
|||||||
|
|
||||||
// The relation between an NativeArray object (see below) and the
|
// The relation between an NativeArray object (see below) and the
|
||||||
// native array it represents.
|
// native array it represents.
|
||||||
// We use 2 different structs to allow non-copyable types to be used, as long
|
enum RelationToSource {
|
||||||
// as RelationToSourceReference() is passed.
|
kReference, // The NativeArray references the native array.
|
||||||
struct RelationToSourceReference {};
|
kCopy // The NativeArray makes a copy of the native array and
|
||||||
struct RelationToSourceCopy {};
|
// owns the copy.
|
||||||
|
};
|
||||||
|
|
||||||
// Adapts a native array to a read-only STL-style container. Instead
|
// Adapts a native array to a read-only STL-style container. Instead
|
||||||
// of the complete STL container concept, this adaptor only implements
|
// of the complete STL container concept, this adaptor only implements
|
||||||
@@ -962,23 +968,22 @@ class NativeArray {
|
|||||||
typedef Element* iterator;
|
typedef Element* iterator;
|
||||||
typedef const Element* const_iterator;
|
typedef const Element* const_iterator;
|
||||||
|
|
||||||
// Constructs from a native array. References the source.
|
// Constructs from a native array.
|
||||||
NativeArray(const Element* array, size_t count, RelationToSourceReference) {
|
NativeArray(const Element* array, size_t count, RelationToSource relation) {
|
||||||
InitRef(array, count);
|
Init(array, count, relation);
|
||||||
}
|
|
||||||
|
|
||||||
// Constructs from a native array. Copies the source.
|
|
||||||
NativeArray(const Element* array, size_t count, RelationToSourceCopy) {
|
|
||||||
InitCopy(array, count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy constructor.
|
// Copy constructor.
|
||||||
NativeArray(const NativeArray& rhs) {
|
NativeArray(const NativeArray& rhs) {
|
||||||
(this->*rhs.clone_)(rhs.array_, rhs.size_);
|
Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
|
||||||
}
|
}
|
||||||
|
|
||||||
~NativeArray() {
|
~NativeArray() {
|
||||||
if (clone_ != &NativeArray::InitRef)
|
// Ensures that the user doesn't instantiate NativeArray with a
|
||||||
|
// const or reference type.
|
||||||
|
static_cast<void>(StaticAssertTypeEqHelper<Element,
|
||||||
|
GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
|
||||||
|
if (relation_to_source_ == kCopy)
|
||||||
delete[] array_;
|
delete[] array_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -992,30 +997,23 @@ class NativeArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
// Initializes this object; makes a copy of the input array if
|
||||||
kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper<
|
// 'relation' is kCopy.
|
||||||
Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value,
|
void Init(const Element* array, size_t a_size, RelationToSource relation) {
|
||||||
};
|
if (relation == kReference) {
|
||||||
|
array_ = array;
|
||||||
// Initializes this object with a copy of the input.
|
} else {
|
||||||
void InitCopy(const Element* array, size_t a_size) {
|
Element* const copy = new Element[a_size];
|
||||||
Element* const copy = new Element[a_size];
|
CopyArray(array, a_size, copy);
|
||||||
CopyArray(array, a_size, copy);
|
array_ = copy;
|
||||||
array_ = copy;
|
}
|
||||||
size_ = a_size;
|
size_ = a_size;
|
||||||
clone_ = &NativeArray::InitCopy;
|
relation_to_source_ = relation;
|
||||||
}
|
|
||||||
|
|
||||||
// Initializes this object with a reference of the input.
|
|
||||||
void InitRef(const Element* array, size_t a_size) {
|
|
||||||
array_ = array;
|
|
||||||
size_ = a_size;
|
|
||||||
clone_ = &NativeArray::InitRef;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Element* array_;
|
const Element* array_;
|
||||||
size_t size_;
|
size_t size_;
|
||||||
void (NativeArray::*clone_)(const Element*, size_t);
|
RelationToSource relation_to_source_;
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(NativeArray);
|
GTEST_DISALLOW_ASSIGN_(NativeArray);
|
||||||
};
|
};
|
||||||
@@ -1158,4 +1156,3 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
|
|||||||
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
// and at most 10 arguments in Combine. Please contact
|
// and at most 10 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 10.
|
// currently set at 10.
|
||||||
|
|
||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
|
||||||
@@ -3157,9 +3157,9 @@ class ValueArray50 {
|
|||||||
//
|
//
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
class CartesianProductGenerator2
|
class CartesianProductGenerator2
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2> > {
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2> ParamType;
|
typedef ::std::tr1::tuple<T1, T2> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator2(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator2(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2)
|
const ParamGenerator<T2>& g2)
|
||||||
@@ -3272,9 +3272,9 @@ class CartesianProductGenerator2
|
|||||||
|
|
||||||
template <typename T1, typename T2, typename T3>
|
template <typename T1, typename T2, typename T3>
|
||||||
class CartesianProductGenerator3
|
class CartesianProductGenerator3
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3> > {
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator3(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator3(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
|
||||||
@@ -3404,9 +3404,9 @@ class CartesianProductGenerator3
|
|||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4>
|
template <typename T1, typename T2, typename T3, typename T4>
|
||||||
class CartesianProductGenerator4
|
class CartesianProductGenerator4
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4> > {
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3, T4> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator4(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator4(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
||||||
@@ -3555,9 +3555,9 @@ class CartesianProductGenerator4
|
|||||||
|
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||||
class CartesianProductGenerator5
|
class CartesianProductGenerator5
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5> > {
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3, T4, T5> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator5(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator5(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
||||||
@@ -3723,10 +3723,10 @@ class CartesianProductGenerator5
|
|||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6>
|
typename T6>
|
||||||
class CartesianProductGenerator6
|
class CartesianProductGenerator6
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5,
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
|
||||||
T6> > {
|
T6> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3, T4, T5, T6> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator6(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator6(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
||||||
@@ -3909,10 +3909,10 @@ class CartesianProductGenerator6
|
|||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7>
|
typename T6, typename T7>
|
||||||
class CartesianProductGenerator7
|
class CartesianProductGenerator7
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
|
||||||
T7> > {
|
T7> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator7(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator7(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
||||||
@@ -4112,10 +4112,10 @@ class CartesianProductGenerator7
|
|||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7, typename T8>
|
typename T6, typename T7, typename T8>
|
||||||
class CartesianProductGenerator8
|
class CartesianProductGenerator8
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
|
||||||
T7, T8> > {
|
T7, T8> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator8(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator8(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
||||||
@@ -4334,10 +4334,10 @@ class CartesianProductGenerator8
|
|||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7, typename T8, typename T9>
|
typename T6, typename T7, typename T8, typename T9>
|
||||||
class CartesianProductGenerator9
|
class CartesianProductGenerator9
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
|
||||||
T7, T8, T9> > {
|
T7, T8, T9> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator9(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator9(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
||||||
@@ -4573,10 +4573,10 @@ class CartesianProductGenerator9
|
|||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7, typename T8, typename T9, typename T10>
|
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||||
class CartesianProductGenerator10
|
class CartesianProductGenerator10
|
||||||
: public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
|
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
|
||||||
T7, T8, T9, T10> > {
|
T7, T8, T9, T10> > {
|
||||||
public:
|
public:
|
||||||
typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
|
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
|
||||||
|
|
||||||
CartesianProductGenerator10(const ParamGenerator<T1>& g1,
|
CartesianProductGenerator10(const ParamGenerator<T1>& g1,
|
||||||
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
|
||||||
@@ -4838,8 +4838,8 @@ class CartesianProductHolder2 {
|
|||||||
CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
|
CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
|
||||||
: g1_(g1), g2_(g2) {}
|
: g1_(g1), g2_(g2) {}
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2> >() const {
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2> >(
|
return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
|
||||||
new CartesianProductGenerator2<T1, T2>(
|
new CartesianProductGenerator2<T1, T2>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
static_cast<ParamGenerator<T2> >(g2_)));
|
static_cast<ParamGenerator<T2> >(g2_)));
|
||||||
@@ -4860,8 +4860,8 @@ CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
|
|||||||
const Generator3& g3)
|
const Generator3& g3)
|
||||||
: g1_(g1), g2_(g2), g3_(g3) {}
|
: g1_(g1), g2_(g2), g3_(g3) {}
|
||||||
template <typename T1, typename T2, typename T3>
|
template <typename T1, typename T2, typename T3>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3> >() const {
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3> >(
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
|
||||||
new CartesianProductGenerator3<T1, T2, T3>(
|
new CartesianProductGenerator3<T1, T2, T3>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
static_cast<ParamGenerator<T2> >(g2_),
|
static_cast<ParamGenerator<T2> >(g2_),
|
||||||
@@ -4885,8 +4885,8 @@ CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
|
|||||||
const Generator3& g3, const Generator4& g4)
|
const Generator3& g3, const Generator4& g4)
|
||||||
: g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
|
: g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
|
||||||
template <typename T1, typename T2, typename T3, typename T4>
|
template <typename T1, typename T2, typename T3, typename T4>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4> >() const {
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3, T4> >(
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
|
||||||
new CartesianProductGenerator4<T1, T2, T3, T4>(
|
new CartesianProductGenerator4<T1, T2, T3, T4>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
static_cast<ParamGenerator<T2> >(g2_),
|
static_cast<ParamGenerator<T2> >(g2_),
|
||||||
@@ -4912,8 +4912,8 @@ CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
|
|||||||
const Generator3& g3, const Generator4& g4, const Generator5& g5)
|
const Generator3& g3, const Generator4& g4, const Generator5& g5)
|
||||||
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
|
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5> >() const {
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5> >(
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
|
||||||
new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
|
new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
static_cast<ParamGenerator<T2> >(g2_),
|
static_cast<ParamGenerator<T2> >(g2_),
|
||||||
@@ -4943,8 +4943,8 @@ CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
|
|||||||
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
|
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6>
|
typename T6>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6> >() const {
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6> >(
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
|
||||||
new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
|
new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
static_cast<ParamGenerator<T2> >(g2_),
|
static_cast<ParamGenerator<T2> >(g2_),
|
||||||
@@ -4976,9 +4976,9 @@ CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
|
|||||||
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
|
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7>
|
typename T6, typename T7>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6,
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
|
||||||
T7> >() const {
|
T7> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7> >(
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
|
||||||
new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
|
new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
static_cast<ParamGenerator<T2> >(g2_),
|
static_cast<ParamGenerator<T2> >(g2_),
|
||||||
@@ -5014,9 +5014,9 @@ CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
|
|||||||
g8_(g8) {}
|
g8_(g8) {}
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7, typename T8>
|
typename T6, typename T7, typename T8>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7,
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
|
||||||
T8> >() const {
|
T8> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
|
||||||
new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
|
new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
static_cast<ParamGenerator<T2> >(g2_),
|
static_cast<ParamGenerator<T2> >(g2_),
|
||||||
@@ -5055,9 +5055,9 @@ CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
|
|||||||
g9_(g9) {}
|
g9_(g9) {}
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7, typename T8, typename T9>
|
typename T6, typename T7, typename T8, typename T9>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
|
||||||
T9> >() const {
|
T9> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
|
||||||
T9> >(
|
T9> >(
|
||||||
new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
|
new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
@@ -5099,10 +5099,10 @@ CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
|
|||||||
g9_(g9), g10_(g10) {}
|
g9_(g9), g10_(g10) {}
|
||||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||||
typename T6, typename T7, typename T8, typename T9, typename T10>
|
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||||
operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9,
|
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
|
||||||
T10> >() const {
|
T9, T10> >() const {
|
||||||
return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9,
|
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
|
||||||
T10> >(
|
T9, T10> >(
|
||||||
new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
|
new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
|
||||||
T10>(
|
T10>(
|
||||||
static_cast<ParamGenerator<T1> >(g1_),
|
static_cast<ParamGenerator<T1> >(g1_),
|
||||||
@@ -39,7 +39,7 @@ $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
|
|||||||
// 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_
|
||||||
@@ -128,9 +128,9 @@ $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)]] {}
|
||||||
@@ -269,8 +269,8 @@ class CartesianProductHolder$i {
|
|||||||
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,[[
|
||||||
|
|
||||||
@@ -30,11 +30,8 @@
|
|||||||
// Authors: wan@google.com (Zhanyong Wan)
|
// Authors: wan@google.com (Zhanyong Wan)
|
||||||
//
|
//
|
||||||
// Low-level types and utilities for porting Google Test to various
|
// Low-level types and utilities for porting Google Test to various
|
||||||
// platforms. All macros ending with _ and symbols defined in an
|
// platforms. They are subject to change without notice. DO NOT USE
|
||||||
// internal namespace are subject to change without notice. Code
|
// THEM IN USER CODE.
|
||||||
// outside Google Test MUST NOT USE THEM DIRECTLY. Macros that don't
|
|
||||||
// end with _ are part of Google Test's public API and can be used by
|
|
||||||
// code outside Google Test.
|
|
||||||
//
|
//
|
||||||
// This file is fundamental to Google Test. All other Google Test source
|
// This file is fundamental to Google Test. All other Google Test source
|
||||||
// files are expected to #include this. Therefore, it cannot #include
|
// files are expected to #include this. Therefore, it cannot #include
|
||||||
@@ -43,30 +40,9 @@
|
|||||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
||||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
||||||
|
|
||||||
// Environment-describing macros
|
// The user can define the following macros in the build script to
|
||||||
// -----------------------------
|
// control Google Test's behavior. If the user doesn't define a macro
|
||||||
//
|
// in this list, Google Test will define it.
|
||||||
// Google Test can be used in many different environments. Macros in
|
|
||||||
// this section tell Google Test what kind of environment it is being
|
|
||||||
// used in, such that Google Test can provide environment-specific
|
|
||||||
// features and implementations.
|
|
||||||
//
|
|
||||||
// Google Test tries to automatically detect the properties of its
|
|
||||||
// environment, so users usually don't need to worry about these
|
|
||||||
// macros. However, the automatic detection is not perfect.
|
|
||||||
// Sometimes it's necessary for a user to define some of the following
|
|
||||||
// macros in the build script to override Google Test's decisions.
|
|
||||||
//
|
|
||||||
// If the user doesn't define a macro in the list, Google Test will
|
|
||||||
// provide a default definition. After this header is #included, all
|
|
||||||
// macros in this list will be defined to either 1 or 0.
|
|
||||||
//
|
|
||||||
// Notes to maintainers:
|
|
||||||
// - Each macro here is a user-tweakable knob; do not grow the list
|
|
||||||
// lightly.
|
|
||||||
// - Use #if to key off these macros. Don't use #ifdef or "#if
|
|
||||||
// defined(...)", which will not work as these macros are ALWAYS
|
|
||||||
// defined.
|
|
||||||
//
|
//
|
||||||
// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2)
|
// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2)
|
||||||
// is/isn't available.
|
// is/isn't available.
|
||||||
@@ -110,15 +86,10 @@
|
|||||||
// - Define to 1 when compiling Google Test itself
|
// - Define to 1 when compiling Google Test itself
|
||||||
// as a shared library.
|
// as a shared library.
|
||||||
|
|
||||||
// Platform-indicating macros
|
// This header defines the following utilities:
|
||||||
// --------------------------
|
|
||||||
//
|
|
||||||
// Macros indicating the platform on which Google Test is being used
|
|
||||||
// (a macro is defined to 1 if compiled on the given platform;
|
|
||||||
// otherwise UNDEFINED -- it's never defined to 0.). Google Test
|
|
||||||
// defines these macros automatically. Code outside Google Test MUST
|
|
||||||
// NOT define them.
|
|
||||||
//
|
//
|
||||||
|
// Macros indicating the current platform (defined to 1 if compiled on
|
||||||
|
// the given platform; otherwise undefined):
|
||||||
// GTEST_OS_AIX - IBM AIX
|
// GTEST_OS_AIX - IBM AIX
|
||||||
// GTEST_OS_CYGWIN - Cygwin
|
// GTEST_OS_CYGWIN - Cygwin
|
||||||
// GTEST_OS_HPUX - HP-UX
|
// GTEST_OS_HPUX - HP-UX
|
||||||
@@ -136,8 +107,6 @@
|
|||||||
// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop
|
// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop
|
||||||
// GTEST_OS_WINDOWS_MINGW - MinGW
|
// GTEST_OS_WINDOWS_MINGW - MinGW
|
||||||
// GTEST_OS_WINDOWS_MOBILE - Windows Mobile
|
// GTEST_OS_WINDOWS_MOBILE - Windows Mobile
|
||||||
// GTEST_OS_WINDOWS_PHONE - Windows Phone
|
|
||||||
// GTEST_OS_WINDOWS_RT - Windows Store App/WinRT
|
|
||||||
// GTEST_OS_ZOS - z/OS
|
// GTEST_OS_ZOS - z/OS
|
||||||
//
|
//
|
||||||
// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
|
// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
|
||||||
@@ -147,50 +116,22 @@
|
|||||||
// googletestframework@googlegroups.com (patches for fixing them are
|
// googletestframework@googlegroups.com (patches for fixing them are
|
||||||
// even more welcome!).
|
// even more welcome!).
|
||||||
//
|
//
|
||||||
// It is possible that none of the GTEST_OS_* macros are defined.
|
// Note that it is possible that none of the GTEST_OS_* macros are defined.
|
||||||
|
|
||||||
// Feature-indicating macros
|
|
||||||
// -------------------------
|
|
||||||
//
|
|
||||||
// Macros indicating which Google Test features are available (a macro
|
|
||||||
// is defined to 1 if the corresponding feature is supported;
|
|
||||||
// otherwise UNDEFINED -- it's never defined to 0.). Google Test
|
|
||||||
// defines these macros automatically. Code outside Google Test MUST
|
|
||||||
// NOT define them.
|
|
||||||
//
|
|
||||||
// These macros are public so that portable tests can be written.
|
|
||||||
// Such tests typically surround code using a feature with an #if
|
|
||||||
// which controls that code. For example:
|
|
||||||
//
|
|
||||||
// #if GTEST_HAS_DEATH_TEST
|
|
||||||
// EXPECT_DEATH(DoSomethingDeadly());
|
|
||||||
// #endif
|
|
||||||
//
|
//
|
||||||
|
// Macros indicating available Google Test features (defined to 1 if
|
||||||
|
// the corresponding feature is supported; otherwise undefined):
|
||||||
// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized
|
// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized
|
||||||
// tests)
|
// tests)
|
||||||
// GTEST_HAS_DEATH_TEST - death tests
|
// GTEST_HAS_DEATH_TEST - death tests
|
||||||
// GTEST_HAS_PARAM_TEST - value-parameterized tests
|
// GTEST_HAS_PARAM_TEST - value-parameterized tests
|
||||||
// GTEST_HAS_TYPED_TEST - typed tests
|
// GTEST_HAS_TYPED_TEST - typed tests
|
||||||
// GTEST_HAS_TYPED_TEST_P - type-parameterized tests
|
// GTEST_HAS_TYPED_TEST_P - type-parameterized tests
|
||||||
// GTEST_IS_THREADSAFE - Google Test is thread-safe.
|
|
||||||
// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
|
// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
|
||||||
// GTEST_HAS_POSIX_RE (see above) which users can
|
// GTEST_HAS_POSIX_RE (see above) which users can
|
||||||
// define themselves.
|
// define themselves.
|
||||||
// GTEST_USES_SIMPLE_RE - our own simple regex is used;
|
// GTEST_USES_SIMPLE_RE - our own simple regex is used;
|
||||||
// the above two are mutually exclusive.
|
// the above two are mutually exclusive.
|
||||||
// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
|
// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
|
||||||
|
|
||||||
// Misc public macros
|
|
||||||
// ------------------
|
|
||||||
//
|
|
||||||
// GTEST_FLAG(flag_name) - references the variable corresponding to
|
|
||||||
// the given Google Test flag.
|
|
||||||
|
|
||||||
// Internal utilities
|
|
||||||
// ------------------
|
|
||||||
//
|
|
||||||
// The following macros and utilities are for Google Test's INTERNAL
|
|
||||||
// use only. Code outside Google Test MUST NOT USE THEM DIRECTLY.
|
|
||||||
//
|
//
|
||||||
// Macros for basic C++ coding:
|
// Macros for basic C++ coding:
|
||||||
// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
|
// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
|
||||||
@@ -199,18 +140,13 @@
|
|||||||
// GTEST_DISALLOW_ASSIGN_ - disables operator=.
|
// GTEST_DISALLOW_ASSIGN_ - disables operator=.
|
||||||
// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
|
// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
|
||||||
// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
|
// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
|
||||||
// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
|
|
||||||
// suppressed (constant conditional).
|
|
||||||
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
|
|
||||||
// is suppressed.
|
|
||||||
//
|
|
||||||
// C++11 feature wrappers:
|
|
||||||
//
|
|
||||||
// GTEST_MOVE_ - portability wrapper for std::move.
|
|
||||||
//
|
//
|
||||||
// Synchronization:
|
// Synchronization:
|
||||||
// Mutex, MutexLock, ThreadLocal, GetThreadCount()
|
// Mutex, MutexLock, ThreadLocal, GetThreadCount()
|
||||||
// - synchronization primitives.
|
// - synchronization primitives.
|
||||||
|
// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
|
||||||
|
// synchronization primitives have real implementations
|
||||||
|
// and Google Test is thread-safe; or 0 otherwise.
|
||||||
//
|
//
|
||||||
// Template meta programming:
|
// Template meta programming:
|
||||||
// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only.
|
// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only.
|
||||||
@@ -246,6 +182,7 @@
|
|||||||
// BiggestInt - the biggest signed integer type.
|
// BiggestInt - the biggest signed integer type.
|
||||||
//
|
//
|
||||||
// Command-line utilities:
|
// Command-line utilities:
|
||||||
|
// GTEST_FLAG() - references a flag.
|
||||||
// GTEST_DECLARE_*() - declares a flag.
|
// GTEST_DECLARE_*() - declares a flag.
|
||||||
// GTEST_DEFINE_*() - defines a flag.
|
// GTEST_DEFINE_*() - defines a flag.
|
||||||
// GetInjectableArgvs() - returns the command line as a vector of strings.
|
// GetInjectableArgvs() - returns the command line as a vector of strings.
|
||||||
@@ -271,11 +208,9 @@
|
|||||||
# include <TargetConditionals.h>
|
# include <TargetConditionals.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm> // NOLINT
|
|
||||||
#include <iostream> // NOLINT
|
#include <iostream> // NOLINT
|
||||||
#include <sstream> // NOLINT
|
#include <sstream> // NOLINT
|
||||||
#include <string> // NOLINT
|
#include <string> // NOLINT
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
|
#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
|
||||||
#define GTEST_FLAG_PREFIX_ "gtest_"
|
#define GTEST_FLAG_PREFIX_ "gtest_"
|
||||||
@@ -302,19 +237,6 @@
|
|||||||
# define GTEST_OS_WINDOWS_MOBILE 1
|
# define GTEST_OS_WINDOWS_MOBILE 1
|
||||||
# elif defined(__MINGW__) || defined(__MINGW32__)
|
# elif defined(__MINGW__) || defined(__MINGW32__)
|
||||||
# define GTEST_OS_WINDOWS_MINGW 1
|
# define GTEST_OS_WINDOWS_MINGW 1
|
||||||
# elif defined(WINAPI_FAMILY)
|
|
||||||
# include <winapifamily.h>
|
|
||||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
|
||||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
|
||||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
|
||||||
# define GTEST_OS_WINDOWS_PHONE 1
|
|
||||||
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
|
||||||
# define GTEST_OS_WINDOWS_RT 1
|
|
||||||
# else
|
|
||||||
// WINAPI_FAMILY defined but no known partition matched.
|
|
||||||
// Default to desktop.
|
|
||||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
|
||||||
# endif
|
|
||||||
# else
|
# else
|
||||||
# define GTEST_OS_WINDOWS_DESKTOP 1
|
# define GTEST_OS_WINDOWS_DESKTOP 1
|
||||||
# endif // _WIN32_WCE
|
# endif // _WIN32_WCE
|
||||||
@@ -347,23 +269,6 @@
|
|||||||
# define GTEST_OS_QNX 1
|
# define GTEST_OS_QNX 1
|
||||||
#endif // __CYGWIN__
|
#endif // __CYGWIN__
|
||||||
|
|
||||||
// Macros for disabling Microsoft Visual C++ warnings.
|
|
||||||
//
|
|
||||||
// GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 4385)
|
|
||||||
// /* code that triggers warnings C4800 and C4385 */
|
|
||||||
// GTEST_DISABLE_MSC_WARNINGS_POP_()
|
|
||||||
#if _MSC_VER >= 1500
|
|
||||||
# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) \
|
|
||||||
__pragma(warning(push)) \
|
|
||||||
__pragma(warning(disable: warnings))
|
|
||||||
# define GTEST_DISABLE_MSC_WARNINGS_POP_() \
|
|
||||||
__pragma(warning(pop))
|
|
||||||
#else
|
|
||||||
// Older versions of MSVC don't have __pragma.
|
|
||||||
# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings)
|
|
||||||
# define GTEST_DISABLE_MSC_WARNINGS_POP_()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GTEST_LANG_CXX11
|
#ifndef GTEST_LANG_CXX11
|
||||||
// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when
|
// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when
|
||||||
// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a
|
// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a
|
||||||
@@ -377,58 +282,19 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// C++11 specifies that <initializer_list> provides std::initializer_list. Use
|
|
||||||
// that if gtest is used in C++11 mode and libstdc++ isn't very old (binaries
|
|
||||||
// targeting OS X 10.6 can build with clang but need to use gcc4.2's
|
|
||||||
// libstdc++).
|
|
||||||
#if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325)
|
|
||||||
# define GTEST_HAS_STD_INITIALIZER_LIST_ 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// C++11 specifies that <tuple> provides std::tuple.
|
|
||||||
// Some platforms still might not have it, however.
|
|
||||||
#if GTEST_LANG_CXX11
|
|
||||||
# define GTEST_HAS_STD_TUPLE_ 1
|
|
||||||
# if defined(__clang__)
|
|
||||||
// Inspired by http://clang.llvm.org/docs/LanguageExtensions.html#__has_include
|
|
||||||
# if defined(__has_include) && !__has_include(<tuple>)
|
|
||||||
# undef GTEST_HAS_STD_TUPLE_
|
|
||||||
# endif
|
|
||||||
# elif defined(_MSC_VER)
|
|
||||||
// Inspired by boost/config/stdlib/dinkumware.hpp
|
|
||||||
# if defined(_CPPLIB_VER) && _CPPLIB_VER < 520
|
|
||||||
# undef GTEST_HAS_STD_TUPLE_
|
|
||||||
# endif
|
|
||||||
# elif defined(__GLIBCXX__)
|
|
||||||
// Inspired by boost/config/stdlib/libstdcpp3.hpp,
|
|
||||||
// http://gcc.gnu.org/gcc-4.2/changes.html and
|
|
||||||
// http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01.html#manual.intro.status.standard.200x
|
|
||||||
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
|
|
||||||
# undef GTEST_HAS_STD_TUPLE_
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Brings in definitions for functions used in the testing::internal::posix
|
// Brings in definitions for functions used in the testing::internal::posix
|
||||||
// namespace (read, write, close, chdir, isatty, stat). We do not currently
|
// namespace (read, write, close, chdir, isatty, stat). We do not currently
|
||||||
// use them on Windows Mobile.
|
// use them on Windows Mobile.
|
||||||
#if GTEST_OS_WINDOWS
|
#if !GTEST_OS_WINDOWS
|
||||||
# if !GTEST_OS_WINDOWS_MOBILE
|
|
||||||
# include <direct.h>
|
|
||||||
# include <io.h>
|
|
||||||
# endif
|
|
||||||
// In order to avoid having to include <windows.h>, use forward declaration
|
|
||||||
// assuming CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION.
|
|
||||||
// This assumption is verified by
|
|
||||||
// WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION.
|
|
||||||
struct _RTL_CRITICAL_SECTION;
|
|
||||||
#else
|
|
||||||
// This assumes that non-Windows OSes provide unistd.h. For OSes where this
|
// This assumes that non-Windows OSes provide unistd.h. For OSes where this
|
||||||
// is not the case, we need to include headers that provide the functions
|
// is not the case, we need to include headers that provide the functions
|
||||||
// mentioned above.
|
// mentioned above.
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <strings.h>
|
# include <strings.h>
|
||||||
#endif // GTEST_OS_WINDOWS
|
#elif !GTEST_OS_WINDOWS_MOBILE
|
||||||
|
# include <direct.h>
|
||||||
|
# include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GTEST_OS_LINUX_ANDROID
|
#if GTEST_OS_LINUX_ANDROID
|
||||||
// Used to define __ANDROID_API__ matching the target NDK API level.
|
// Used to define __ANDROID_API__ matching the target NDK API level.
|
||||||
@@ -673,21 +539,11 @@ struct _RTL_CRITICAL_SECTION;
|
|||||||
|
|
||||||
// To avoid conditional compilation everywhere, we make it
|
// To avoid conditional compilation everywhere, we make it
|
||||||
// gtest-port.h's responsibility to #include the header implementing
|
// gtest-port.h's responsibility to #include the header implementing
|
||||||
// tuple.
|
// tr1/tuple.
|
||||||
#if GTEST_HAS_STD_TUPLE_
|
|
||||||
# include <tuple> // IWYU pragma: export
|
|
||||||
# define GTEST_TUPLE_NAMESPACE_ ::std
|
|
||||||
#endif // GTEST_HAS_STD_TUPLE_
|
|
||||||
|
|
||||||
// We include tr1::tuple even if std::tuple is available to define printers for
|
|
||||||
// them.
|
|
||||||
#if GTEST_HAS_TR1_TUPLE
|
#if GTEST_HAS_TR1_TUPLE
|
||||||
# ifndef GTEST_TUPLE_NAMESPACE_
|
|
||||||
# define GTEST_TUPLE_NAMESPACE_ ::std::tr1
|
|
||||||
# endif // GTEST_TUPLE_NAMESPACE_
|
|
||||||
|
|
||||||
# if GTEST_USE_OWN_TR1_TUPLE
|
# if GTEST_USE_OWN_TR1_TUPLE
|
||||||
# include "gtest/internal/gtest-tuple.h" // IWYU pragma: export // NOLINT
|
# include "gtest/internal/gtest-tuple.h"
|
||||||
# elif GTEST_ENV_HAS_STD_TUPLE_
|
# elif GTEST_ENV_HAS_STD_TUPLE_
|
||||||
# include <tuple>
|
# include <tuple>
|
||||||
// C++11 puts its tuple into the ::std namespace rather than
|
// C++11 puts its tuple into the ::std namespace rather than
|
||||||
@@ -718,7 +574,7 @@ using ::std::tuple_size;
|
|||||||
// This prevents <boost/tr1/detail/config.hpp>, which defines
|
// This prevents <boost/tr1/detail/config.hpp>, which defines
|
||||||
// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
|
// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
|
||||||
# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
|
# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
|
||||||
# include <tuple> // IWYU pragma: export // NOLINT
|
# include <tuple>
|
||||||
|
|
||||||
# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
|
# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
|
||||||
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
|
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
|
||||||
@@ -741,7 +597,7 @@ using ::std::tuple_size;
|
|||||||
# else
|
# else
|
||||||
// If the compiler is not GCC 4.0+, we assume the user is using a
|
// If the compiler is not GCC 4.0+, we assume the user is using a
|
||||||
// spec-conforming TR1 implementation.
|
// spec-conforming TR1 implementation.
|
||||||
# include <tuple> // IWYU pragma: export // NOLINT
|
# include <tuple> // NOLINT
|
||||||
# endif // GTEST_USE_OWN_TR1_TUPLE
|
# endif // GTEST_USE_OWN_TR1_TUPLE
|
||||||
|
|
||||||
#endif // GTEST_HAS_TR1_TUPLE
|
#endif // GTEST_HAS_TR1_TUPLE
|
||||||
@@ -775,8 +631,7 @@ using ::std::tuple_size;
|
|||||||
#ifndef GTEST_HAS_STREAM_REDIRECTION
|
#ifndef GTEST_HAS_STREAM_REDIRECTION
|
||||||
// By default, we assume that stream redirection is supported on all
|
// By default, we assume that stream redirection is supported on all
|
||||||
// platforms except known mobile ones.
|
// platforms except known mobile ones.
|
||||||
# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || \
|
# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
|
||||||
GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
|
|
||||||
# define GTEST_HAS_STREAM_REDIRECTION 0
|
# define GTEST_HAS_STREAM_REDIRECTION 0
|
||||||
# else
|
# else
|
||||||
# define GTEST_HAS_STREAM_REDIRECTION 1
|
# define GTEST_HAS_STREAM_REDIRECTION 1
|
||||||
@@ -883,25 +738,6 @@ using ::std::tuple_size;
|
|||||||
# define GTEST_MUST_USE_RESULT_
|
# define GTEST_MUST_USE_RESULT_
|
||||||
#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
|
#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
|
||||||
|
|
||||||
#if GTEST_LANG_CXX11
|
|
||||||
# define GTEST_MOVE_(x) ::std::move(x) // NOLINT
|
|
||||||
#else
|
|
||||||
# define GTEST_MOVE_(x) x
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// MS C++ compiler emits warning when a conditional expression is compile time
|
|
||||||
// constant. In some contexts this warning is false positive and needs to be
|
|
||||||
// suppressed. Use the following two macros in such cases:
|
|
||||||
//
|
|
||||||
// GTEST_INTENTIONAL_CONST_COND_PUSH_()
|
|
||||||
// while (true) {
|
|
||||||
// GTEST_INTENTIONAL_CONST_COND_POP_()
|
|
||||||
// }
|
|
||||||
# define GTEST_INTENTIONAL_CONST_COND_PUSH_() \
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127)
|
|
||||||
# define GTEST_INTENTIONAL_CONST_COND_POP_() \
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
|
||||||
|
|
||||||
// Determine whether the compiler supports Microsoft's Structured Exception
|
// Determine whether the compiler supports Microsoft's Structured Exception
|
||||||
// Handling. This is supported by several Windows compilers but generally
|
// Handling. This is supported by several Windows compilers but generally
|
||||||
// does not exist on any other system.
|
// does not exist on any other system.
|
||||||
@@ -916,9 +752,6 @@ using ::std::tuple_size;
|
|||||||
# define GTEST_HAS_SEH 0
|
# define GTEST_HAS_SEH 0
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#define GTEST_IS_THREADSAFE \
|
|
||||||
(GTEST_OS_WINDOWS || GTEST_HAS_PTHREAD)
|
|
||||||
|
|
||||||
#endif // GTEST_HAS_SEH
|
#endif // GTEST_HAS_SEH
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -949,58 +782,10 @@ using ::std::tuple_size;
|
|||||||
# define GTEST_HAS_CXXABI_H_ 0
|
# define GTEST_HAS_CXXABI_H_ 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// A function level attribute to disable checking for use of uninitialized
|
|
||||||
// memory when built with MemorySanitizer.
|
|
||||||
#if defined(__clang__)
|
|
||||||
# if __has_feature(memory_sanitizer)
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ \
|
|
||||||
__attribute__((no_sanitize_memory))
|
|
||||||
# else
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
|
||||||
# endif // __has_feature(memory_sanitizer)
|
|
||||||
#else
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
|
||||||
#endif // __clang__
|
|
||||||
|
|
||||||
// A function level attribute to disable AddressSanitizer instrumentation.
|
|
||||||
#if defined(__clang__)
|
|
||||||
# if __has_feature(address_sanitizer)
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ \
|
|
||||||
__attribute__((no_sanitize_address))
|
|
||||||
# else
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
|
||||||
# endif // __has_feature(address_sanitizer)
|
|
||||||
#else
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
|
||||||
#endif // __clang__
|
|
||||||
|
|
||||||
// A function level attribute to disable ThreadSanitizer instrumentation.
|
|
||||||
#if defined(__clang__)
|
|
||||||
# if __has_feature(thread_sanitizer)
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ \
|
|
||||||
__attribute__((no_sanitize_thread))
|
|
||||||
# else
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
|
||||||
# endif // __has_feature(thread_sanitizer)
|
|
||||||
#else
|
|
||||||
# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
|
||||||
#endif // __clang__
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
class Message;
|
class Message;
|
||||||
|
|
||||||
#if defined(GTEST_TUPLE_NAMESPACE_)
|
|
||||||
// Import tuple and friends into the ::testing namespace.
|
|
||||||
// It is part of our interface, having them in ::testing allows us to change
|
|
||||||
// their types as needed.
|
|
||||||
using GTEST_TUPLE_NAMESPACE_::get;
|
|
||||||
using GTEST_TUPLE_NAMESPACE_::make_tuple;
|
|
||||||
using GTEST_TUPLE_NAMESPACE_::tuple;
|
|
||||||
using GTEST_TUPLE_NAMESPACE_::tuple_size;
|
|
||||||
using GTEST_TUPLE_NAMESPACE_::tuple_element;
|
|
||||||
#endif // defined(GTEST_TUPLE_NAMESPACE_)
|
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// A secret type that Google Test users don't know about. It has no
|
// A secret type that Google Test users don't know about. It has no
|
||||||
@@ -1012,8 +797,8 @@ class Secret;
|
|||||||
// expression is true. For example, you could use it to verify the
|
// expression is true. For example, you could use it to verify the
|
||||||
// size of a static array:
|
// size of a static array:
|
||||||
//
|
//
|
||||||
// GTEST_COMPILE_ASSERT_(GTEST_ARRAY_SIZE_(names) == NUM_NAMES,
|
// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
|
||||||
// names_incorrect_size);
|
// content_type_names_incorrect_size);
|
||||||
//
|
//
|
||||||
// or to make sure a struct is smaller than a certain size:
|
// or to make sure a struct is smaller than a certain size:
|
||||||
//
|
//
|
||||||
@@ -1079,12 +864,7 @@ template <typename T1, typename T2>
|
|||||||
struct StaticAssertTypeEqHelper;
|
struct StaticAssertTypeEqHelper;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct StaticAssertTypeEqHelper<T, T> {
|
struct StaticAssertTypeEqHelper<T, T> {};
|
||||||
enum { value = true };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Evaluates to the number of elements in 'array'.
|
|
||||||
#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0]))
|
|
||||||
|
|
||||||
#if GTEST_HAS_GLOBAL_STRING
|
#if GTEST_HAS_GLOBAL_STRING
|
||||||
typedef ::string string;
|
typedef ::string string;
|
||||||
@@ -1133,11 +913,6 @@ class scoped_ptr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
friend void swap(scoped_ptr& a, scoped_ptr& b) {
|
|
||||||
using std::swap;
|
|
||||||
swap(a.ptr_, b.ptr_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* ptr_;
|
T* ptr_;
|
||||||
|
|
||||||
@@ -1349,9 +1124,7 @@ inline To DownCast_(From* f) { // so we only accept pointers
|
|||||||
// for compile-time type checking, and has no overhead in an
|
// for compile-time type checking, and has no overhead in an
|
||||||
// optimized build at run-time, as it will be optimized away
|
// optimized build at run-time, as it will be optimized away
|
||||||
// completely.
|
// completely.
|
||||||
GTEST_INTENTIONAL_CONST_COND_PUSH_()
|
|
||||||
if (false) {
|
if (false) {
|
||||||
GTEST_INTENTIONAL_CONST_COND_POP_()
|
|
||||||
const To to = NULL;
|
const To to = NULL;
|
||||||
::testing::internal::ImplicitCast_<From*>(to);
|
::testing::internal::ImplicitCast_<From*>(to);
|
||||||
}
|
}
|
||||||
@@ -1406,11 +1179,12 @@ extern ::std::vector<testing::internal::string> g_argvs;
|
|||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
// Defines synchronization primitives.
|
// Defines synchronization primitives.
|
||||||
#if GTEST_IS_THREADSAFE
|
|
||||||
# if GTEST_HAS_PTHREAD
|
#if GTEST_HAS_PTHREAD
|
||||||
// Sleeps for (roughly) n milliseconds. This function is only for testing
|
|
||||||
// Google Test's own constructs. Don't use it in user tests, either
|
// Sleeps for (roughly) n milli-seconds. This function is only for
|
||||||
// directly or indirectly.
|
// testing Google Test's own constructs. Don't use it in user tests,
|
||||||
|
// either directly or indirectly.
|
||||||
inline void SleepMilliseconds(int n) {
|
inline void SleepMilliseconds(int n) {
|
||||||
const timespec time = {
|
const timespec time = {
|
||||||
0, // 0 seconds.
|
0, // 0 seconds.
|
||||||
@@ -1418,10 +1192,7 @@ inline void SleepMilliseconds(int n) {
|
|||||||
};
|
};
|
||||||
nanosleep(&time, NULL);
|
nanosleep(&time, NULL);
|
||||||
}
|
}
|
||||||
# endif // GTEST_HAS_PTHREAD
|
|
||||||
|
|
||||||
# if 0 // OS detection
|
|
||||||
# elif GTEST_HAS_PTHREAD
|
|
||||||
// Allows a controller thread to pause execution of newly created
|
// Allows a controller thread to pause execution of newly created
|
||||||
// threads until notified. Instances of this class must be created
|
// threads until notified. Instances of this class must be created
|
||||||
// and destroyed in the controller thread.
|
// and destroyed in the controller thread.
|
||||||
@@ -1465,62 +1236,6 @@ class Notification {
|
|||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
|
||||||
};
|
};
|
||||||
|
|
||||||
# elif GTEST_OS_WINDOWS
|
|
||||||
|
|
||||||
GTEST_API_ void SleepMilliseconds(int n);
|
|
||||||
|
|
||||||
// Provides leak-safe Windows kernel handle ownership.
|
|
||||||
// Used in death tests and in threading support.
|
|
||||||
class GTEST_API_ AutoHandle {
|
|
||||||
public:
|
|
||||||
// Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
|
|
||||||
// avoid including <windows.h> in this header file. Including <windows.h> is
|
|
||||||
// undesirable because it defines a lot of symbols and macros that tend to
|
|
||||||
// conflict with client code. This assumption is verified by
|
|
||||||
// WindowsTypesTest.HANDLEIsVoidStar.
|
|
||||||
typedef void* Handle;
|
|
||||||
AutoHandle();
|
|
||||||
explicit AutoHandle(Handle handle);
|
|
||||||
|
|
||||||
~AutoHandle();
|
|
||||||
|
|
||||||
Handle Get() const;
|
|
||||||
void Reset();
|
|
||||||
void Reset(Handle handle);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Returns true iff the handle is a valid handle object that can be closed.
|
|
||||||
bool IsCloseable() const;
|
|
||||||
|
|
||||||
Handle handle_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Allows a controller thread to pause execution of newly created
|
|
||||||
// threads until notified. Instances of this class must be created
|
|
||||||
// and destroyed in the controller thread.
|
|
||||||
//
|
|
||||||
// This class is only for testing Google Test's own constructs. Do not
|
|
||||||
// use it in user tests, either directly or indirectly.
|
|
||||||
class GTEST_API_ Notification {
|
|
||||||
public:
|
|
||||||
Notification();
|
|
||||||
void Notify();
|
|
||||||
void WaitForNotification();
|
|
||||||
|
|
||||||
private:
|
|
||||||
AutoHandle event_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
|
|
||||||
};
|
|
||||||
# endif // OS detection
|
|
||||||
|
|
||||||
// On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD
|
|
||||||
// defined, but we don't want to use MinGW's pthreads implementation, which
|
|
||||||
// has conformance problems with some versions of the POSIX standard.
|
|
||||||
# if GTEST_HAS_PTHREAD && !GTEST_OS_WINDOWS_MINGW
|
|
||||||
|
|
||||||
// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
|
// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
|
||||||
// Consequently, it cannot select a correct instantiation of ThreadWithParam
|
// Consequently, it cannot select a correct instantiation of ThreadWithParam
|
||||||
// in order to call its Run(). Introducing ThreadWithParamBase as a
|
// in order to call its Run(). Introducing ThreadWithParamBase as a
|
||||||
@@ -1558,9 +1273,10 @@ extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class ThreadWithParam : public ThreadWithParamBase {
|
class ThreadWithParam : public ThreadWithParamBase {
|
||||||
public:
|
public:
|
||||||
typedef void UserThreadFunc(T);
|
typedef void (*UserThreadFunc)(T);
|
||||||
|
|
||||||
ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
|
ThreadWithParam(
|
||||||
|
UserThreadFunc func, T param, Notification* thread_can_start)
|
||||||
: func_(func),
|
: func_(func),
|
||||||
param_(param),
|
param_(param),
|
||||||
thread_can_start_(thread_can_start),
|
thread_can_start_(thread_can_start),
|
||||||
@@ -1587,7 +1303,7 @@ class ThreadWithParam : public ThreadWithParamBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UserThreadFunc* const func_; // User-supplied thread function.
|
const UserThreadFunc func_; // User-supplied thread function.
|
||||||
const T param_; // User-supplied parameter to the thread function.
|
const T param_; // User-supplied parameter to the thread function.
|
||||||
// When non-NULL, used to block execution until the controller thread
|
// When non-NULL, used to block execution until the controller thread
|
||||||
// notifies.
|
// notifies.
|
||||||
@@ -1597,255 +1313,26 @@ class ThreadWithParam : public ThreadWithParamBase {
|
|||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
|
||||||
};
|
};
|
||||||
# endif // GTEST_HAS_PTHREAD && !GTEST_OS_WINDOWS_MINGW
|
|
||||||
|
|
||||||
# if 0 // OS detection
|
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
|
||||||
# elif GTEST_OS_WINDOWS
|
// are used in conjunction with class MutexLock:
|
||||||
|
|
||||||
// Mutex implements mutex on Windows platforms. It is used in conjunction
|
|
||||||
// with class MutexLock:
|
|
||||||
//
|
//
|
||||||
// Mutex mutex;
|
// Mutex mutex;
|
||||||
// ...
|
// ...
|
||||||
// MutexLock lock(&mutex); // Acquires the mutex and releases it at the
|
// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end
|
||||||
// // end of the current scope.
|
// // of the current scope.
|
||||||
|
//
|
||||||
|
// MutexBase implements behavior for both statically and dynamically
|
||||||
|
// allocated mutexes. Do not use MutexBase directly. Instead, write
|
||||||
|
// the following to define a static mutex:
|
||||||
//
|
//
|
||||||
// A static Mutex *must* be defined or declared using one of the following
|
|
||||||
// macros:
|
|
||||||
// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
|
// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
|
||||||
|
//
|
||||||
|
// You can forward declare a static mutex like this:
|
||||||
|
//
|
||||||
// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
|
// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
|
||||||
//
|
//
|
||||||
// (A non-static Mutex is defined/declared in the usual way).
|
// To create a dynamic mutex, just define an object of type Mutex.
|
||||||
class GTEST_API_ Mutex {
|
|
||||||
public:
|
|
||||||
enum MutexType { kStatic = 0, kDynamic = 1 };
|
|
||||||
// We rely on kStaticMutex being 0 as it is to what the linker initializes
|
|
||||||
// type_ in static mutexes. critical_section_ will be initialized lazily
|
|
||||||
// in ThreadSafeLazyInit().
|
|
||||||
enum StaticConstructorSelector { kStaticMutex = 0 };
|
|
||||||
|
|
||||||
// This constructor intentionally does nothing. It relies on type_ being
|
|
||||||
// statically initialized to 0 (effectively setting it to kStatic) and on
|
|
||||||
// ThreadSafeLazyInit() to lazily initialize the rest of the members.
|
|
||||||
explicit Mutex(StaticConstructorSelector /*dummy*/) {}
|
|
||||||
|
|
||||||
Mutex();
|
|
||||||
~Mutex();
|
|
||||||
|
|
||||||
void Lock();
|
|
||||||
|
|
||||||
void Unlock();
|
|
||||||
|
|
||||||
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
|
||||||
// with high probability.
|
|
||||||
void AssertHeld();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Initializes owner_thread_id_ and critical_section_ in static mutexes.
|
|
||||||
void ThreadSafeLazyInit();
|
|
||||||
|
|
||||||
// Per http://blogs.msdn.com/b/oldnewthing/archive/2004/02/23/78395.aspx,
|
|
||||||
// we assume that 0 is an invalid value for thread IDs.
|
|
||||||
unsigned int owner_thread_id_;
|
|
||||||
|
|
||||||
// For static mutexes, we rely on these members being initialized to zeros
|
|
||||||
// by the linker.
|
|
||||||
MutexType type_;
|
|
||||||
long critical_section_init_phase_; // NOLINT
|
|
||||||
_RTL_CRITICAL_SECTION* critical_section_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
|
|
||||||
};
|
|
||||||
|
|
||||||
# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
|
|
||||||
extern ::testing::internal::Mutex mutex
|
|
||||||
|
|
||||||
# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
|
|
||||||
::testing::internal::Mutex mutex(::testing::internal::Mutex::kStaticMutex)
|
|
||||||
|
|
||||||
// We cannot name this class MutexLock because the ctor declaration would
|
|
||||||
// conflict with a macro named MutexLock, which is defined on some
|
|
||||||
// platforms. That macro is used as a defensive measure to prevent against
|
|
||||||
// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
|
|
||||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
|
||||||
class GTestMutexLock {
|
|
||||||
public:
|
|
||||||
explicit GTestMutexLock(Mutex* mutex)
|
|
||||||
: mutex_(mutex) { mutex_->Lock(); }
|
|
||||||
|
|
||||||
~GTestMutexLock() { mutex_->Unlock(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Mutex* const mutex_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef GTestMutexLock MutexLock;
|
|
||||||
|
|
||||||
// Base class for ValueHolder<T>. Allows a caller to hold and delete a value
|
|
||||||
// without knowing its type.
|
|
||||||
class ThreadLocalValueHolderBase {
|
|
||||||
public:
|
|
||||||
virtual ~ThreadLocalValueHolderBase() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Provides a way for a thread to send notifications to a ThreadLocal
|
|
||||||
// regardless of its parameter type.
|
|
||||||
class ThreadLocalBase {
|
|
||||||
public:
|
|
||||||
// Creates a new ValueHolder<T> object holding a default value passed to
|
|
||||||
// this ThreadLocal<T>'s constructor and returns it. It is the caller's
|
|
||||||
// responsibility not to call this when the ThreadLocal<T> instance already
|
|
||||||
// has a value on the current thread.
|
|
||||||
virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ThreadLocalBase() {}
|
|
||||||
virtual ~ThreadLocalBase() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocalBase);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Maps a thread to a set of ThreadLocals that have values instantiated on that
|
|
||||||
// thread and notifies them when the thread exits. A ThreadLocal instance is
|
|
||||||
// expected to persist until all threads it has values on have terminated.
|
|
||||||
class GTEST_API_ ThreadLocalRegistry {
|
|
||||||
public:
|
|
||||||
// Registers thread_local_instance as having value on the current thread.
|
|
||||||
// Returns a value that can be used to identify the thread from other threads.
|
|
||||||
static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
|
|
||||||
const ThreadLocalBase* thread_local_instance);
|
|
||||||
|
|
||||||
// Invoked when a ThreadLocal instance is destroyed.
|
|
||||||
static void OnThreadLocalDestroyed(
|
|
||||||
const ThreadLocalBase* thread_local_instance);
|
|
||||||
};
|
|
||||||
|
|
||||||
class GTEST_API_ ThreadWithParamBase {
|
|
||||||
public:
|
|
||||||
void Join();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Runnable {
|
|
||||||
public:
|
|
||||||
virtual ~Runnable() {}
|
|
||||||
virtual void Run() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
ThreadWithParamBase(Runnable *runnable, Notification* thread_can_start);
|
|
||||||
virtual ~ThreadWithParamBase();
|
|
||||||
|
|
||||||
private:
|
|
||||||
AutoHandle thread_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper class for testing Google Test's multi-threading constructs.
|
|
||||||
template <typename T>
|
|
||||||
class ThreadWithParam : public ThreadWithParamBase {
|
|
||||||
public:
|
|
||||||
typedef void UserThreadFunc(T);
|
|
||||||
|
|
||||||
ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
|
|
||||||
: ThreadWithParamBase(new RunnableImpl(func, param), thread_can_start) {
|
|
||||||
}
|
|
||||||
virtual ~ThreadWithParam() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
class RunnableImpl : public Runnable {
|
|
||||||
public:
|
|
||||||
RunnableImpl(UserThreadFunc* func, T param)
|
|
||||||
: func_(func),
|
|
||||||
param_(param) {
|
|
||||||
}
|
|
||||||
virtual ~RunnableImpl() {}
|
|
||||||
virtual void Run() {
|
|
||||||
func_(param_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
UserThreadFunc* const func_;
|
|
||||||
const T param_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(RunnableImpl);
|
|
||||||
};
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Implements thread-local storage on Windows systems.
|
|
||||||
//
|
|
||||||
// // Thread 1
|
|
||||||
// ThreadLocal<int> tl(100); // 100 is the default value for each thread.
|
|
||||||
//
|
|
||||||
// // Thread 2
|
|
||||||
// tl.set(150); // Changes the value for thread 2 only.
|
|
||||||
// EXPECT_EQ(150, tl.get());
|
|
||||||
//
|
|
||||||
// // Thread 1
|
|
||||||
// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value.
|
|
||||||
// tl.set(200);
|
|
||||||
// EXPECT_EQ(200, tl.get());
|
|
||||||
//
|
|
||||||
// The template type argument T must have a public copy constructor.
|
|
||||||
// In addition, the default ThreadLocal constructor requires T to have
|
|
||||||
// a public default constructor.
|
|
||||||
//
|
|
||||||
// The users of a TheadLocal instance have to make sure that all but one
|
|
||||||
// threads (including the main one) using that instance have exited before
|
|
||||||
// destroying it. Otherwise, the per-thread objects managed for them by the
|
|
||||||
// ThreadLocal instance are not guaranteed to be destroyed on all platforms.
|
|
||||||
//
|
|
||||||
// Google Test only uses global ThreadLocal objects. That means they
|
|
||||||
// will die after main() has returned. Therefore, no per-thread
|
|
||||||
// object managed by Google Test will be leaked as long as all threads
|
|
||||||
// using Google Test have exited when main() returns.
|
|
||||||
template <typename T>
|
|
||||||
class ThreadLocal : public ThreadLocalBase {
|
|
||||||
public:
|
|
||||||
ThreadLocal() : default_() {}
|
|
||||||
explicit ThreadLocal(const T& value) : default_(value) {}
|
|
||||||
|
|
||||||
~ThreadLocal() { ThreadLocalRegistry::OnThreadLocalDestroyed(this); }
|
|
||||||
|
|
||||||
T* pointer() { return GetOrCreateValue(); }
|
|
||||||
const T* pointer() const { return GetOrCreateValue(); }
|
|
||||||
const T& get() const { return *pointer(); }
|
|
||||||
void set(const T& value) { *pointer() = value; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Holds a value of T. Can be deleted via its base class without the caller
|
|
||||||
// knowing the type of T.
|
|
||||||
class ValueHolder : public ThreadLocalValueHolderBase {
|
|
||||||
public:
|
|
||||||
explicit ValueHolder(const T& value) : value_(value) {}
|
|
||||||
|
|
||||||
T* pointer() { return &value_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
T value_;
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
T* GetOrCreateValue() const {
|
|
||||||
return static_cast<ValueHolder*>(
|
|
||||||
ThreadLocalRegistry::GetValueOnCurrentThread(this))->pointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const {
|
|
||||||
return new ValueHolder(default_);
|
|
||||||
}
|
|
||||||
|
|
||||||
const T default_; // The default value for each thread.
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
|
|
||||||
};
|
|
||||||
|
|
||||||
# elif GTEST_HAS_PTHREAD
|
|
||||||
|
|
||||||
// MutexBase and Mutex implement mutex on pthreads-based platforms.
|
|
||||||
class MutexBase {
|
class MutexBase {
|
||||||
public:
|
public:
|
||||||
// Acquires this mutex.
|
// Acquires this mutex.
|
||||||
@@ -1890,8 +1377,8 @@ class MutexBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Forward-declares a static mutex.
|
// Forward-declares a static mutex.
|
||||||
# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
|
# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
|
||||||
extern ::testing::internal::MutexBase mutex
|
extern ::testing::internal::MutexBase mutex
|
||||||
|
|
||||||
// Defines and statically (i.e. at link time) initializes a static mutex.
|
// Defines and statically (i.e. at link time) initializes a static mutex.
|
||||||
// The initialization list here does not explicitly initialize each field,
|
// The initialization list here does not explicitly initialize each field,
|
||||||
@@ -1899,8 +1386,8 @@ class MutexBase {
|
|||||||
// particular, the owner_ field (a pthread_t) is not explicitly initialized.
|
// particular, the owner_ field (a pthread_t) is not explicitly initialized.
|
||||||
// This allows initialization to work whether pthread_t is a scalar or struct.
|
// This allows initialization to work whether pthread_t is a scalar or struct.
|
||||||
// The flag -Wmissing-field-initializers must not be specified for this to work.
|
// The flag -Wmissing-field-initializers must not be specified for this to work.
|
||||||
# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
|
# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
|
||||||
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false }
|
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false }
|
||||||
|
|
||||||
// The Mutex class can only be used for mutexes created at runtime. It
|
// The Mutex class can only be used for mutexes created at runtime. It
|
||||||
// shares its API with MutexBase otherwise.
|
// shares its API with MutexBase otherwise.
|
||||||
@@ -1918,11 +1405,9 @@ class Mutex : public MutexBase {
|
|||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
|
||||||
};
|
};
|
||||||
|
|
||||||
// We cannot name this class MutexLock because the ctor declaration would
|
// We cannot name this class MutexLock as the ctor declaration would
|
||||||
// conflict with a macro named MutexLock, which is defined on some
|
// conflict with a macro named MutexLock, which is defined on some
|
||||||
// platforms. That macro is used as a defensive measure to prevent against
|
// platforms. Hence the typedef trick below.
|
||||||
// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
|
|
||||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
|
||||||
class GTestMutexLock {
|
class GTestMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit GTestMutexLock(MutexBase* mutex)
|
explicit GTestMutexLock(MutexBase* mutex)
|
||||||
@@ -1956,6 +1441,34 @@ extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements thread-local storage on pthreads-based systems.
|
// Implements thread-local storage on pthreads-based systems.
|
||||||
|
//
|
||||||
|
// // Thread 1
|
||||||
|
// ThreadLocal<int> tl(100); // 100 is the default value for each thread.
|
||||||
|
//
|
||||||
|
// // Thread 2
|
||||||
|
// tl.set(150); // Changes the value for thread 2 only.
|
||||||
|
// EXPECT_EQ(150, tl.get());
|
||||||
|
//
|
||||||
|
// // Thread 1
|
||||||
|
// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value.
|
||||||
|
// tl.set(200);
|
||||||
|
// EXPECT_EQ(200, tl.get());
|
||||||
|
//
|
||||||
|
// The template type argument T must have a public copy constructor.
|
||||||
|
// In addition, the default ThreadLocal constructor requires T to have
|
||||||
|
// a public default constructor.
|
||||||
|
//
|
||||||
|
// An object managed for a thread by a ThreadLocal instance is deleted
|
||||||
|
// when the thread exits. Or, if the ThreadLocal instance dies in
|
||||||
|
// that thread, when the ThreadLocal dies. It's the user's
|
||||||
|
// responsibility to ensure that all other threads using a ThreadLocal
|
||||||
|
// have exited when it dies, or the per-thread objects for those
|
||||||
|
// threads will not be deleted.
|
||||||
|
//
|
||||||
|
// Google Test only uses global ThreadLocal objects. That means they
|
||||||
|
// will die after main() has returned. Therefore, no per-thread
|
||||||
|
// object managed by Google Test will be leaked as long as all threads
|
||||||
|
// using Google Test have exited when main() returns.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ThreadLocal {
|
class ThreadLocal {
|
||||||
public:
|
public:
|
||||||
@@ -2020,9 +1533,9 @@ class ThreadLocal {
|
|||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
|
||||||
};
|
};
|
||||||
|
|
||||||
# endif // OS detection
|
# define GTEST_IS_THREADSAFE 1
|
||||||
|
|
||||||
#else // GTEST_IS_THREADSAFE
|
#else // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
// A dummy implementation of synchronization primitives (mutex, lock,
|
// A dummy implementation of synchronization primitives (mutex, lock,
|
||||||
// and thread-local variable). Necessary for compiling Google Test where
|
// and thread-local variable). Necessary for compiling Google Test where
|
||||||
@@ -2042,11 +1555,6 @@ class Mutex {
|
|||||||
|
|
||||||
# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
|
# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
|
||||||
|
|
||||||
// We cannot name this class MutexLock because the ctor declaration would
|
|
||||||
// conflict with a macro named MutexLock, which is defined on some
|
|
||||||
// platforms. That macro is used as a defensive measure to prevent against
|
|
||||||
// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
|
|
||||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
|
||||||
class GTestMutexLock {
|
class GTestMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit GTestMutexLock(Mutex*) {} // NOLINT
|
explicit GTestMutexLock(Mutex*) {} // NOLINT
|
||||||
@@ -2067,7 +1575,11 @@ class ThreadLocal {
|
|||||||
T value_;
|
T value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GTEST_IS_THREADSAFE
|
// The above synchronization primitives have dummy implementations.
|
||||||
|
// Therefore Google Test is not thread-safe.
|
||||||
|
# define GTEST_IS_THREADSAFE 0
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_PTHREAD
|
||||||
|
|
||||||
// Returns the number of threads running in the process, or 0 to indicate that
|
// Returns the number of threads running in the process, or 0 to indicate that
|
||||||
// we cannot detect it.
|
// we cannot detect it.
|
||||||
@@ -2240,7 +1752,11 @@ inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
|
|||||||
|
|
||||||
// Functions deprecated by MSVC 8.0.
|
// Functions deprecated by MSVC 8.0.
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996 /* deprecated function */)
|
#ifdef _MSC_VER
|
||||||
|
// Temporarily disable warning 4996 (deprecated function).
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
inline const char* StrNCpy(char* dest, const char* src, size_t n) {
|
inline const char* StrNCpy(char* dest, const char* src, size_t n) {
|
||||||
return strncpy(dest, src, n);
|
return strncpy(dest, src, n);
|
||||||
@@ -2250,7 +1766,7 @@ inline const char* StrNCpy(char* dest, const char* src, size_t n) {
|
|||||||
// StrError() aren't needed on Windows CE at this time and thus not
|
// StrError() aren't needed on Windows CE at this time and thus not
|
||||||
// defined there.
|
// defined there.
|
||||||
|
|
||||||
#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
|
#if !GTEST_OS_WINDOWS_MOBILE
|
||||||
inline int ChDir(const char* dir) { return chdir(dir); }
|
inline int ChDir(const char* dir) { return chdir(dir); }
|
||||||
#endif
|
#endif
|
||||||
inline FILE* FOpen(const char* path, const char* mode) {
|
inline FILE* FOpen(const char* path, const char* mode) {
|
||||||
@@ -2274,7 +1790,7 @@ inline int Close(int fd) { return close(fd); }
|
|||||||
inline const char* StrError(int errnum) { return strerror(errnum); }
|
inline const char* StrError(int errnum) { return strerror(errnum); }
|
||||||
#endif
|
#endif
|
||||||
inline const char* GetEnv(const char* name) {
|
inline const char* GetEnv(const char* name) {
|
||||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE | GTEST_OS_WINDOWS_RT
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
// We are on Windows CE, which has no environment variables.
|
// We are on Windows CE, which has no environment variables.
|
||||||
return NULL;
|
return NULL;
|
||||||
#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
|
#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
|
||||||
@@ -2287,7 +1803,9 @@ inline const char* GetEnv(const char* name) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS_MOBILE
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
// Windows CE has no C library. The abort() function is used in
|
// Windows CE has no C library. The abort() function is used in
|
||||||
@@ -2427,4 +1945,3 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
|
|||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
||||||
|
|
||||||
@@ -53,14 +53,6 @@
|
|||||||
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
|
|
||||||
// those compilers.
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */
|
|
||||||
# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \
|
|
||||||
GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GTEST_n_TUPLE_(T) is the type of an n-tuple.
|
// GTEST_n_TUPLE_(T) is the type of an n-tuple.
|
||||||
#define GTEST_0_TUPLE_(T) tuple<>
|
#define GTEST_0_TUPLE_(T) tuple<>
|
||||||
#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
|
#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
|
||||||
@@ -52,14 +52,6 @@ $$ This meta comment fixes auto-indentation in Emacs. }}
|
|||||||
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
|
|
||||||
// those compilers.
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */
|
|
||||||
# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \
|
|
||||||
GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
$range i 0..n-1
|
$range i 0..n-1
|
||||||
$range j 0..n
|
$range j 0..n
|
||||||
@@ -70,6 +70,7 @@ namespace internal {
|
|||||||
// of them.
|
// of them.
|
||||||
const char kPathSeparator = '\\';
|
const char kPathSeparator = '\\';
|
||||||
const char kAlternatePathSeparator = '/';
|
const char kAlternatePathSeparator = '/';
|
||||||
|
const char kPathSeparatorString[] = "\\";
|
||||||
const char kAlternatePathSeparatorString[] = "/";
|
const char kAlternatePathSeparatorString[] = "/";
|
||||||
# if GTEST_OS_WINDOWS_MOBILE
|
# if GTEST_OS_WINDOWS_MOBILE
|
||||||
// Windows CE doesn't have a current directory. You should not use
|
// Windows CE doesn't have a current directory. You should not use
|
||||||
@@ -83,6 +84,7 @@ const char kCurrentDirectoryString[] = ".\\";
|
|||||||
# endif // GTEST_OS_WINDOWS_MOBILE
|
# endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
#else
|
#else
|
||||||
const char kPathSeparator = '/';
|
const char kPathSeparator = '/';
|
||||||
|
const char kPathSeparatorString[] = "/";
|
||||||
const char kCurrentDirectoryString[] = "./";
|
const char kCurrentDirectoryString[] = "./";
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
@@ -97,7 +99,7 @@ static bool IsPathSeparator(char c) {
|
|||||||
|
|
||||||
// Returns the current working directory, or "" if unsuccessful.
|
// Returns the current working directory, or "" if unsuccessful.
|
||||||
FilePath FilePath::GetCurrentDir() {
|
FilePath FilePath::GetCurrentDir() {
|
||||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
// Windows CE doesn't have a current directory, so we just return
|
// Windows CE doesn't have a current directory, so we just return
|
||||||
// something reasonable.
|
// something reasonable.
|
||||||
return FilePath(kCurrentDirectoryString);
|
return FilePath(kCurrentDirectoryString);
|
||||||
@@ -968,6 +968,32 @@ GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
|
|||||||
// platform.
|
// platform.
|
||||||
GTEST_API_ std::string GetLastErrnoDescription();
|
GTEST_API_ std::string GetLastErrnoDescription();
|
||||||
|
|
||||||
|
# if GTEST_OS_WINDOWS
|
||||||
|
// Provides leak-safe Windows kernel handle ownership.
|
||||||
|
class AutoHandle {
|
||||||
|
public:
|
||||||
|
AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
|
||||||
|
explicit AutoHandle(HANDLE handle) : handle_(handle) {}
|
||||||
|
|
||||||
|
~AutoHandle() { Reset(); }
|
||||||
|
|
||||||
|
HANDLE Get() const { return handle_; }
|
||||||
|
void Reset() { Reset(INVALID_HANDLE_VALUE); }
|
||||||
|
void Reset(HANDLE handle) {
|
||||||
|
if (handle != handle_) {
|
||||||
|
if (handle_ != INVALID_HANDLE_VALUE)
|
||||||
|
::CloseHandle(handle_);
|
||||||
|
handle_ = handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HANDLE handle_;
|
||||||
|
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
|
||||||
|
};
|
||||||
|
# endif // GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// Attempts to parse a string into a positive integer pointed to by the
|
// Attempts to parse a string into a positive integer pointed to by the
|
||||||
// number parameter. Returns true if that is possible.
|
// number parameter. Returns true if that is possible.
|
||||||
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
|
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
|
||||||
@@ -36,14 +36,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS
|
#if GTEST_OS_WINDOWS_MOBILE
|
||||||
# include <windows.h>
|
# include <windows.h> // For TerminateProcess()
|
||||||
|
#elif GTEST_OS_WINDOWS
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <map> // Used in ThreadLocal.
|
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif // GTEST_OS_WINDOWS
|
#endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
#if GTEST_OS_MAC
|
#if GTEST_OS_MAC
|
||||||
# include <mach/mach_init.h>
|
# include <mach/mach_init.h>
|
||||||
@@ -53,7 +53,6 @@
|
|||||||
|
|
||||||
#if GTEST_OS_QNX
|
#if GTEST_OS_QNX
|
||||||
# include <devctl.h>
|
# include <devctl.h>
|
||||||
# include <fcntl.h>
|
|
||||||
# include <sys/procfs.h>
|
# include <sys/procfs.h>
|
||||||
#endif // GTEST_OS_QNX
|
#endif // GTEST_OS_QNX
|
||||||
|
|
||||||
@@ -134,389 +133,6 @@ size_t GetThreadCount() {
|
|||||||
|
|
||||||
#endif // GTEST_OS_MAC
|
#endif // GTEST_OS_MAC
|
||||||
|
|
||||||
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
|
||||||
|
|
||||||
void SleepMilliseconds(int n) {
|
|
||||||
::Sleep(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoHandle::AutoHandle()
|
|
||||||
: handle_(INVALID_HANDLE_VALUE) {}
|
|
||||||
|
|
||||||
AutoHandle::AutoHandle(Handle handle)
|
|
||||||
: handle_(handle) {}
|
|
||||||
|
|
||||||
AutoHandle::~AutoHandle() {
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoHandle::Handle AutoHandle::Get() const {
|
|
||||||
return handle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoHandle::Reset() {
|
|
||||||
Reset(INVALID_HANDLE_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AutoHandle::Reset(HANDLE handle) {
|
|
||||||
// Resetting with the same handle we already own is invalid.
|
|
||||||
if (handle_ != handle) {
|
|
||||||
if (IsCloseable()) {
|
|
||||||
::CloseHandle(handle_);
|
|
||||||
}
|
|
||||||
handle_ = handle;
|
|
||||||
} else {
|
|
||||||
GTEST_CHECK_(!IsCloseable())
|
|
||||||
<< "Resetting a valid handle to itself is likely a programmer error "
|
|
||||||
"and thus not allowed.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AutoHandle::IsCloseable() const {
|
|
||||||
// Different Windows APIs may use either of these values to represent an
|
|
||||||
// invalid handle.
|
|
||||||
return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Notification::Notification()
|
|
||||||
: event_(::CreateEvent(NULL, // Default security attributes.
|
|
||||||
TRUE, // Do not reset automatically.
|
|
||||||
FALSE, // Initially unset.
|
|
||||||
NULL)) { // Anonymous event.
|
|
||||||
GTEST_CHECK_(event_.Get() != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notification::Notify() {
|
|
||||||
GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Notification::WaitForNotification() {
|
|
||||||
GTEST_CHECK_(
|
|
||||||
::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mutex::Mutex()
|
|
||||||
: type_(kDynamic),
|
|
||||||
owner_thread_id_(0),
|
|
||||||
critical_section_init_phase_(0),
|
|
||||||
critical_section_(new CRITICAL_SECTION) {
|
|
||||||
::InitializeCriticalSection(critical_section_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mutex::~Mutex() {
|
|
||||||
// Static mutexes are leaked intentionally. It is not thread-safe to try
|
|
||||||
// to clean them up.
|
|
||||||
// TODO(yukawa): Switch to Slim Reader/Writer (SRW) Locks, which requires
|
|
||||||
// nothing to clean it up but is available only on Vista and later.
|
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937.aspx
|
|
||||||
if (type_ == kDynamic) {
|
|
||||||
::DeleteCriticalSection(critical_section_);
|
|
||||||
delete critical_section_;
|
|
||||||
critical_section_ = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mutex::Lock() {
|
|
||||||
ThreadSafeLazyInit();
|
|
||||||
::EnterCriticalSection(critical_section_);
|
|
||||||
owner_thread_id_ = ::GetCurrentThreadId();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mutex::Unlock() {
|
|
||||||
ThreadSafeLazyInit();
|
|
||||||
// We don't protect writing to owner_thread_id_ here, as it's the
|
|
||||||
// caller's responsibility to ensure that the current thread holds the
|
|
||||||
// mutex when this is called.
|
|
||||||
owner_thread_id_ = 0;
|
|
||||||
::LeaveCriticalSection(critical_section_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
|
||||||
// with high probability.
|
|
||||||
void Mutex::AssertHeld() {
|
|
||||||
ThreadSafeLazyInit();
|
|
||||||
GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
|
|
||||||
<< "The current thread is not holding the mutex @" << this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initializes owner_thread_id_ and critical_section_ in static mutexes.
|
|
||||||
void Mutex::ThreadSafeLazyInit() {
|
|
||||||
// Dynamic mutexes are initialized in the constructor.
|
|
||||||
if (type_ == kStatic) {
|
|
||||||
switch (
|
|
||||||
::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
|
|
||||||
case 0:
|
|
||||||
// If critical_section_init_phase_ was 0 before the exchange, we
|
|
||||||
// are the first to test it and need to perform the initialization.
|
|
||||||
owner_thread_id_ = 0;
|
|
||||||
critical_section_ = new CRITICAL_SECTION;
|
|
||||||
::InitializeCriticalSection(critical_section_);
|
|
||||||
// Updates the critical_section_init_phase_ to 2 to signal
|
|
||||||
// initialization complete.
|
|
||||||
GTEST_CHECK_(::InterlockedCompareExchange(
|
|
||||||
&critical_section_init_phase_, 2L, 1L) ==
|
|
||||||
1L);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// Somebody else is already initializing the mutex; spin until they
|
|
||||||
// are done.
|
|
||||||
while (::InterlockedCompareExchange(&critical_section_init_phase_,
|
|
||||||
2L,
|
|
||||||
2L) != 2L) {
|
|
||||||
// Possibly yields the rest of the thread's time slice to other
|
|
||||||
// threads.
|
|
||||||
::Sleep(0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
break; // The mutex is already initialized and ready for use.
|
|
||||||
|
|
||||||
default:
|
|
||||||
GTEST_CHECK_(false)
|
|
||||||
<< "Unexpected value of critical_section_init_phase_ "
|
|
||||||
<< "while initializing a static mutex.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class ThreadWithParamSupport : public ThreadWithParamBase {
|
|
||||||
public:
|
|
||||||
static HANDLE CreateThread(Runnable* runnable,
|
|
||||||
Notification* thread_can_start) {
|
|
||||||
ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
|
|
||||||
DWORD thread_id;
|
|
||||||
// TODO(yukawa): Consider to use _beginthreadex instead.
|
|
||||||
HANDLE thread_handle = ::CreateThread(
|
|
||||||
NULL, // Default security.
|
|
||||||
0, // Default stack size.
|
|
||||||
&ThreadWithParamSupport::ThreadMain,
|
|
||||||
param, // Parameter to ThreadMainStatic
|
|
||||||
0x0, // Default creation flags.
|
|
||||||
&thread_id); // Need a valid pointer for the call to work under Win98.
|
|
||||||
GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error "
|
|
||||||
<< ::GetLastError() << ".";
|
|
||||||
if (thread_handle == NULL) {
|
|
||||||
delete param;
|
|
||||||
}
|
|
||||||
return thread_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct ThreadMainParam {
|
|
||||||
ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
|
|
||||||
: runnable_(runnable),
|
|
||||||
thread_can_start_(thread_can_start) {
|
|
||||||
}
|
|
||||||
scoped_ptr<Runnable> runnable_;
|
|
||||||
// Does not own.
|
|
||||||
Notification* thread_can_start_;
|
|
||||||
};
|
|
||||||
|
|
||||||
static DWORD WINAPI ThreadMain(void* ptr) {
|
|
||||||
// Transfers ownership.
|
|
||||||
scoped_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
|
|
||||||
if (param->thread_can_start_ != NULL)
|
|
||||||
param->thread_can_start_->WaitForNotification();
|
|
||||||
param->runnable_->Run();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prohibit instantiation.
|
|
||||||
ThreadWithParamSupport();
|
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
|
|
||||||
Notification* thread_can_start)
|
|
||||||
: thread_(ThreadWithParamSupport::CreateThread(runnable,
|
|
||||||
thread_can_start)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadWithParamBase::~ThreadWithParamBase() {
|
|
||||||
Join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadWithParamBase::Join() {
|
|
||||||
GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
|
|
||||||
<< "Failed to join the thread with error " << ::GetLastError() << ".";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maps a thread to a set of ThreadIdToThreadLocals that have values
|
|
||||||
// instantiated on that thread and notifies them when the thread exits. A
|
|
||||||
// ThreadLocal instance is expected to persist until all threads it has
|
|
||||||
// values on have terminated.
|
|
||||||
class ThreadLocalRegistryImpl {
|
|
||||||
public:
|
|
||||||
// Registers thread_local_instance as having value on the current thread.
|
|
||||||
// Returns a value that can be used to identify the thread from other threads.
|
|
||||||
static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
|
|
||||||
const ThreadLocalBase* thread_local_instance) {
|
|
||||||
DWORD current_thread = ::GetCurrentThreadId();
|
|
||||||
MutexLock lock(&mutex_);
|
|
||||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
|
||||||
GetThreadLocalsMapLocked();
|
|
||||||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
|
||||||
thread_to_thread_locals->find(current_thread);
|
|
||||||
if (thread_local_pos == thread_to_thread_locals->end()) {
|
|
||||||
thread_local_pos = thread_to_thread_locals->insert(
|
|
||||||
std::make_pair(current_thread, ThreadLocalValues())).first;
|
|
||||||
StartWatcherThreadFor(current_thread);
|
|
||||||
}
|
|
||||||
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
|
||||||
ThreadLocalValues::iterator value_pos =
|
|
||||||
thread_local_values.find(thread_local_instance);
|
|
||||||
if (value_pos == thread_local_values.end()) {
|
|
||||||
value_pos =
|
|
||||||
thread_local_values
|
|
||||||
.insert(std::make_pair(
|
|
||||||
thread_local_instance,
|
|
||||||
linked_ptr<ThreadLocalValueHolderBase>(
|
|
||||||
thread_local_instance->NewValueForCurrentThread())))
|
|
||||||
.first;
|
|
||||||
}
|
|
||||||
return value_pos->second.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnThreadLocalDestroyed(
|
|
||||||
const ThreadLocalBase* thread_local_instance) {
|
|
||||||
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
|
|
||||||
// Clean up the ThreadLocalValues data structure while holding the lock, but
|
|
||||||
// defer the destruction of the ThreadLocalValueHolderBases.
|
|
||||||
{
|
|
||||||
MutexLock lock(&mutex_);
|
|
||||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
|
||||||
GetThreadLocalsMapLocked();
|
|
||||||
for (ThreadIdToThreadLocals::iterator it =
|
|
||||||
thread_to_thread_locals->begin();
|
|
||||||
it != thread_to_thread_locals->end();
|
|
||||||
++it) {
|
|
||||||
ThreadLocalValues& thread_local_values = it->second;
|
|
||||||
ThreadLocalValues::iterator value_pos =
|
|
||||||
thread_local_values.find(thread_local_instance);
|
|
||||||
if (value_pos != thread_local_values.end()) {
|
|
||||||
value_holders.push_back(value_pos->second);
|
|
||||||
thread_local_values.erase(value_pos);
|
|
||||||
// This 'if' can only be successful at most once, so theoretically we
|
|
||||||
// could break out of the loop here, but we don't bother doing so.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Outside the lock, let the destructor for 'value_holders' deallocate the
|
|
||||||
// ThreadLocalValueHolderBases.
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnThreadExit(DWORD thread_id) {
|
|
||||||
GTEST_CHECK_(thread_id != 0) << ::GetLastError();
|
|
||||||
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
|
|
||||||
// Clean up the ThreadIdToThreadLocals data structure while holding the
|
|
||||||
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
|
|
||||||
{
|
|
||||||
MutexLock lock(&mutex_);
|
|
||||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
|
||||||
GetThreadLocalsMapLocked();
|
|
||||||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
|
||||||
thread_to_thread_locals->find(thread_id);
|
|
||||||
if (thread_local_pos != thread_to_thread_locals->end()) {
|
|
||||||
ThreadLocalValues& thread_local_values = thread_local_pos->second;
|
|
||||||
for (ThreadLocalValues::iterator value_pos =
|
|
||||||
thread_local_values.begin();
|
|
||||||
value_pos != thread_local_values.end();
|
|
||||||
++value_pos) {
|
|
||||||
value_holders.push_back(value_pos->second);
|
|
||||||
}
|
|
||||||
thread_to_thread_locals->erase(thread_local_pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Outside the lock, let the destructor for 'value_holders' deallocate the
|
|
||||||
// ThreadLocalValueHolderBases.
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// In a particular thread, maps a ThreadLocal object to its value.
|
|
||||||
typedef std::map<const ThreadLocalBase*,
|
|
||||||
linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues;
|
|
||||||
// Stores all ThreadIdToThreadLocals having values in a thread, indexed by
|
|
||||||
// thread's ID.
|
|
||||||
typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
|
|
||||||
|
|
||||||
// Holds the thread id and thread handle that we pass from
|
|
||||||
// StartWatcherThreadFor to WatcherThreadFunc.
|
|
||||||
typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
|
|
||||||
|
|
||||||
static void StartWatcherThreadFor(DWORD thread_id) {
|
|
||||||
// The returned handle will be kept in thread_map and closed by
|
|
||||||
// watcher_thread in WatcherThreadFunc.
|
|
||||||
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
|
|
||||||
FALSE,
|
|
||||||
thread_id);
|
|
||||||
GTEST_CHECK_(thread != NULL);
|
|
||||||
// We need to to pass a valid thread ID pointer into CreateThread for it
|
|
||||||
// to work correctly under Win98.
|
|
||||||
DWORD watcher_thread_id;
|
|
||||||
HANDLE watcher_thread = ::CreateThread(
|
|
||||||
NULL, // Default security.
|
|
||||||
0, // Default stack size
|
|
||||||
&ThreadLocalRegistryImpl::WatcherThreadFunc,
|
|
||||||
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
|
|
||||||
CREATE_SUSPENDED,
|
|
||||||
&watcher_thread_id);
|
|
||||||
GTEST_CHECK_(watcher_thread != NULL);
|
|
||||||
// Give the watcher thread the same priority as ours to avoid being
|
|
||||||
// blocked by it.
|
|
||||||
::SetThreadPriority(watcher_thread,
|
|
||||||
::GetThreadPriority(::GetCurrentThread()));
|
|
||||||
::ResumeThread(watcher_thread);
|
|
||||||
::CloseHandle(watcher_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Monitors exit from a given thread and notifies those
|
|
||||||
// ThreadIdToThreadLocals about thread termination.
|
|
||||||
static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
|
|
||||||
const ThreadIdAndHandle* tah =
|
|
||||||
reinterpret_cast<const ThreadIdAndHandle*>(param);
|
|
||||||
GTEST_CHECK_(
|
|
||||||
::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
|
|
||||||
OnThreadExit(tah->first);
|
|
||||||
::CloseHandle(tah->second);
|
|
||||||
delete tah;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns map of thread local instances.
|
|
||||||
static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
|
|
||||||
mutex_.AssertHeld();
|
|
||||||
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals;
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protects access to GetThreadLocalsMapLocked() and its return value.
|
|
||||||
static Mutex mutex_;
|
|
||||||
// Protects access to GetThreadMapLocked() and its return value.
|
|
||||||
static Mutex thread_map_mutex_;
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
|
|
||||||
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);
|
|
||||||
|
|
||||||
ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
|
|
||||||
const ThreadLocalBase* thread_local_instance) {
|
|
||||||
return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
|
|
||||||
thread_local_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadLocalRegistry::OnThreadLocalDestroyed(
|
|
||||||
const ThreadLocalBase* thread_local_instance) {
|
|
||||||
ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
|
|
||||||
|
|
||||||
#if GTEST_USES_POSIX_RE
|
#if GTEST_USES_POSIX_RE
|
||||||
|
|
||||||
// Implements RE. Currently only needed for death tests.
|
// Implements RE. Currently only needed for death tests.
|
||||||
@@ -886,7 +502,10 @@ GTestLog::~GTestLog() {
|
|||||||
}
|
}
|
||||||
// Disable Microsoft deprecation warnings for POSIX functions called from
|
// Disable Microsoft deprecation warnings for POSIX functions called from
|
||||||
// this class (creat, dup, dup2, and close)
|
// this class (creat, dup, dup2, and close)
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable: 4996)
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#if GTEST_HAS_STREAM_REDIRECTION
|
#if GTEST_HAS_STREAM_REDIRECTION
|
||||||
|
|
||||||
@@ -1005,7 +624,9 @@ std::string CapturedStream::ReadEntireFile(FILE* file) {
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
# ifdef _MSC_VER
|
||||||
|
# pragma warning(pop)
|
||||||
|
# endif // _MSC_VER
|
||||||
|
|
||||||
static CapturedStream* g_captured_stderr = NULL;
|
static CapturedStream* g_captured_stderr = NULL;
|
||||||
static CapturedStream* g_captured_stdout = NULL;
|
static CapturedStream* g_captured_stdout = NULL;
|
||||||
@@ -45,7 +45,6 @@
|
|||||||
#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"
|
||||||
@@ -57,9 +56,6 @@ 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.
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
|
||||||
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
|
||||||
size_t count, ostream* os) {
|
size_t count, ostream* os) {
|
||||||
char text[5] = "";
|
char text[5] = "";
|
||||||
@@ -256,9 +252,6 @@ void PrintTo(wchar_t wc, ostream* os) {
|
|||||||
// The array starts at begin, the length is len, it may include '\0' characters
|
// The array starts at begin, the length is len, it may include '\0' characters
|
||||||
// and may not be NUL-terminated.
|
// and may not be NUL-terminated.
|
||||||
template <typename CharType>
|
template <typename CharType>
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
|
||||||
static void PrintCharsAsStringTo(
|
static void PrintCharsAsStringTo(
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
const CharType* begin, size_t len, ostream* os) {
|
||||||
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
|
||||||
@@ -280,9 +273,6 @@ static void PrintCharsAsStringTo(
|
|||||||
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
|
||||||
// 'begin'. CharType must be either char or wchar_t.
|
// 'begin'. CharType must be either char or wchar_t.
|
||||||
template <typename CharType>
|
template <typename CharType>
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
|
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
|
|
||||||
static void UniversalPrintCharArray(
|
static void UniversalPrintCharArray(
|
||||||
const CharType* begin, size_t len, ostream* os) {
|
const CharType* begin, size_t len, ostream* os) {
|
||||||
// The code
|
// The code
|
||||||
@@ -339,7 +329,7 @@ void PrintTo(const wchar_t* s, ostream* os) {
|
|||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||||
PrintCharsAsStringTo(s, std::wcslen(s), os);
|
PrintCharsAsStringTo(s, wcslen(s), os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // wchar_t is native
|
#endif // wchar_t is native
|
||||||
@@ -50,8 +50,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
|
||||||
|
|
||||||
#if GTEST_OS_LINUX
|
#if GTEST_OS_LINUX
|
||||||
|
|
||||||
// TODO(kenton@google.com): Use autoconf to detect availability of
|
// TODO(kenton@google.com): Use autoconf to detect availability of
|
||||||
@@ -804,13 +802,21 @@ TimeInMillis GetTimeInMillis() {
|
|||||||
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
|
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
|
||||||
__timeb64 now;
|
__timeb64 now;
|
||||||
|
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
|
||||||
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
|
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
|
||||||
// (deprecated function) there.
|
// (deprecated function) there.
|
||||||
// TODO(kenton@google.com): Use GetTickCount()? Or use
|
// TODO(kenton@google.com): Use GetTickCount()? Or use
|
||||||
// SystemTimeToFileTime()
|
// SystemTimeToFileTime()
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4996) // Temporarily disables warning 4996.
|
||||||
_ftime64(&now);
|
_ftime64(&now);
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
# pragma warning(pop) // Restores the warning state.
|
||||||
|
# else
|
||||||
|
|
||||||
|
_ftime64(&now);
|
||||||
|
|
||||||
|
# endif // _MSC_VER
|
||||||
|
|
||||||
return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
|
return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
|
||||||
#elif GTEST_HAS_GETTIMEOFDAY_
|
#elif GTEST_HAS_GETTIMEOFDAY_
|
||||||
@@ -950,13 +956,6 @@ AssertionResult::AssertionResult(const AssertionResult& other)
|
|||||||
static_cast< ::std::string*>(NULL)) {
|
static_cast< ::std::string*>(NULL)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swaps two AssertionResults.
|
|
||||||
void AssertionResult::swap(AssertionResult& other) {
|
|
||||||
using std::swap;
|
|
||||||
swap(success_, other.success_);
|
|
||||||
swap(message_, other.message_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
|
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
|
||||||
AssertionResult AssertionResult::operator!() const {
|
AssertionResult AssertionResult::operator!() const {
|
||||||
AssertionResult negation(!success_);
|
AssertionResult negation(!success_);
|
||||||
@@ -2555,8 +2554,7 @@ enum GTestColor {
|
|||||||
COLOR_YELLOW
|
COLOR_YELLOW
|
||||||
};
|
};
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
|
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
|
||||||
!GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
|
|
||||||
|
|
||||||
// Returns the character attribute for the given color.
|
// Returns the character attribute for the given color.
|
||||||
WORD GetColorAttribute(GTestColor color) {
|
WORD GetColorAttribute(GTestColor color) {
|
||||||
@@ -2624,8 +2622,7 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
|
|||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || \
|
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS
|
||||||
GTEST_OS_IOS || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
|
|
||||||
const bool use_color = false;
|
const bool use_color = false;
|
||||||
#else
|
#else
|
||||||
static const bool in_color_mode =
|
static const bool in_color_mode =
|
||||||
@@ -2640,8 +2637,7 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
|
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
|
||||||
!GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
|
|
||||||
const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
// Gets the current text color.
|
// Gets the current text color.
|
||||||
@@ -3223,23 +3219,27 @@ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
|
|||||||
// Converts the given epoch time in milliseconds to a date string in the ISO
|
// Converts the given epoch time in milliseconds to a date string in the ISO
|
||||||
// 8601 format, without the timezone information.
|
// 8601 format, without the timezone information.
|
||||||
std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
|
std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
|
||||||
|
// Using non-reentrant version as localtime_r is not portable.
|
||||||
time_t seconds = static_cast<time_t>(ms / 1000);
|
time_t seconds = static_cast<time_t>(ms / 1000);
|
||||||
struct tm time_struct;
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
if (localtime_s(&time_struct, &seconds) != 0)
|
# pragma warning(push) // Saves the current warning state.
|
||||||
return ""; // Invalid ms value
|
# pragma warning(disable:4996) // Temporarily disables warning 4996
|
||||||
|
// (function or variable may be unsafe).
|
||||||
|
const struct tm* const time_struct = localtime(&seconds); // NOLINT
|
||||||
|
# pragma warning(pop) // Restores the warning state again.
|
||||||
#else
|
#else
|
||||||
if (localtime_r(&seconds, &time_struct) == NULL)
|
const struct tm* const time_struct = localtime(&seconds); // NOLINT
|
||||||
return ""; // Invalid ms value
|
|
||||||
#endif
|
#endif
|
||||||
|
if (time_struct == NULL)
|
||||||
|
return ""; // Invalid ms value
|
||||||
|
|
||||||
// YYYY-MM-DDThh:mm:ss
|
// YYYY-MM-DDThh:mm:ss
|
||||||
return StreamableToString(time_struct.tm_year + 1900) + "-" +
|
return StreamableToString(time_struct->tm_year + 1900) + "-" +
|
||||||
String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
|
String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" +
|
||||||
String::FormatIntWidth2(time_struct.tm_mday) + "T" +
|
String::FormatIntWidth2(time_struct->tm_mday) + "T" +
|
||||||
String::FormatIntWidth2(time_struct.tm_hour) + ":" +
|
String::FormatIntWidth2(time_struct->tm_hour) + ":" +
|
||||||
String::FormatIntWidth2(time_struct.tm_min) + ":" +
|
String::FormatIntWidth2(time_struct->tm_min) + ":" +
|
||||||
String::FormatIntWidth2(time_struct.tm_sec);
|
String::FormatIntWidth2(time_struct->tm_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
|
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
|
||||||
@@ -3812,7 +3812,7 @@ void UnitTest::AddTestPartResult(
|
|||||||
// with another testing framework) and specify the former on the
|
// with another testing framework) and specify the former on the
|
||||||
// command line for debugging.
|
// command line for debugging.
|
||||||
if (GTEST_FLAG(break_on_failure)) {
|
if (GTEST_FLAG(break_on_failure)) {
|
||||||
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
|
#if GTEST_OS_WINDOWS
|
||||||
// Using DebugBreak on Windows allows gtest to still break into a debugger
|
// Using DebugBreak on Windows allows gtest to still break into a debugger
|
||||||
// when a failure happens and both the --gtest_break_on_failure and
|
// when a failure happens and both the --gtest_break_on_failure and
|
||||||
// the --gtest_catch_exceptions flags are specified.
|
// the --gtest_catch_exceptions flags are specified.
|
||||||
@@ -3890,7 +3890,7 @@ int UnitTest::Run() {
|
|||||||
// process. In either case the user does not want to see pop-up dialogs
|
// process. In either case the user does not want to see pop-up dialogs
|
||||||
// about crashes - they are expected.
|
// about crashes - they are expected.
|
||||||
if (impl()->catch_exceptions() || in_death_test_child_process) {
|
if (impl()->catch_exceptions() || in_death_test_child_process) {
|
||||||
# if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
|
# if !GTEST_OS_WINDOWS_MOBILE
|
||||||
// SetErrorMode doesn't exist on CE.
|
// SetErrorMode doesn't exist on CE.
|
||||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
|
||||||
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
|
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
|
||||||
@@ -3993,10 +3993,17 @@ namespace internal {
|
|||||||
|
|
||||||
UnitTestImpl::UnitTestImpl(UnitTest* parent)
|
UnitTestImpl::UnitTestImpl(UnitTest* parent)
|
||||||
: parent_(parent),
|
: parent_(parent),
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */)
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push) // Saves the current warning state.
|
||||||
|
# pragma warning(disable:4355) // Temporarily disables warning 4355
|
||||||
|
// (using this in initializer).
|
||||||
default_global_test_part_result_reporter_(this),
|
default_global_test_part_result_reporter_(this),
|
||||||
default_per_thread_test_part_result_reporter_(this),
|
default_per_thread_test_part_result_reporter_(this),
|
||||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
# pragma warning(pop) // Restores the warning state again.
|
||||||
|
#else
|
||||||
|
default_global_test_part_result_reporter_(this),
|
||||||
|
default_per_thread_test_part_result_reporter_(this),
|
||||||
|
#endif // _MSC_VER
|
||||||
global_test_part_result_repoter_(
|
global_test_part_result_repoter_(
|
||||||
&default_global_test_part_result_reporter_),
|
&default_global_test_part_result_reporter_),
|
||||||
per_thread_test_part_result_reporter_(
|
per_thread_test_part_result_reporter_(
|
||||||
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 @@
|
|||||||
#Sat Nov 21 18:19:09 EST 2015
|
|
||||||
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-2.8-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
|
||||||
|
|||||||
104
gradlew
vendored
104
gradlew
vendored
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
@@ -6,42 +6,6 @@
|
|||||||
##
|
##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS=""
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=`basename "$0"`
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
||||||
MAX_FD="maximum"
|
|
||||||
|
|
||||||
warn ( ) {
|
|
||||||
echo "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
die ( ) {
|
|
||||||
echo
|
|
||||||
echo "$*"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
|
||||||
cygwin=false
|
|
||||||
msys=false
|
|
||||||
darwin=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN* )
|
|
||||||
cygwin=true
|
|
||||||
;;
|
|
||||||
Darwin* )
|
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
PRG="$0"
|
||||||
@@ -56,9 +20,49 @@ while [ -h "$PRG" ] ; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
SAVED="`pwd`"
|
||||||
cd "`dirname \"$PRG\"`/" >&-
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
APP_HOME="`pwd -P`"
|
APP_HOME="`pwd -P`"
|
||||||
cd "$SAVED" >&-
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
@@ -85,7 +89,7 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
@@ -150,11 +154,19 @@ if $cygwin ; then
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save () {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
14
gradlew.bat
vendored
14
gradlew.bat
vendored
@@ -8,14 +8,14 @@
|
|||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS=
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
@@ -46,10 +46,9 @@ echo location of your Java installation.
|
|||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
:init
|
||||||
@rem Get command-line arguments, handling Windowz variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
@@ -60,11 +59,6 @@ set _SKIP=2
|
|||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
set CMD_LINE_ARGS=%$
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|||||||
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/
|
||||||
|
}
|
||||||
249
hal/build.gradle
249
hal/build.gradle
@@ -1,47 +1,222 @@
|
|||||||
// There are two hal libraries that are built
|
|
||||||
// - Desktop which is used by simulation (gcc/msvc)
|
|
||||||
// - Athena which is used by the roborio (arm)
|
|
||||||
|
|
||||||
apply plugin: 'cpp'
|
apply plugin: 'cpp'
|
||||||
|
apply plugin: 'google-test'
|
||||||
|
apply plugin: 'visual-studio'
|
||||||
|
apply plugin: 'edu.wpi.first.NativeUtils'
|
||||||
|
|
||||||
|
apply from: '../config.gradle'
|
||||||
|
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
model {
|
model {
|
||||||
components {
|
dependencyConfigs {
|
||||||
HALAthena(NativeLibrarySpec) {
|
wpiutil(DependencyConfig) {
|
||||||
targetPlatform 'arm'
|
groupId = 'edu.wpi.first.wpiutil'
|
||||||
tasks.withType(CppCompile) {
|
artifactId = 'wpiutil-cpp'
|
||||||
dependsOn addNiLibraryLinks
|
headerClassifier = 'headers'
|
||||||
}
|
ext = 'zip'
|
||||||
sources {
|
version = '3.+'
|
||||||
cpp {
|
sharedConfigs = [ halAthena: [], halSim: [], halDev: [], halSimTestingBaseTest: [] ]
|
||||||
source {
|
staticConfigs = [ halSimStaticDeps: [] ]
|
||||||
srcDirs = ["lib/Athena", "lib/Athena/FRC_FPGA_ChipObject", "lib/Shared"]
|
}
|
||||||
includes = ["**/*.cpp"]
|
}
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
exportedHeaders {
|
}
|
||||||
srcDirs = ["include", "lib/Athena", "lib/Athena/FRC_FPGA_ChipObject", "lib/Shared"]
|
return retList
|
||||||
|
}
|
||||||
|
x64SymbolFilter = { symbols->
|
||||||
|
def retList = []
|
||||||
|
symbols.each { symbol->
|
||||||
|
if (symbol.startsWith('HAL_')) {
|
||||||
|
retList << symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
components {
|
||||||
|
if (!project.hasProperty('skipAthena')) {
|
||||||
|
halAthena(NativeLibrarySpec) {
|
||||||
|
baseName = 'wpiHal'
|
||||||
|
sources {
|
||||||
|
cpp {
|
||||||
|
source {
|
||||||
|
srcDirs = [ 'src/main/native/shared', 'src/main/native/athena' ]
|
||||||
|
includes = ["**/*.cpp"]
|
||||||
|
}
|
||||||
|
exportedHeaders {
|
||||||
|
srcDirs = ["src/main/native/include"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binaries.all { binary->
|
||||||
|
if (binary.targetPlatform.architecture.name != 'athena') {
|
||||||
|
binary.buildable = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!project.hasProperty('onlyAthena')) {
|
||||||
// HALDesktop(NativeLibrarySpec) {
|
halSim(NativeLibrarySpec) {
|
||||||
// binaries.all {
|
baseName = 'wpiHal'
|
||||||
// if (toolChain in Gcc){
|
sources {
|
||||||
// cppCompiler.args "-std=c++1y"
|
cpp {
|
||||||
// }
|
source {
|
||||||
// }
|
srcDirs = [ 'src/main/native/shared', 'src/main/native/sim' ]
|
||||||
//
|
includes = ["**/*.cpp"]
|
||||||
// sources {
|
}
|
||||||
// cpp {
|
exportedHeaders {
|
||||||
// source {
|
srcDirs = ["src/main/native/include"]
|
||||||
// srcDirs = ["lib/Desktop", "lib/Shared"]
|
}
|
||||||
// includes = ["**/*.cpp"]
|
}
|
||||||
// }
|
}
|
||||||
// exportedHeaders {
|
binaries.all { binary ->
|
||||||
// srcDirs = ["include", "lib/Desktop", "lib/Shared"]
|
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 {
|
||||||
|
halSimTestingBaseTest {
|
||||||
|
sources {
|
||||||
|
cpp.source.srcDir 'src/test/native/cpp'
|
||||||
|
cpp.exportedHeaders.srcDir 'src/test/native/include'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binaries {
|
||||||
|
all {
|
||||||
|
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 {
|
||||||
|
runCpp(Exec) {
|
||||||
|
def found = false
|
||||||
|
$.components.each {
|
||||||
|
if (it in NativeExecutableSpec && it.name == 'halDev') {
|
||||||
|
it.binaries.each {
|
||||||
|
if (!found) {
|
||||||
|
def arch = it.targetPlatform.architecture.name
|
||||||
|
if (arch == 'x86-64' || arch == 'x86') {
|
||||||
|
dependsOn it.tasks.install
|
||||||
|
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'
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
enum AccelerometerRange {
|
|
||||||
kRange_2G = 0,
|
|
||||||
kRange_4G = 1,
|
|
||||||
kRange_8G = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void setAccelerometerActive(bool);
|
|
||||||
void setAccelerometerRange(AccelerometerRange);
|
|
||||||
double getAccelerometerX();
|
|
||||||
double getAccelerometerY();
|
|
||||||
double getAccelerometerZ();
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
enum AnalogTriggerType
|
|
||||||
{
|
|
||||||
kInWindow = 0,
|
|
||||||
kState = 1,
|
|
||||||
kRisingPulse = 2,
|
|
||||||
kFallingPulse = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
// Analog output functions
|
|
||||||
void* initializeAnalogOutputPort(void* port_pointer, int32_t *status);
|
|
||||||
void freeAnalogOutputPort(void* analog_port_pointer);
|
|
||||||
void setAnalogOutput(void* analog_port_pointer, double voltage, int32_t *status);
|
|
||||||
double getAnalogOutput(void* analog_port_pointer, int32_t *status);
|
|
||||||
bool checkAnalogOutputChannel(uint32_t pin);
|
|
||||||
|
|
||||||
// Analog input functions
|
|
||||||
void* initializeAnalogInputPort(void* port_pointer, int32_t *status);
|
|
||||||
void freeAnalogInputPort(void* analog_port_pointer);
|
|
||||||
bool checkAnalogModule(uint8_t module);
|
|
||||||
bool checkAnalogInputChannel(uint32_t pin);
|
|
||||||
|
|
||||||
void setAnalogSampleRate(double samplesPerSecond, int32_t *status);
|
|
||||||
float getAnalogSampleRate(int32_t *status);
|
|
||||||
void setAnalogAverageBits(void* analog_port_pointer, uint32_t bits, int32_t *status);
|
|
||||||
uint32_t getAnalogAverageBits(void* analog_port_pointer, int32_t *status);
|
|
||||||
void setAnalogOversampleBits(void* analog_port_pointer, uint32_t bits, int32_t *status);
|
|
||||||
uint32_t getAnalogOversampleBits(void* analog_port_pointer, int32_t *status);
|
|
||||||
int16_t getAnalogValue(void* analog_port_pointer, int32_t *status);
|
|
||||||
int32_t getAnalogAverageValue(void* analog_port_pointer, int32_t *status);
|
|
||||||
int32_t getAnalogVoltsToValue(void* analog_port_pointer, double voltage, int32_t *status);
|
|
||||||
float getAnalogVoltage(void* analog_port_pointer, int32_t *status);
|
|
||||||
float getAnalogAverageVoltage(void* analog_port_pointer, int32_t *status);
|
|
||||||
uint32_t getAnalogLSBWeight(void* analog_port_pointer, int32_t *status);
|
|
||||||
int32_t getAnalogOffset(void* analog_port_pointer, int32_t *status);
|
|
||||||
|
|
||||||
bool isAccumulatorChannel(void* analog_port_pointer, int32_t *status);
|
|
||||||
void initAccumulator(void* analog_port_pointer, int32_t *status);
|
|
||||||
void resetAccumulator(void* analog_port_pointer, int32_t *status);
|
|
||||||
void setAccumulatorCenter(void* analog_port_pointer, int32_t center, int32_t *status);
|
|
||||||
void setAccumulatorDeadband(void* analog_port_pointer, int32_t deadband, int32_t *status);
|
|
||||||
int64_t getAccumulatorValue(void* analog_port_pointer, int32_t *status);
|
|
||||||
uint32_t getAccumulatorCount(void* analog_port_pointer, int32_t *status);
|
|
||||||
void getAccumulatorOutput(void* analog_port_pointer, int64_t *value, uint32_t *count,
|
|
||||||
int32_t *status);
|
|
||||||
|
|
||||||
void* initializeAnalogTrigger(void* port_pointer, uint32_t *index, int32_t *status);
|
|
||||||
void cleanAnalogTrigger(void* analog_trigger_pointer, int32_t *status);
|
|
||||||
void setAnalogTriggerLimitsRaw(void* analog_trigger_pointer, int32_t lower, int32_t upper,
|
|
||||||
int32_t *status);
|
|
||||||
void setAnalogTriggerLimitsVoltage(void* analog_trigger_pointer, double lower, double upper,
|
|
||||||
int32_t *status);
|
|
||||||
void setAnalogTriggerAveraged(void* analog_trigger_pointer, bool useAveragedValue,
|
|
||||||
int32_t *status);
|
|
||||||
void setAnalogTriggerFiltered(void* analog_trigger_pointer, bool useFilteredValue,
|
|
||||||
int32_t *status);
|
|
||||||
bool getAnalogTriggerInWindow(void* analog_trigger_pointer, int32_t *status);
|
|
||||||
bool getAnalogTriggerTriggerState(void* analog_trigger_pointer, int32_t *status);
|
|
||||||
bool getAnalogTriggerOutput(void* analog_trigger_pointer, AnalogTriggerType type,
|
|
||||||
int32_t *status);
|
|
||||||
|
|
||||||
//// Float JNA Hack
|
|
||||||
// Float
|
|
||||||
int getAnalogSampleRateIntHack(int32_t *status);
|
|
||||||
int getAnalogVoltageIntHack(void* analog_port_pointer, int32_t *status);
|
|
||||||
int getAnalogAverageVoltageIntHack(void* analog_port_pointer, int32_t *status);
|
|
||||||
|
|
||||||
// Doubles
|
|
||||||
void setAnalogSampleRateIntHack(int samplesPerSecond, int32_t *status);
|
|
||||||
int32_t getAnalogVoltsToValueIntHack(void* analog_port_pointer, int voltage, int32_t *status);
|
|
||||||
void setAnalogTriggerLimitsVoltageIntHack(void* analog_trigger_pointer, int lower, int upper,
|
|
||||||
int32_t *status);
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#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,829 +0,0 @@
|
|||||||
/**
|
|
||||||
* @brief CAN TALON SRX driver.
|
|
||||||
*
|
|
||||||
* The TALON SRX is designed to instrument all runtime signals periodically.
|
|
||||||
* The default periods are chosen to support 16 TALONs with 10ms update rate
|
|
||||||
* for control (throttle or setpoint). However these can be overridden with
|
|
||||||
* SetStatusFrameRate. @see SetStatusFrameRate
|
|
||||||
* The getters for these unsolicited signals are auto generated at the bottom
|
|
||||||
* of this module.
|
|
||||||
*
|
|
||||||
* Likewise most control signals are sent periodically using the fire-and-forget
|
|
||||||
* CAN API. The setters for these unsolicited signals are auto generated at the
|
|
||||||
* bottom of this module.
|
|
||||||
*
|
|
||||||
* Signals that are not available in an unsolicited fashion are the Close Loop
|
|
||||||
* gains. For teams that have a single profile for their TALON close loop they
|
|
||||||
* can use either the webpage to configure their TALONs once or set the PIDF,
|
|
||||||
* Izone, CloseLoopRampRate, etc... once in the robot application. These
|
|
||||||
* parameters are saved to flash so once they are loaded in the TALON, they
|
|
||||||
* will persist through power cycles and mode changes.
|
|
||||||
*
|
|
||||||
* For teams that have one or two profiles to switch between, they can use the
|
|
||||||
* same strategy since there are two slots to choose from and the
|
|
||||||
* ProfileSlotSelect is periodically sent in the 10 ms control frame.
|
|
||||||
*
|
|
||||||
* For teams that require changing gains frequently, they can use the soliciting
|
|
||||||
* API to get and set those parameters. Most likely they will only need to set
|
|
||||||
* them in a periodic fashion as a function of what motion the application is
|
|
||||||
* attempting. If this API is used, be mindful of the CAN utilization reported
|
|
||||||
* in the driver station.
|
|
||||||
*
|
|
||||||
* If calling application has used the config routines to configure the
|
|
||||||
* selected feedback sensor, then all positions are measured in floating point
|
|
||||||
* precision rotations. All sensor velocities are specified in floating point
|
|
||||||
* precision RPM.
|
|
||||||
* @see ConfigPotentiometerTurns
|
|
||||||
* @see ConfigEncoderCodesPerRev
|
|
||||||
* HOWEVER, if calling application has not called the config routine for
|
|
||||||
* selected feedback sensor, then all getters/setters for position/velocity use
|
|
||||||
* the native engineering units of the Talon SRX firm (just like in 2015).
|
|
||||||
* Signals explained below.
|
|
||||||
*
|
|
||||||
* Encoder position is measured in encoder edges. Every edge is counted
|
|
||||||
* (similar to roboRIO 4X mode). Analog position is 10 bits, meaning 1024
|
|
||||||
* ticks per rotation (0V => 3.3V). Use SetFeedbackDeviceSelect to select
|
|
||||||
* which sensor type you need. Once you do that you can use GetSensorPosition()
|
|
||||||
* and GetSensorVelocity(). These signals are updated on CANBus every 20ms (by
|
|
||||||
* default). If a relative sensor is selected, you can zero (or change the
|
|
||||||
* current value) using SetSensorPosition.
|
|
||||||
*
|
|
||||||
* Analog Input and quadrature position (and velocity) are also explicitly
|
|
||||||
* reported in GetEncPosition, GetEncVel, GetAnalogInWithOv, GetAnalogInVel.
|
|
||||||
* These signals are available all the time, regardless of what sensor is
|
|
||||||
* selected at a rate of 100ms. This allows easy instrumentation for "in the
|
|
||||||
* pits" checking of all sensors regardless of modeselect. The 100ms rate is
|
|
||||||
* overridable for teams who want to acquire sensor data for processing, not
|
|
||||||
* just instrumentation. Or just select the sensor using
|
|
||||||
* SetFeedbackDeviceSelect to get it at 20ms.
|
|
||||||
*
|
|
||||||
* Velocity is in position ticks / 100ms.
|
|
||||||
*
|
|
||||||
* All output units are in respect to duty cycle (throttle) which is -1023(full
|
|
||||||
* reverse) to +1023 (full forward). This includes demand (which specifies
|
|
||||||
* duty cycle when in duty cycle mode) and rampRamp, which is in throttle units
|
|
||||||
* per 10ms (if nonzero).
|
|
||||||
*
|
|
||||||
* Pos and velocity close loops are calc'd as
|
|
||||||
* err = target - posOrVel.
|
|
||||||
* iErr += err;
|
|
||||||
* if( (IZone!=0) and abs(err) > IZone)
|
|
||||||
* ClearIaccum()
|
|
||||||
* output = P X err + I X iErr + D X dErr + F X target
|
|
||||||
* dErr = err - lastErr
|
|
||||||
* P, I, and D gains are always positive. F can be negative.
|
|
||||||
* Motor direction can be reversed using SetRevMotDuringCloseLoopEn if
|
|
||||||
* sensor and motor are out of phase. Similarly feedback sensor can also be
|
|
||||||
* reversed (multiplied by -1) if you prefer the sensor to be inverted.
|
|
||||||
*
|
|
||||||
* P gain is specified in throttle per error tick. For example, a value of 102
|
|
||||||
* is ~9.9% (which is 102/1023) throttle per 1 ADC unit(10bit) or 1 quadrature
|
|
||||||
* encoder edge depending on selected sensor.
|
|
||||||
*
|
|
||||||
* I gain is specified in throttle per integrated error. For example, a value
|
|
||||||
* of 10 equates to ~0.99% (which is 10/1023) for each accumulated ADC unit
|
|
||||||
* (10 bit) or 1 quadrature encoder edge depending on selected sensor.
|
|
||||||
* Close loop and integral accumulator runs every 1ms.
|
|
||||||
*
|
|
||||||
* D gain is specified in throttle per derivative error. For example a value of
|
|
||||||
* 102 equates to ~9.9% (which is 102/1023) per change of 1 unit (ADC or
|
|
||||||
* encoder) per ms.
|
|
||||||
*
|
|
||||||
* I Zone is specified in the same units as sensor position (ADC units or
|
|
||||||
* quadrature edges). If pos/vel error is outside of this value, the
|
|
||||||
* integrated error will auto-clear...
|
|
||||||
* if( (IZone!=0) and abs(err) > IZone)
|
|
||||||
* ClearIaccum()
|
|
||||||
* ...this is very useful in preventing integral windup and is highly
|
|
||||||
* recommended if using full PID to keep stability low.
|
|
||||||
*
|
|
||||||
* CloseLoopRampRate is in throttle units per 1ms. Set to zero to disable
|
|
||||||
* ramping. Works the same as RampThrottle but only is in effect when a close
|
|
||||||
* loop mode and profile slot is selected.
|
|
||||||
*
|
|
||||||
* auto generated using spreadsheet and wpiclassgen.py
|
|
||||||
* @link https://docs.google.com/spreadsheets/d/1OU_ZV7fZLGYUQ-Uhc8sVAmUmWTlT8XBFYK8lfjg_tac/edit#gid=1766046967
|
|
||||||
*/
|
|
||||||
#ifndef CanTalonSRX_H_
|
|
||||||
#define CanTalonSRX_H_
|
|
||||||
#include "ctre/ctre.h" //BIT Defines + Typedefs, TALON_Control_6_MotProfAddTrajPoint_t
|
|
||||||
#include "ctre/CtreCanNode.h"
|
|
||||||
#include <FRC_NetworkCommunication/CANSessionMux.h> //CAN Comm
|
|
||||||
#include <map>
|
|
||||||
#include <atomic>
|
|
||||||
#include <deque>
|
|
||||||
#include <mutex>
|
|
||||||
class CanTalonSRX : public CtreCanNode {
|
|
||||||
private:
|
|
||||||
// Use this for determining whether the default move constructor has been
|
|
||||||
// called; this prevents us from calling the destructor twice.
|
|
||||||
struct HasBeenMoved {
|
|
||||||
HasBeenMoved(HasBeenMoved &&other) {
|
|
||||||
other.moved = true;
|
|
||||||
moved = false;
|
|
||||||
}
|
|
||||||
HasBeenMoved() = default;
|
|
||||||
std::atomic<bool> moved{false};
|
|
||||||
operator bool() const { return moved; }
|
|
||||||
} m_hasBeenMoved;
|
|
||||||
|
|
||||||
// Vars for opening a CAN stream if caller needs signals that require
|
|
||||||
// soliciting
|
|
||||||
uint32_t _can_h; //!< Session handle for catching response params.
|
|
||||||
int32_t _can_stat; //!< Session handle status.
|
|
||||||
struct tCANStreamMessage _msgBuff[20];
|
|
||||||
static int const kMsgCapacity = 20;
|
|
||||||
typedef std::map<uint32_t, uint32_t> sigs_t;
|
|
||||||
// Catches signal updates that are solicited. Expect this to be very few.
|
|
||||||
sigs_t _sigs;
|
|
||||||
void OpenSessionIfNeedBe();
|
|
||||||
void ProcessStreamMessages();
|
|
||||||
/**
|
|
||||||
* Called in various places to double check we are using the best control
|
|
||||||
* frame. If the Talon firmware is too old, use control 1 framing, which
|
|
||||||
* does not allow setting control signals until robot is enabled. If Talon
|
|
||||||
* firmware can suport control5, use that since that frame can be
|
|
||||||
* transmitted during robot-disable. If calling application uses setParam
|
|
||||||
* to set the signal eLegacyControlMode, caller can force using control1
|
|
||||||
* if needed for some reason.
|
|
||||||
*/
|
|
||||||
void UpdateControlId();
|
|
||||||
/**
|
|
||||||
* @return true if Talon is reporting that it supports control5, and therefore
|
|
||||||
* RIO can send control5 to update control params (even when
|
|
||||||
* disabled).
|
|
||||||
*/
|
|
||||||
bool IsControl5Supported();
|
|
||||||
/**
|
|
||||||
* Get a copy of the control frame to send.
|
|
||||||
* @param [out] pointer to eight byte array to fill.
|
|
||||||
*/
|
|
||||||
void GetControlFrameCopy(uint8_t *toFill);
|
|
||||||
/**
|
|
||||||
* @return the tx task that transmits Control6 (motion profile control).
|
|
||||||
* If it's not scheduled, then schedule it. This is part
|
|
||||||
* of making the lazy-framing that only peforms MotionProf framing
|
|
||||||
* when needed to save bandwidth.
|
|
||||||
*/
|
|
||||||
CtreCanNode::txTask<TALON_Control_6_MotProfAddTrajPoint_t> GetControl6();
|
|
||||||
/**
|
|
||||||
* Caller is either pushing a new motion profile point, or is
|
|
||||||
* calling the Process buffer routine. In either case check our
|
|
||||||
* flow control to see if we need to start sending control6.
|
|
||||||
*/
|
|
||||||
void ReactToMotionProfileCall();
|
|
||||||
/**
|
|
||||||
* Update the NextPt signals inside the control frame given the next pt to
|
|
||||||
* send.
|
|
||||||
* @param control pointer to the CAN frame payload containing control6. Only
|
|
||||||
* the signals that serialize the next trajectory point are
|
|
||||||
* updated from the contents of newPt.
|
|
||||||
* @param newPt point to the next trajectory that needs to be inserted into
|
|
||||||
* Talon RAM.
|
|
||||||
*/
|
|
||||||
void CopyTrajPtIntoControl(
|
|
||||||
TALON_Control_6_MotProfAddTrajPoint_t *control,
|
|
||||||
const TALON_Control_6_MotProfAddTrajPoint_t *newPt);
|
|
||||||
//---------------------- General Control framing ---------------------------//
|
|
||||||
/**
|
|
||||||
* Frame period for control1 or control5, depending on which one we are using.
|
|
||||||
*/
|
|
||||||
int _controlPeriodMs = kDefaultControlPeriodMs;
|
|
||||||
/**
|
|
||||||
* Frame Period of the motion profile control6 frame.
|
|
||||||
*/
|
|
||||||
int _control6PeriodMs = kDefaultControl6PeriodMs;
|
|
||||||
/**
|
|
||||||
* When using control5, we still need to send a frame to enable robot. This
|
|
||||||
* controls the period. This only is used when we are in the control5 state.
|
|
||||||
* @see ControlFrameSelControl5
|
|
||||||
*/
|
|
||||||
int _enablePeriodMs = kDefaultEnablePeriodMs;
|
|
||||||
/**
|
|
||||||
* ArbID to use for control frame. Should be either CONTROL_1 or CONTROL_5.
|
|
||||||
*/
|
|
||||||
uint32_t _controlFrameArbId;
|
|
||||||
/**
|
|
||||||
* Boolean flag to signal calling applications intent to allow using control5
|
|
||||||
* assuming Talon firmware supports it. This can be cleared to force control1
|
|
||||||
* framing.
|
|
||||||
*/
|
|
||||||
bool _useControl5ifSupported = true;
|
|
||||||
//--------------------- Buffering Motion Profile ---------------------------//
|
|
||||||
/**
|
|
||||||
* Top level Buffer for motion profile trajectory buffering.
|
|
||||||
* Basically this buffers up the eight byte CAN frame payloads that are
|
|
||||||
* handshaked into the Talon RAM.
|
|
||||||
* TODO: Should this be moved into a separate header, and if so where
|
|
||||||
* logically should it reside?
|
|
||||||
* TODO: Add compression so that multiple CAN frames can be compressed into
|
|
||||||
* one exchange.
|
|
||||||
*/
|
|
||||||
class TrajectoryBuffer {
|
|
||||||
public:
|
|
||||||
void Clear() { _motProfTopBuffer.clear(); }
|
|
||||||
/**
|
|
||||||
* push caller's uncompressed simple trajectory point.
|
|
||||||
*/
|
|
||||||
void Push(TALON_Control_6_MotProfAddTrajPoint_huff0_t &pt) {
|
|
||||||
_motProfTopBuffer.push_back(pt);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the next trajectory point CAN frame to send.
|
|
||||||
* Underlying layer may compress the next few points together
|
|
||||||
* into one control_6 frame.
|
|
||||||
*/
|
|
||||||
TALON_Control_6_MotProfAddTrajPoint_t *Front() {
|
|
||||||
/* TODO : peek ahead and use compression strategies */
|
|
||||||
_lastFront = _motProfTopBuffer.front();
|
|
||||||
return (TALON_Control_6_MotProfAddTrajPoint_t *)&_lastFront;
|
|
||||||
}
|
|
||||||
void Pop() {
|
|
||||||
/* TODO : pop multiple points if last front'd point was compressed. */
|
|
||||||
_motProfTopBuffer.pop_front();
|
|
||||||
}
|
|
||||||
unsigned int GetNumTrajectories() { return _motProfTopBuffer.size(); }
|
|
||||||
bool IsEmpty() { return _motProfTopBuffer.empty(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::deque<TALON_Control_6_MotProfAddTrajPoint_huff0_t> _motProfTopBuffer;
|
|
||||||
TALON_Control_6_MotProfAddTrajPoint_huff0_t _lastFront;
|
|
||||||
};
|
|
||||||
TrajectoryBuffer _motProfTopBuffer;
|
|
||||||
/**
|
|
||||||
* To keep buffers from getting out of control, place a cap on the top level
|
|
||||||
* buffer. Calling application
|
|
||||||
* can stream addition points as they are fed to Talon.
|
|
||||||
* Approx memory footprint is this capacity X 8 bytes.
|
|
||||||
*/
|
|
||||||
static const int kMotionProfileTopBufferCapacity = 2048;
|
|
||||||
/**
|
|
||||||
* Flow control for streaming trajectories.
|
|
||||||
*/
|
|
||||||
int32_t _motProfFlowControl = -1;
|
|
||||||
/**
|
|
||||||
* Since we may need the MP pts to be emptied into Talon in the background
|
|
||||||
* make sure the buffering is thread-safe.
|
|
||||||
*/
|
|
||||||
std::mutex _mutMotProf;
|
|
||||||
/**
|
|
||||||
* Send a one shot frame to set an arbitrary signal.
|
|
||||||
* Most signals are in the control frame so avoid using this API unless you
|
|
||||||
* have to.
|
|
||||||
* Use this api for...
|
|
||||||
* -A motor controller profile signal eProfileParam_XXXs. These are backed up
|
|
||||||
* in flash. If you are gain-scheduling then call this periodically.
|
|
||||||
* -Default brake and limit switch signals... eOnBoot_XXXs. Avoid doing this,
|
|
||||||
* use the override signals in the control frame.
|
|
||||||
* Talon will automatically send a PARAM_RESPONSE after the set, so
|
|
||||||
* GetParamResponse will catch the latest value after a couple ms.
|
|
||||||
*/
|
|
||||||
CTR_Code SetParamRaw(uint32_t paramEnum, int32_t rawBits);
|
|
||||||
/**
|
|
||||||
* Checks cached CAN frames and updating solicited signals.
|
|
||||||
*/
|
|
||||||
CTR_Code GetParamResponseRaw(uint32_t paramEnum, int32_t &rawBits);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// default control update rate is 10ms.
|
|
||||||
static const int kDefaultControlPeriodMs = 10;
|
|
||||||
// default enable update rate is 50ms (when using the new control5 frame).
|
|
||||||
static const int kDefaultEnablePeriodMs = 50;
|
|
||||||
// Default update rate for motion profile control 6. This only takes effect
|
|
||||||
// when calling uses MP functions.
|
|
||||||
static const int kDefaultControl6PeriodMs = 10;
|
|
||||||
explicit CanTalonSRX(int deviceNumber = 0,
|
|
||||||
int controlPeriodMs = kDefaultControlPeriodMs,
|
|
||||||
int enablePeriodMs = kDefaultEnablePeriodMs);
|
|
||||||
~CanTalonSRX();
|
|
||||||
void Set(double value);
|
|
||||||
/* mode select enumerations */
|
|
||||||
// Demand is 11bit signed duty cycle [-1023,1023].
|
|
||||||
static const int kMode_DutyCycle = 0;
|
|
||||||
// Position PIDF.
|
|
||||||
static const int kMode_PositionCloseLoop = 1;
|
|
||||||
// Velocity PIDF.
|
|
||||||
static const int kMode_VelocityCloseLoop = 2;
|
|
||||||
// Current close loop - not done.
|
|
||||||
static const int kMode_CurrentCloseLoop = 3;
|
|
||||||
// Voltage Compensation Mode - not done. Demand is fixed pt target 8.8 volts.
|
|
||||||
static const int kMode_VoltCompen = 4;
|
|
||||||
// Demand is the 6 bit Device ID of the 'master' TALON SRX.
|
|
||||||
static const int kMode_SlaveFollower = 5;
|
|
||||||
// Demand is '0' (Disabled), '1' (Enabled), or '2' (Hold).
|
|
||||||
static const int kMode_MotionProfile = 6;
|
|
||||||
// Zero the output (honors brake/coast) regardless of demand.
|
|
||||||
// Might be useful if we need to change modes but can't atomically
|
|
||||||
// change all the signals we want in between.
|
|
||||||
static const int kMode_NoDrive = 15;
|
|
||||||
/* limit switch enumerations */
|
|
||||||
static const int kLimitSwitchOverride_UseDefaultsFromFlash = 1;
|
|
||||||
static const int kLimitSwitchOverride_DisableFwd_DisableRev = 4;
|
|
||||||
static const int kLimitSwitchOverride_DisableFwd_EnableRev = 5;
|
|
||||||
static const int kLimitSwitchOverride_EnableFwd_DisableRev = 6;
|
|
||||||
static const int kLimitSwitchOverride_EnableFwd_EnableRev = 7;
|
|
||||||
/* brake override enumerations */
|
|
||||||
static const int kBrakeOverride_UseDefaultsFromFlash = 0;
|
|
||||||
static const int kBrakeOverride_OverrideCoast = 1;
|
|
||||||
static const int kBrakeOverride_OverrideBrake = 2;
|
|
||||||
/* feedback device enumerations */
|
|
||||||
static const int kFeedbackDev_DigitalQuadEnc = 0;
|
|
||||||
static const int kFeedbackDev_AnalogPot = 2;
|
|
||||||
static const int kFeedbackDev_AnalogEncoder = 3;
|
|
||||||
static const int kFeedbackDev_CountEveryRisingEdge = 4;
|
|
||||||
static const int kFeedbackDev_CountEveryFallingEdge = 5;
|
|
||||||
static const int kFeedbackDev_PosIsPulseWidth = 8;
|
|
||||||
/* ProfileSlotSelect enumerations*/
|
|
||||||
static const int kProfileSlotSelect_Slot0 = 0;
|
|
||||||
static const int kProfileSlotSelect_Slot1 = 1;
|
|
||||||
/* status frame rate types */
|
|
||||||
static const int kStatusFrame_General = 0;
|
|
||||||
static const int kStatusFrame_Feedback = 1;
|
|
||||||
static const int kStatusFrame_Encoder = 2;
|
|
||||||
static const int kStatusFrame_AnalogTempVbat = 3;
|
|
||||||
static const int kStatusFrame_PulseWidthMeas = 4;
|
|
||||||
static const int kStatusFrame_MotionProfile = 5;
|
|
||||||
/* Motion Profile status bits */
|
|
||||||
static const int kMotionProfileFlag_ActTraj_IsValid = 0x1;
|
|
||||||
static const int kMotionProfileFlag_HasUnderrun = 0x2;
|
|
||||||
static const int kMotionProfileFlag_IsUnderrun = 0x4;
|
|
||||||
static const int kMotionProfileFlag_ActTraj_IsLast = 0x8;
|
|
||||||
static const int kMotionProfileFlag_ActTraj_VelOnly = 0x10;
|
|
||||||
/* Motion Profile Set Output */
|
|
||||||
// Motor output is neutral, Motion Profile Executer is not running.
|
|
||||||
static const int kMotionProf_Disabled = 0;
|
|
||||||
// Motor output is updated from Motion Profile Executer, MPE will
|
|
||||||
// process the buffered points.
|
|
||||||
static const int kMotionProf_Enable = 1;
|
|
||||||
// Motor output is updated from Motion Profile Executer, MPE will
|
|
||||||
// stay processing current trajectory point.
|
|
||||||
static const int kMotionProf_Hold = 2;
|
|
||||||
/**
|
|
||||||
* Signal enumeration for generic signal access.
|
|
||||||
* Although every signal is enumerated, only use this for traffic that must
|
|
||||||
* be solicited.
|
|
||||||
* Use the auto generated getters/setters at bottom of this header as much as
|
|
||||||
* possible.
|
|
||||||
*/
|
|
||||||
enum param_t {
|
|
||||||
eProfileParamSlot0_P = 1,
|
|
||||||
eProfileParamSlot0_I = 2,
|
|
||||||
eProfileParamSlot0_D = 3,
|
|
||||||
eProfileParamSlot0_F = 4,
|
|
||||||
eProfileParamSlot0_IZone = 5,
|
|
||||||
eProfileParamSlot0_CloseLoopRampRate = 6,
|
|
||||||
eProfileParamSlot1_P = 11,
|
|
||||||
eProfileParamSlot1_I = 12,
|
|
||||||
eProfileParamSlot1_D = 13,
|
|
||||||
eProfileParamSlot1_F = 14,
|
|
||||||
eProfileParamSlot1_IZone = 15,
|
|
||||||
eProfileParamSlot1_CloseLoopRampRate = 16,
|
|
||||||
eProfileParamSoftLimitForThreshold = 21,
|
|
||||||
eProfileParamSoftLimitRevThreshold = 22,
|
|
||||||
eProfileParamSoftLimitForEnable = 23,
|
|
||||||
eProfileParamSoftLimitRevEnable = 24,
|
|
||||||
eOnBoot_BrakeMode = 31,
|
|
||||||
eOnBoot_LimitSwitch_Forward_NormallyClosed = 32,
|
|
||||||
eOnBoot_LimitSwitch_Reverse_NormallyClosed = 33,
|
|
||||||
eOnBoot_LimitSwitch_Forward_Disable = 34,
|
|
||||||
eOnBoot_LimitSwitch_Reverse_Disable = 35,
|
|
||||||
eFault_OverTemp = 41,
|
|
||||||
eFault_UnderVoltage = 42,
|
|
||||||
eFault_ForLim = 43,
|
|
||||||
eFault_RevLim = 44,
|
|
||||||
eFault_HardwareFailure = 45,
|
|
||||||
eFault_ForSoftLim = 46,
|
|
||||||
eFault_RevSoftLim = 47,
|
|
||||||
eStckyFault_OverTemp = 48,
|
|
||||||
eStckyFault_UnderVoltage = 49,
|
|
||||||
eStckyFault_ForLim = 50,
|
|
||||||
eStckyFault_RevLim = 51,
|
|
||||||
eStckyFault_ForSoftLim = 52,
|
|
||||||
eStckyFault_RevSoftLim = 53,
|
|
||||||
eAppliedThrottle = 61,
|
|
||||||
eCloseLoopErr = 62,
|
|
||||||
eFeedbackDeviceSelect = 63,
|
|
||||||
eRevMotDuringCloseLoopEn = 64,
|
|
||||||
eModeSelect = 65,
|
|
||||||
eProfileSlotSelect = 66,
|
|
||||||
eRampThrottle = 67,
|
|
||||||
eRevFeedbackSensor = 68,
|
|
||||||
eLimitSwitchEn = 69,
|
|
||||||
eLimitSwitchClosedFor = 70,
|
|
||||||
eLimitSwitchClosedRev = 71,
|
|
||||||
eSensorPosition = 73,
|
|
||||||
eSensorVelocity = 74,
|
|
||||||
eCurrent = 75,
|
|
||||||
eBrakeIsEnabled = 76,
|
|
||||||
eEncPosition = 77,
|
|
||||||
eEncVel = 78,
|
|
||||||
eEncIndexRiseEvents = 79,
|
|
||||||
eQuadApin = 80,
|
|
||||||
eQuadBpin = 81,
|
|
||||||
eQuadIdxpin = 82,
|
|
||||||
eAnalogInWithOv = 83,
|
|
||||||
eAnalogInVel = 84,
|
|
||||||
eTemp = 85,
|
|
||||||
eBatteryV = 86,
|
|
||||||
eResetCount = 87,
|
|
||||||
eResetFlags = 88,
|
|
||||||
eFirmVers = 89,
|
|
||||||
eSettingsChanged = 90,
|
|
||||||
eQuadFilterEn = 91,
|
|
||||||
ePidIaccum = 93,
|
|
||||||
eStatus1FrameRate = 94, // TALON_Status_1_General_10ms_t
|
|
||||||
eStatus2FrameRate = 95, // TALON_Status_2_Feedback_20ms_t
|
|
||||||
eStatus3FrameRate = 96, // TALON_Status_3_Enc_100ms_t
|
|
||||||
eStatus4FrameRate = 97, // TALON_Status_4_AinTempVbat_100ms_t
|
|
||||||
eStatus6FrameRate = 98, // TALON_Status_6_Eol_t
|
|
||||||
eStatus7FrameRate = 99, // TALON_Status_7_Debug_200ms_t
|
|
||||||
eClearPositionOnIdx = 100,
|
|
||||||
// reserved,
|
|
||||||
// reserved,
|
|
||||||
// reserved,
|
|
||||||
ePeakPosOutput = 104,
|
|
||||||
eNominalPosOutput = 105,
|
|
||||||
ePeakNegOutput = 106,
|
|
||||||
eNominalNegOutput = 107,
|
|
||||||
eQuadIdxPolarity = 108,
|
|
||||||
eStatus8FrameRate = 109, // TALON_Status_8_PulseWid_100ms_t
|
|
||||||
eAllowPosOverflow = 110,
|
|
||||||
eProfileParamSlot0_AllowableClosedLoopErr = 111,
|
|
||||||
eNumberPotTurns = 112,
|
|
||||||
eNumberEncoderCPR = 113,
|
|
||||||
ePwdPosition = 114,
|
|
||||||
eAinPosition = 115,
|
|
||||||
eProfileParamVcompRate = 116,
|
|
||||||
eProfileParamSlot1_AllowableClosedLoopErr = 117,
|
|
||||||
eStatus9FrameRate = 118, // TALON_Status_9_MotProfBuffer_100ms_t
|
|
||||||
eMotionProfileHasUnderrunErr = 119,
|
|
||||||
eReserved120 = 120,
|
|
||||||
eLegacyControlMode = 121,
|
|
||||||
};
|
|
||||||
//---- setters and getters that use the solicated param request/response ---//
|
|
||||||
/**
|
|
||||||
* Send a one shot frame to set an arbitrary signal.
|
|
||||||
* Most signals are in the control frame so avoid using this API unless you
|
|
||||||
* have to.
|
|
||||||
* Use this api for...
|
|
||||||
* -A motor controller profile signal eProfileParam_XXXs. These are backed
|
|
||||||
* up in flash. If you are gain-scheduling then call this periodically.
|
|
||||||
* -Default brake and limit switch signals... eOnBoot_XXXs. Avoid doing
|
|
||||||
* this, use the override signals in the control frame.
|
|
||||||
* Talon will automatically send a PARAM_RESPONSE after the set, so
|
|
||||||
* GetParamResponse will catch the latest value after a couple ms.
|
|
||||||
*/
|
|
||||||
CTR_Code SetParam(param_t paramEnum, double value);
|
|
||||||
/**
|
|
||||||
* Asks TALON to immedietely respond with signal value. This API is only used
|
|
||||||
* for signals that are not sent periodically.
|
|
||||||
* This can be useful for reading params that rarely change like Limit Switch
|
|
||||||
* settings and PIDF values.
|
|
||||||
* @param param to request.
|
|
||||||
*/
|
|
||||||
CTR_Code RequestParam(param_t paramEnum);
|
|
||||||
CTR_Code GetParamResponse(param_t paramEnum, double &value);
|
|
||||||
CTR_Code GetParamResponseInt32(param_t paramEnum, int &value);
|
|
||||||
//----------- getters and setters that use param request/response ----------//
|
|
||||||
/**
|
|
||||||
* These signals are backed up in flash and will survive a power cycle.
|
|
||||||
* If your application requires changing these values consider using both
|
|
||||||
* slots and switch between slot0 <=> slot1.
|
|
||||||
* If your application requires changing these signals frequently then it
|
|
||||||
* makes sense to leverage this API.
|
|
||||||
* Getters don't block, so it may require several calls to get the latest
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
CTR_Code SetPgain(unsigned slotIdx, double gain);
|
|
||||||
CTR_Code SetIgain(unsigned slotIdx, double gain);
|
|
||||||
CTR_Code SetDgain(unsigned slotIdx, double gain);
|
|
||||||
CTR_Code SetFgain(unsigned slotIdx, double gain);
|
|
||||||
CTR_Code SetIzone(unsigned slotIdx, int zone);
|
|
||||||
CTR_Code SetCloseLoopRampRate(unsigned slotIdx, int closeLoopRampRate);
|
|
||||||
CTR_Code SetVoltageCompensationRate(double voltagePerMs);
|
|
||||||
CTR_Code SetSensorPosition(int pos);
|
|
||||||
CTR_Code SetForwardSoftLimit(int forwardLimit);
|
|
||||||
CTR_Code SetReverseSoftLimit(int reverseLimit);
|
|
||||||
CTR_Code SetForwardSoftEnable(int enable);
|
|
||||||
CTR_Code SetReverseSoftEnable(int enable);
|
|
||||||
CTR_Code GetPgain(unsigned slotIdx, double &gain);
|
|
||||||
CTR_Code GetIgain(unsigned slotIdx, double &gain);
|
|
||||||
CTR_Code GetDgain(unsigned slotIdx, double &gain);
|
|
||||||
CTR_Code GetFgain(unsigned slotIdx, double &gain);
|
|
||||||
CTR_Code GetIzone(unsigned slotIdx, int &zone);
|
|
||||||
CTR_Code GetCloseLoopRampRate(unsigned slotIdx, int &closeLoopRampRate);
|
|
||||||
CTR_Code GetVoltageCompensationRate(double &voltagePerMs);
|
|
||||||
CTR_Code GetForwardSoftLimit(int &forwardLimit);
|
|
||||||
CTR_Code GetReverseSoftLimit(int &reverseLimit);
|
|
||||||
CTR_Code GetForwardSoftEnable(int &enable);
|
|
||||||
CTR_Code GetReverseSoftEnable(int &enable);
|
|
||||||
CTR_Code GetPulseWidthRiseToFallUs(int ¶m);
|
|
||||||
CTR_Code IsPulseWidthSensorPresent(int ¶m);
|
|
||||||
CTR_Code SetModeSelect(int modeSelect, int demand);
|
|
||||||
/**
|
|
||||||
* Change the periodMs of a TALON's status frame. See kStatusFrame_* enums
|
|
||||||
* for what's available.
|
|
||||||
*/
|
|
||||||
CTR_Code SetStatusFrameRate(unsigned frameEnum, unsigned periodMs);
|
|
||||||
/**
|
|
||||||
* Clear all sticky faults in TALON.
|
|
||||||
*/
|
|
||||||
CTR_Code ClearStickyFaults();
|
|
||||||
/**
|
|
||||||
* Calling application can opt to speed up the handshaking between the robot
|
|
||||||
* API and the Talon to increase the
|
|
||||||
* download rate of the Talon's Motion Profile. Ideally the period should be
|
|
||||||
* no more than half the period
|
|
||||||
* of a trajectory point.
|
|
||||||
*/
|
|
||||||
void ChangeMotionControlFramePeriod(uint32_t periodMs);
|
|
||||||
/**
|
|
||||||
* Clear the buffered motion profile in both Talon RAM (bottom), and in the
|
|
||||||
* API (top).
|
|
||||||
*/
|
|
||||||
void ClearMotionProfileTrajectories();
|
|
||||||
/**
|
|
||||||
* Retrieve just the buffer count for the api-level (top) buffer.
|
|
||||||
* This routine performs no CAN or data structure lookups, so its fast and
|
|
||||||
* ideal if caller needs to quickly poll the progress of trajectory points
|
|
||||||
* being emptied into Talon's RAM. Otherwise just use GetMotionProfileStatus.
|
|
||||||
* @return number of trajectory points in the top buffer.
|
|
||||||
*/
|
|
||||||
uint32_t GetMotionProfileTopLevelBufferCount();
|
|
||||||
/**
|
|
||||||
* Retrieve just the buffer full for the api-level (top) buffer.
|
|
||||||
* This routine performs no CAN or data structure lookups, so its fast and
|
|
||||||
* ideal if caller needs to quickly poll. Otherwise just use
|
|
||||||
* GetMotionProfileStatus.
|
|
||||||
* @return number of trajectory points in the top buffer.
|
|
||||||
*/
|
|
||||||
bool IsMotionProfileTopLevelBufferFull();
|
|
||||||
/**
|
|
||||||
* Push another trajectory point into the top level buffer (which is emptied
|
|
||||||
* into the Talon's bottom buffer as room allows).
|
|
||||||
* @param targPos servo position in native Talon units (sensor units).
|
|
||||||
* @param targVel velocity to feed-forward in native Talon units (sensor
|
|
||||||
* units per 100ms).
|
|
||||||
* @param profileSlotSelect which slot to pull PIDF gains from. Currently
|
|
||||||
* supports 0 or 1.
|
|
||||||
* @param timeDurMs time in milliseconds of how long to apply this point.
|
|
||||||
* @param velOnly set to nonzero to signal Talon that only the feed-foward
|
|
||||||
* velocity should be used, i.e. do not perform PID on
|
|
||||||
* position. This is equivalent to setting PID gains to zero,
|
|
||||||
* but much more efficient and synchronized to MP.
|
|
||||||
* @param isLastPoint set to nonzero to signal Talon to keep processing this
|
|
||||||
* trajectory point, instead of jumping to the next one
|
|
||||||
* when timeDurMs expires. Otherwise MP executer will
|
|
||||||
* eventually see an empty buffer after the last point
|
|
||||||
* expires, causing it to assert the IsUnderRun flag.
|
|
||||||
* However this may be desired if calling application
|
|
||||||
* nevers wants to terminate the MP.
|
|
||||||
* @param zeroPos set to nonzero to signal Talon to "zero" the selected
|
|
||||||
* position sensor before executing this trajectory point.
|
|
||||||
* Typically the first point should have this set only thus
|
|
||||||
* allowing the remainder of the MP positions to be relative
|
|
||||||
* to zero.
|
|
||||||
* @return CTR_OKAY if trajectory point push ok. CTR_BufferFull if buffer is
|
|
||||||
* full due to kMotionProfileTopBufferCapacity.
|
|
||||||
*/
|
|
||||||
CTR_Code PushMotionProfileTrajectory(int targPos, int targVel,
|
|
||||||
int profileSlotSelect, int timeDurMs,
|
|
||||||
int velOnly, int isLastPoint,
|
|
||||||
int zeroPos);
|
|
||||||
/**
|
|
||||||
* This must be called periodically to funnel the trajectory points from the
|
|
||||||
* API's top level buffer to the Talon's bottom level buffer. Recommendation
|
|
||||||
* is to call this twice as fast as the executation rate of the motion
|
|
||||||
* profile. So if MP is running with 20ms trajectory points, try calling
|
|
||||||
* this routine every 10ms. All motion profile functions are thread-safe
|
|
||||||
* through the use of a mutex, so there is no harm in having the caller
|
|
||||||
* utilize threading.
|
|
||||||
*/
|
|
||||||
void ProcessMotionProfileBuffer();
|
|
||||||
/**
|
|
||||||
* Retrieve all status information.
|
|
||||||
* Since this all comes from one CAN frame, its ideal to have one routine to
|
|
||||||
* retrieve the frame once and decode everything.
|
|
||||||
* @param [out] flags bitfield for status bools. Starting with least
|
|
||||||
* significant bit: IsValid, HasUnderrun, IsUnderrun, IsLast, VelOnly.
|
|
||||||
*
|
|
||||||
* IsValid set when MP executer is processing a trajectory point,
|
|
||||||
* and that point's status is instrumented with IsLast,
|
|
||||||
* VelOnly, targPos, targVel. However if MP executor is
|
|
||||||
* not processing a trajectory point, then this flag is
|
|
||||||
* false, and the instrumented signals will be zero.
|
|
||||||
* HasUnderrun is set anytime the MP executer is ready to pop
|
|
||||||
* another trajectory point from the Talon's RAM,
|
|
||||||
* but the buffer is empty. It can only be cleared
|
|
||||||
* by using SetParam(eMotionProfileHasUnderrunErr,0);
|
|
||||||
* IsUnderrun is set when the MP executer is ready for another
|
|
||||||
* point, but the buffer is empty, and cleared when
|
|
||||||
* the MP executer does not need another point.
|
|
||||||
* HasUnderrun shadows this registor when this
|
|
||||||
* register gets set, however HasUnderrun stays
|
|
||||||
* asserted until application has process it, and
|
|
||||||
* IsUnderrun auto-clears when the condition is
|
|
||||||
* resolved.
|
|
||||||
* IsLast is set/cleared based on the MP executer's current
|
|
||||||
* trajectory point's IsLast value. This assumes
|
|
||||||
* IsLast was set when PushMotionProfileTrajectory
|
|
||||||
* was used to insert the currently processed trajectory
|
|
||||||
* point.
|
|
||||||
* VelOnly is set/cleared based on the MP executer's current
|
|
||||||
* trajectory point's VelOnly value.
|
|
||||||
*
|
|
||||||
* @param [out] profileSlotSelect The currently processed trajectory point's
|
|
||||||
* selected slot. This can differ in the currently selected slot used
|
|
||||||
* for Position and Velocity servo modes.
|
|
||||||
* @param [out] targPos The currently processed trajectory point's position
|
|
||||||
* in native units. This param is zero if IsValid is zero.
|
|
||||||
* @param [out] targVel The currently processed trajectory point's velocity
|
|
||||||
* in native units. This param is zero if IsValid is zero.
|
|
||||||
* @param [out] topBufferRem The remaining number of points in the top level
|
|
||||||
* buffer.
|
|
||||||
* @param [out] topBufferCnt The number of points in the top level buffer to
|
|
||||||
* be sent to Talon.
|
|
||||||
* @param [out] btmBufferCnt The number of points in the bottom level buffer
|
|
||||||
* inside Talon.
|
|
||||||
* @return CTR error code
|
|
||||||
*/
|
|
||||||
CTR_Code GetMotionProfileStatus(uint32_t &flags, uint32_t &profileSlotSelect,
|
|
||||||
int32_t &targPos, int32_t &targVel,
|
|
||||||
uint32_t &topBufferRemaining,
|
|
||||||
uint32_t &topBufferCnt,
|
|
||||||
uint32_t &btmBufferCnt,
|
|
||||||
uint32_t &outputEnable);
|
|
||||||
//------------------------ auto generated ------------------------------------//
|
|
||||||
/* This API is optimal since it uses the fire-and-forget CAN interface.
|
|
||||||
* These signals should cover the majority of all use cases.
|
|
||||||
*/
|
|
||||||
CTR_Code GetFault_OverTemp(int ¶m);
|
|
||||||
CTR_Code GetFault_UnderVoltage(int ¶m);
|
|
||||||
CTR_Code GetFault_ForLim(int ¶m);
|
|
||||||
CTR_Code GetFault_RevLim(int ¶m);
|
|
||||||
CTR_Code GetFault_HardwareFailure(int ¶m);
|
|
||||||
CTR_Code GetFault_ForSoftLim(int ¶m);
|
|
||||||
CTR_Code GetFault_RevSoftLim(int ¶m);
|
|
||||||
CTR_Code GetStckyFault_OverTemp(int ¶m);
|
|
||||||
CTR_Code GetStckyFault_UnderVoltage(int ¶m);
|
|
||||||
CTR_Code GetStckyFault_ForLim(int ¶m);
|
|
||||||
CTR_Code GetStckyFault_RevLim(int ¶m);
|
|
||||||
CTR_Code GetStckyFault_ForSoftLim(int ¶m);
|
|
||||||
CTR_Code GetStckyFault_RevSoftLim(int ¶m);
|
|
||||||
CTR_Code GetAppliedThrottle(int ¶m);
|
|
||||||
CTR_Code GetCloseLoopErr(int ¶m);
|
|
||||||
CTR_Code GetFeedbackDeviceSelect(int ¶m);
|
|
||||||
CTR_Code GetModeSelect(int ¶m);
|
|
||||||
CTR_Code GetLimitSwitchEn(int ¶m);
|
|
||||||
CTR_Code GetLimitSwitchClosedFor(int ¶m);
|
|
||||||
CTR_Code GetLimitSwitchClosedRev(int ¶m);
|
|
||||||
CTR_Code GetSensorPosition(int ¶m);
|
|
||||||
CTR_Code GetSensorVelocity(int ¶m);
|
|
||||||
CTR_Code GetCurrent(double ¶m);
|
|
||||||
CTR_Code GetBrakeIsEnabled(int ¶m);
|
|
||||||
CTR_Code GetEncPosition(int ¶m);
|
|
||||||
CTR_Code GetEncVel(int ¶m);
|
|
||||||
CTR_Code GetEncIndexRiseEvents(int ¶m);
|
|
||||||
CTR_Code GetQuadApin(int ¶m);
|
|
||||||
CTR_Code GetQuadBpin(int ¶m);
|
|
||||||
CTR_Code GetQuadIdxpin(int ¶m);
|
|
||||||
CTR_Code GetAnalogInWithOv(int ¶m);
|
|
||||||
CTR_Code GetAnalogInVel(int ¶m);
|
|
||||||
CTR_Code GetTemp(double ¶m);
|
|
||||||
CTR_Code GetBatteryV(double ¶m);
|
|
||||||
CTR_Code GetResetCount(int ¶m);
|
|
||||||
CTR_Code GetResetFlags(int ¶m);
|
|
||||||
CTR_Code GetFirmVers(int ¶m);
|
|
||||||
CTR_Code GetPulseWidthPosition(int ¶m);
|
|
||||||
CTR_Code GetPulseWidthVelocity(int ¶m);
|
|
||||||
CTR_Code GetPulseWidthRiseToRiseUs(int ¶m);
|
|
||||||
CTR_Code GetActTraj_IsValid(int ¶m);
|
|
||||||
CTR_Code GetActTraj_ProfileSlotSelect(int ¶m);
|
|
||||||
CTR_Code GetActTraj_VelOnly(int ¶m);
|
|
||||||
CTR_Code GetActTraj_IsLast(int ¶m);
|
|
||||||
CTR_Code GetOutputType(int ¶m);
|
|
||||||
CTR_Code GetHasUnderrun(int ¶m);
|
|
||||||
CTR_Code GetIsUnderrun(int ¶m);
|
|
||||||
CTR_Code GetNextID(int ¶m);
|
|
||||||
CTR_Code GetBufferIsFull(int ¶m);
|
|
||||||
CTR_Code GetCount(int ¶m);
|
|
||||||
CTR_Code GetActTraj_Velocity(int ¶m);
|
|
||||||
CTR_Code GetActTraj_Position(int ¶m);
|
|
||||||
CTR_Code SetDemand(int param);
|
|
||||||
CTR_Code SetOverrideLimitSwitchEn(int param);
|
|
||||||
CTR_Code SetFeedbackDeviceSelect(int param);
|
|
||||||
CTR_Code SetRevMotDuringCloseLoopEn(int param);
|
|
||||||
CTR_Code SetOverrideBrakeType(int param);
|
|
||||||
CTR_Code SetModeSelect(int param);
|
|
||||||
CTR_Code SetProfileSlotSelect(int param);
|
|
||||||
CTR_Code SetRampThrottle(int param);
|
|
||||||
CTR_Code SetRevFeedbackSensor(int param);
|
|
||||||
};
|
|
||||||
extern "C" {
|
|
||||||
void *c_TalonSRX_Create3(int deviceNumber, int controlPeriodMs, int enablePeriodMs);
|
|
||||||
void *c_TalonSRX_Create2(int deviceNumber, int controlPeriodMs);
|
|
||||||
void *c_TalonSRX_Create1(int deviceNumber);
|
|
||||||
void c_TalonSRX_Destroy(void *handle);
|
|
||||||
void c_TalonSRX_Set(void *handle, double value);
|
|
||||||
CTR_Code c_TalonSRX_SetParam(void *handle, int paramEnum, double value);
|
|
||||||
CTR_Code c_TalonSRX_RequestParam(void *handle, int paramEnum);
|
|
||||||
CTR_Code c_TalonSRX_GetParamResponse(void *handle, int paramEnum, double *value);
|
|
||||||
CTR_Code c_TalonSRX_GetParamResponseInt32(void *handle, int paramEnum, int *value);
|
|
||||||
CTR_Code c_TalonSRX_SetPgain(void *handle, int slotIdx, double gain);
|
|
||||||
CTR_Code c_TalonSRX_SetIgain(void *handle, int slotIdx, double gain);
|
|
||||||
CTR_Code c_TalonSRX_SetDgain(void *handle, int slotIdx, double gain);
|
|
||||||
CTR_Code c_TalonSRX_SetFgain(void *handle, int slotIdx, double gain);
|
|
||||||
CTR_Code c_TalonSRX_SetIzone(void *handle, int slotIdx, int zone);
|
|
||||||
CTR_Code c_TalonSRX_SetCloseLoopRampRate(void *handle, int slotIdx, int closeLoopRampRate);
|
|
||||||
CTR_Code c_TalonSRX_SetVoltageCompensationRate(void *handle, double voltagePerMs);
|
|
||||||
CTR_Code c_TalonSRX_SetSensorPosition(void *handle, int pos);
|
|
||||||
CTR_Code c_TalonSRX_SetForwardSoftLimit(void *handle, int forwardLimit);
|
|
||||||
CTR_Code c_TalonSRX_SetReverseSoftLimit(void *handle, int reverseLimit);
|
|
||||||
CTR_Code c_TalonSRX_SetForwardSoftEnable(void *handle, int enable);
|
|
||||||
CTR_Code c_TalonSRX_SetReverseSoftEnable(void *handle, int enable);
|
|
||||||
CTR_Code c_TalonSRX_GetPgain(void *handle, int slotIdx, double *gain);
|
|
||||||
CTR_Code c_TalonSRX_GetIgain(void *handle, int slotIdx, double *gain);
|
|
||||||
CTR_Code c_TalonSRX_GetDgain(void *handle, int slotIdx, double *gain);
|
|
||||||
CTR_Code c_TalonSRX_GetFgain(void *handle, int slotIdx, double *gain);
|
|
||||||
CTR_Code c_TalonSRX_GetIzone(void *handle, int slotIdx, int *zone);
|
|
||||||
CTR_Code c_TalonSRX_GetCloseLoopRampRate(void *handle, int slotIdx, int *closeLoopRampRate);
|
|
||||||
CTR_Code c_TalonSRX_GetVoltageCompensationRate(void *handle, double *voltagePerMs);
|
|
||||||
CTR_Code c_TalonSRX_GetForwardSoftLimit(void *handle, int *forwardLimit);
|
|
||||||
CTR_Code c_TalonSRX_GetReverseSoftLimit(void *handle, int *reverseLimit);
|
|
||||||
CTR_Code c_TalonSRX_GetForwardSoftEnable(void *handle, int *enable);
|
|
||||||
CTR_Code c_TalonSRX_GetReverseSoftEnable(void *handle, int *enable);
|
|
||||||
CTR_Code c_TalonSRX_GetPulseWidthRiseToFallUs(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_IsPulseWidthSensorPresent(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_SetModeSelect2(void *handle, int modeSelect, int demand);
|
|
||||||
CTR_Code c_TalonSRX_SetStatusFrameRate(void *handle, int frameEnum, int periodMs);
|
|
||||||
CTR_Code c_TalonSRX_ClearStickyFaults(void *handle);
|
|
||||||
void c_TalonSRX_ChangeMotionControlFramePeriod(void *handle, int periodMs);
|
|
||||||
void c_TalonSRX_ClearMotionProfileTrajectories(void *handle);
|
|
||||||
int c_TalonSRX_GetMotionProfileTopLevelBufferCount(void *handle);
|
|
||||||
int c_TalonSRX_IsMotionProfileTopLevelBufferFull(void *handle);
|
|
||||||
CTR_Code c_TalonSRX_PushMotionProfileTrajectory(void *handle, int targPos, int targVel, int profileSlotSelect, int timeDurMs, int velOnly, int isLastPoint, int zeroPos);
|
|
||||||
void c_TalonSRX_ProcessMotionProfileBuffer(void *handle);
|
|
||||||
CTR_Code c_TalonSRX_GetMotionProfileStatus(void *handle, int *flags, int *profileSlotSelect, int *targPos, int *targVel, int *topBufferRemaining, int *topBufferCnt, int *btmBufferCnt, int *outputEnable);
|
|
||||||
CTR_Code c_TalonSRX_GetFault_OverTemp(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFault_UnderVoltage(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFault_ForLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFault_RevLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFault_HardwareFailure(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFault_ForSoftLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFault_RevSoftLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetStckyFault_OverTemp(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetStckyFault_UnderVoltage(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetStckyFault_ForLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetStckyFault_RevLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetStckyFault_ForSoftLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetStckyFault_RevSoftLim(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetAppliedThrottle(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetCloseLoopErr(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFeedbackDeviceSelect(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetModeSelect(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetLimitSwitchEn(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetLimitSwitchClosedFor(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetLimitSwitchClosedRev(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetSensorPosition(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetSensorVelocity(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetCurrent(void *handle, double *param);
|
|
||||||
CTR_Code c_TalonSRX_GetBrakeIsEnabled(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetEncPosition(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetEncVel(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetEncIndexRiseEvents(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetQuadApin(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetQuadBpin(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetQuadIdxpin(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetAnalogInWithOv(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetAnalogInVel(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetTemp(void *handle, double *param);
|
|
||||||
CTR_Code c_TalonSRX_GetBatteryV(void *handle, double *param);
|
|
||||||
CTR_Code c_TalonSRX_GetResetCount(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetResetFlags(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetFirmVers(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetPulseWidthPosition(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetPulseWidthVelocity(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetPulseWidthRiseToRiseUs(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetActTraj_IsValid(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetActTraj_ProfileSlotSelect(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetActTraj_VelOnly(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetActTraj_IsLast(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetOutputType(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetHasUnderrun(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetIsUnderrun(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetNextID(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetBufferIsFull(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetCount(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetActTraj_Velocity(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_GetActTraj_Position(void *handle, int *param);
|
|
||||||
CTR_Code c_TalonSRX_SetDemand(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetOverrideLimitSwitchEn(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetFeedbackDeviceSelect(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetRevMotDuringCloseLoopEn(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetOverrideBrakeType(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetModeSelect(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetProfileSlotSelect(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetRampThrottle(void *handle, int param);
|
|
||||||
CTR_Code c_TalonSRX_SetRevFeedbackSensor(void *handle, int param);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
* Compressor.h
|
|
||||||
* Methods for interacting with a compressor with the CAN PCM device
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifndef __HAL_COMPRESSOR_H__
|
|
||||||
#define __HAL_COMPRESSOR_H__
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void *initializeCompressor(uint8_t module);
|
|
||||||
bool checkCompressorModule(uint8_t module);
|
|
||||||
|
|
||||||
bool getCompressor(void *pcm_pointer, int32_t *status);
|
|
||||||
|
|
||||||
void setClosedLoopControl(void *pcm_pointer, bool value, int32_t *status);
|
|
||||||
bool getClosedLoopControl(void *pcm_pointer, int32_t *status);
|
|
||||||
|
|
||||||
bool getPressureSwitch(void *pcm_pointer, int32_t *status);
|
|
||||||
float getCompressorCurrent(void *pcm_pointer, int32_t *status);
|
|
||||||
|
|
||||||
bool getCompressorCurrentTooHighFault(void *pcm_pointer, int32_t *status);
|
|
||||||
bool getCompressorCurrentTooHighStickyFault(void *pcm_pointer, int32_t *status);
|
|
||||||
bool getCompressorShortedStickyFault(void *pcm_pointer, int32_t *status);
|
|
||||||
bool getCompressorShortedFault(void *pcm_pointer, int32_t *status);
|
|
||||||
bool getCompressorNotConnectedStickyFault(void *pcm_pointer, int32_t *status);
|
|
||||||
bool getCompressorNotConnectedFault(void *pcm_pointer, int32_t *status);
|
|
||||||
void clearAllPCMStickyFaults(void *pcm_pointer, int32_t *status);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "HAL/cpp/priority_mutex.h"
|
|
||||||
|
|
||||||
enum Mode
|
|
||||||
{
|
|
||||||
kTwoPulse = 0,
|
|
||||||
kSemiperiod = 1,
|
|
||||||
kPulseLength = 2,
|
|
||||||
kExternalDirection = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
priority_recursive_mutex& spiGetSemaphore(uint8_t port);
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
void* initializeDigitalPort(void* port_pointer, int32_t *status);
|
|
||||||
void freeDigitalPort(void* digital_port_pointer);
|
|
||||||
bool checkPWMChannel(void* digital_port_pointer);
|
|
||||||
bool checkRelayChannel(void* digital_port_pointer);
|
|
||||||
|
|
||||||
void setPWM(void* digital_port_pointer, unsigned short value, int32_t *status);
|
|
||||||
bool allocatePWMChannel(void* digital_port_pointer, int32_t *status);
|
|
||||||
void freePWMChannel(void* digital_port_pointer, int32_t *status);
|
|
||||||
unsigned short getPWM(void* digital_port_pointer, int32_t *status);
|
|
||||||
void latchPWMZero(void* digital_port_pointer, int32_t *status);
|
|
||||||
void setPWMPeriodScale(void* digital_port_pointer, uint32_t squelchMask, int32_t *status);
|
|
||||||
void* allocatePWM(int32_t *status);
|
|
||||||
void freePWM(void* pwmGenerator, int32_t *status);
|
|
||||||
void setPWMRate(double rate, int32_t *status);
|
|
||||||
void setPWMDutyCycle(void* pwmGenerator, double dutyCycle, int32_t *status);
|
|
||||||
void setPWMOutputChannel(void* pwmGenerator, uint32_t pin, int32_t *status);
|
|
||||||
|
|
||||||
void setRelayForward(void* digital_port_pointer, bool on, int32_t *status);
|
|
||||||
void setRelayReverse(void* digital_port_pointer, bool on, int32_t *status);
|
|
||||||
bool getRelayForward(void* digital_port_pointer, int32_t *status);
|
|
||||||
bool getRelayReverse(void* digital_port_pointer, int32_t *status);
|
|
||||||
|
|
||||||
bool allocateDIO(void* digital_port_pointer, bool input, int32_t *status);
|
|
||||||
void freeDIO(void* digital_port_pointer, int32_t *status);
|
|
||||||
void setDIO(void* digital_port_pointer, short value, int32_t *status);
|
|
||||||
bool getDIO(void* digital_port_pointer, int32_t *status);
|
|
||||||
bool getDIODirection(void* digital_port_pointer, int32_t *status);
|
|
||||||
void pulse(void* digital_port_pointer, double pulseLength, int32_t *status);
|
|
||||||
bool isPulsing(void* digital_port_pointer, int32_t *status);
|
|
||||||
bool isAnyPulsing(int32_t *status);
|
|
||||||
|
|
||||||
void setFilterSelect(void* digital_port_pointer, int filter_index,
|
|
||||||
int32_t* status);
|
|
||||||
int getFilterSelect(void* digital_port_pointer, int32_t* status);
|
|
||||||
|
|
||||||
void setFilterPeriod(int filter_index, uint32_t value, int32_t* status);
|
|
||||||
uint32_t getFilterPeriod(int filter_index, int32_t* status);
|
|
||||||
|
|
||||||
void* initializeCounter(Mode mode, uint32_t *index, int32_t *status);
|
|
||||||
void freeCounter(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterAverageSize(void* counter_pointer, int32_t size, int32_t *status);
|
|
||||||
void setCounterUpSource(void* counter_pointer, uint32_t pin, bool analogTrigger, int32_t *status);
|
|
||||||
void setCounterUpSourceEdge(void* counter_pointer, bool risingEdge, bool fallingEdge,
|
|
||||||
int32_t *status);
|
|
||||||
void clearCounterUpSource(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterDownSource(void* counter_pointer, uint32_t pin, bool analogTrigger, int32_t *status);
|
|
||||||
void setCounterDownSourceEdge(void* counter_pointer, bool risingEdge, bool fallingEdge,
|
|
||||||
int32_t *status);
|
|
||||||
void clearCounterDownSource(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterUpDownMode(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterExternalDirectionMode(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterSemiPeriodMode(void* counter_pointer, bool highSemiPeriod, int32_t *status);
|
|
||||||
void setCounterPulseLengthMode(void* counter_pointer, double threshold, int32_t *status);
|
|
||||||
int32_t getCounterSamplesToAverage(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterSamplesToAverage(void* counter_pointer, int samplesToAverage, int32_t *status);
|
|
||||||
void resetCounter(void* counter_pointer, int32_t *status);
|
|
||||||
int32_t getCounter(void* counter_pointer, int32_t *status);
|
|
||||||
double getCounterPeriod(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterMaxPeriod(void* counter_pointer, double maxPeriod, int32_t *status);
|
|
||||||
void setCounterUpdateWhenEmpty(void* counter_pointer, bool enabled, int32_t *status);
|
|
||||||
bool getCounterStopped(void* counter_pointer, int32_t *status);
|
|
||||||
bool getCounterDirection(void* counter_pointer, int32_t *status);
|
|
||||||
void setCounterReverseDirection(void* counter_pointer, bool reverseDirection, int32_t *status);
|
|
||||||
|
|
||||||
void* initializeEncoder(uint8_t port_a_module, uint32_t port_a_pin, bool port_a_analog_trigger,
|
|
||||||
uint8_t port_b_module, uint32_t port_b_pin, bool port_b_analog_trigger,
|
|
||||||
bool reverseDirection, int32_t *index, int32_t *status); // TODO: fix routing
|
|
||||||
void freeEncoder(void* encoder_pointer, int32_t *status);
|
|
||||||
void resetEncoder(void* encoder_pointer, int32_t *status);
|
|
||||||
int32_t getEncoder(void* encoder_pointer, int32_t *status); // Raw value
|
|
||||||
double getEncoderPeriod(void* encoder_pointer, int32_t *status);
|
|
||||||
void setEncoderMaxPeriod(void* encoder_pointer, double maxPeriod, int32_t *status);
|
|
||||||
bool getEncoderStopped(void* encoder_pointer, int32_t *status);
|
|
||||||
bool getEncoderDirection(void* encoder_pointer, int32_t *status);
|
|
||||||
void setEncoderReverseDirection(void* encoder_pointer, bool reverseDirection, int32_t *status);
|
|
||||||
void setEncoderSamplesToAverage(void* encoder_pointer, uint32_t samplesToAverage,
|
|
||||||
int32_t *status);
|
|
||||||
uint32_t getEncoderSamplesToAverage(void* encoder_pointer, int32_t *status);
|
|
||||||
void setEncoderIndexSource(void *encoder_pointer, uint32_t pin, bool analogTrigger, bool activeHigh,
|
|
||||||
bool edgeSensitive, int32_t *status);
|
|
||||||
|
|
||||||
uint16_t getLoopTiming(int32_t *status);
|
|
||||||
|
|
||||||
void spiInitialize(uint8_t port, int32_t *status);
|
|
||||||
int32_t spiTransaction(uint8_t port, uint8_t *dataToSend, uint8_t *dataReceived, uint8_t size);
|
|
||||||
int32_t spiWrite(uint8_t port, uint8_t* dataToSend, uint8_t sendSize);
|
|
||||||
int32_t spiRead(uint8_t port, uint8_t *buffer, uint8_t count);
|
|
||||||
void spiClose(uint8_t port);
|
|
||||||
void spiSetSpeed(uint8_t port, uint32_t speed);
|
|
||||||
void spiSetOpts(uint8_t port, int msb_first, int sample_on_trailing, int clk_idle_high);
|
|
||||||
void spiSetChipSelectActiveHigh(uint8_t port, int32_t *status);
|
|
||||||
void spiSetChipSelectActiveLow(uint8_t port, int32_t *status);
|
|
||||||
int32_t spiGetHandle(uint8_t port);
|
|
||||||
void spiSetHandle(uint8_t port, int32_t handle);
|
|
||||||
|
|
||||||
void spiInitAccumulator(uint8_t port, uint32_t period, uint32_t cmd,
|
|
||||||
uint8_t xfer_size, uint32_t valid_mask,
|
|
||||||
uint32_t valid_value, uint8_t data_shift,
|
|
||||||
uint8_t data_size, bool is_signed, bool big_endian,
|
|
||||||
int32_t *status);
|
|
||||||
void spiFreeAccumulator(uint8_t port, int32_t *status);
|
|
||||||
void spiResetAccumulator(uint8_t port, int32_t *status);
|
|
||||||
void spiSetAccumulatorCenter(uint8_t port, int32_t center, int32_t *status);
|
|
||||||
void spiSetAccumulatorDeadband(uint8_t port, int32_t deadband, int32_t *status);
|
|
||||||
int32_t spiGetAccumulatorLastValue(uint8_t port, int32_t *status);
|
|
||||||
int64_t spiGetAccumulatorValue(uint8_t port, int32_t *status);
|
|
||||||
uint32_t spiGetAccumulatorCount(uint8_t port, int32_t *status);
|
|
||||||
double spiGetAccumulatorAverage(uint8_t port, int32_t *status);
|
|
||||||
void spiGetAccumulatorOutput(uint8_t port, int64_t *value, uint32_t *count,
|
|
||||||
int32_t *status);
|
|
||||||
|
|
||||||
void i2CInitialize(uint8_t port, int32_t *status);
|
|
||||||
int32_t i2CTransaction(uint8_t port, uint8_t deviceAddress, uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceived, uint8_t receiveSize);
|
|
||||||
int32_t i2CWrite(uint8_t port, uint8_t deviceAddress, uint8_t *dataToSend, uint8_t sendSize);
|
|
||||||
int32_t i2CRead(uint8_t port, uint8_t deviceAddress, uint8_t *buffer, uint8_t count);
|
|
||||||
void i2CClose(uint8_t port);
|
|
||||||
|
|
||||||
//// Float JNA Hack
|
|
||||||
// double
|
|
||||||
void setPWMRateIntHack(int rate, int32_t *status);
|
|
||||||
void setPWMDutyCycleIntHack(void* pwmGenerator, int32_t dutyCycle, int32_t *status);
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define CTR_RxTimeout_MESSAGE "CTRE CAN Recieve Timeout"
|
|
||||||
#define CTR_TxTimeout_MESSAGE "CTRE CAN Transmit Timeout"
|
|
||||||
#define CTR_InvalidParamValue_MESSAGE "CTRE CAN Invalid Parameter"
|
|
||||||
#define CTR_UnexpectedArbId_MESSAGE "CTRE Unexpected Arbitration ID (CAN Node ID)"
|
|
||||||
#define CTR_TxFailed_MESSAGE "CTRE CAN Transmit Error"
|
|
||||||
#define CTR_SigNotUpdated_MESSAGE "CTRE CAN Signal Not Updated"
|
|
||||||
|
|
||||||
#define NiFpga_Status_FifoTimeout_MESSAGE "NIFPGA: FIFO timeout error"
|
|
||||||
#define NiFpga_Status_TransferAborted_MESSAGE "NIFPGA: Transfer aborted error"
|
|
||||||
#define NiFpga_Status_MemoryFull_MESSAGE "NIFPGA: Memory Allocation failed, memory full"
|
|
||||||
#define NiFpga_Status_SoftwareFault_MESSAGE "NIFPGA: Unexepected software error"
|
|
||||||
#define NiFpga_Status_InvalidParameter_MESSAGE "NIFPGA: Invalid Parameter"
|
|
||||||
#define NiFpga_Status_ResourceNotFound_MESSAGE "NIFPGA: Resource not found"
|
|
||||||
#define NiFpga_Status_ResourceNotInitialized_MESSAGE "NIFPGA: Resource not initialized"
|
|
||||||
#define NiFpga_Status_HardwareFault_MESSAGE "NIFPGA: Hardware Fault"
|
|
||||||
#define NiFpga_Status_IrqTimeout_MESSAGE "NIFPGA: Interrupt timeout"
|
|
||||||
|
|
||||||
#define ERR_CANSessionMux_InvalidBuffer_MESSAGE "CAN: Invalid Buffer"
|
|
||||||
#define ERR_CANSessionMux_MessageNotFound_MESSAGE "CAN: Message not found"
|
|
||||||
#define WARN_CANSessionMux_NoToken_MESSAGE "CAN: No token"
|
|
||||||
#define ERR_CANSessionMux_NotAllowed_MESSAGE "CAN: Not allowed"
|
|
||||||
#define ERR_CANSessionMux_NotInitialized_MESSAGE "CAN: Not initialized"
|
|
||||||
|
|
||||||
#define SAMPLE_RATE_TOO_HIGH 1001
|
|
||||||
#define SAMPLE_RATE_TOO_HIGH_MESSAGE "HAL: Analog module sample rate is too high"
|
|
||||||
#define VOLTAGE_OUT_OF_RANGE 1002
|
|
||||||
#define VOLTAGE_OUT_OF_RANGE_MESSAGE "HAL: Voltage to convert to raw value is out of range [0; 5]"
|
|
||||||
#define LOOP_TIMING_ERROR 1004
|
|
||||||
#define LOOP_TIMING_ERROR_MESSAGE "HAL: Digital module loop timing is not the expected value"
|
|
||||||
#define SPI_WRITE_NO_MOSI 1012
|
|
||||||
#define SPI_WRITE_NO_MOSI_MESSAGE "HAL: Cannot write to SPI port with no MOSI output"
|
|
||||||
#define SPI_READ_NO_MISO 1013
|
|
||||||
#define SPI_READ_NO_MISO_MESSAGE "HAL: Cannot read from SPI port with no MISO input"
|
|
||||||
#define SPI_READ_NO_DATA 1014
|
|
||||||
#define SPI_READ_NO_DATA_MESSAGE "HAL: No data available to read from SPI"
|
|
||||||
#define INCOMPATIBLE_STATE 1015
|
|
||||||
#define INCOMPATIBLE_STATE_MESSAGE "HAL: Incompatible State: The operation cannot be completed"
|
|
||||||
#define NO_AVAILABLE_RESOURCES -1004
|
|
||||||
#define NO_AVAILABLE_RESOURCES_MESSAGE "HAL: No available resources to allocate"
|
|
||||||
#define NULL_PARAMETER -1005
|
|
||||||
#define NULL_PARAMETER_MESSAGE "HAL: A pointer parameter to a method is NULL"
|
|
||||||
#define ANALOG_TRIGGER_LIMIT_ORDER_ERROR -1010
|
|
||||||
#define ANALOG_TRIGGER_LIMIT_ORDER_ERROR_MESSAGE "HAL: AnalogTrigger limits error. Lower limit > Upper Limit"
|
|
||||||
#define ANALOG_TRIGGER_PULSE_OUTPUT_ERROR -1011
|
|
||||||
#define ANALOG_TRIGGER_PULSE_OUTPUT_ERROR_MESSAGE "HAL: Attempted to read AnalogTrigger pulse output."
|
|
||||||
#define PARAMETER_OUT_OF_RANGE -1028
|
|
||||||
#define PARAMETER_OUT_OF_RANGE_MESSAGE "HAL: A parameter is out of range."
|
|
||||||
#define RESOURCE_IS_ALLOCATED -1029
|
|
||||||
#define RESOURCE_IS_ALLOCATED_MESSAGE "HAL: Resource already allocated"
|
|
||||||
|
|
||||||
#define VI_ERROR_SYSTEM_ERROR_MESSAGE "HAL - VISA: System Error";
|
|
||||||
#define VI_ERROR_INV_OBJECT_MESSAGE "HAL - VISA: Invalid Object"
|
|
||||||
#define VI_ERROR_RSRC_LOCKED_MESSAGE "HAL - VISA: Resource Locked"
|
|
||||||
#define VI_ERROR_RSRC_NFOUND_MESSAGE "HAL - VISA: Resource Not Found"
|
|
||||||
#define VI_ERROR_INV_RSRC_NAME_MESSAGE "HAL - VISA: Invalid Resource Name"
|
|
||||||
#define VI_ERROR_QUEUE_OVERFLOW_MESSAGE "HAL - VISA: Queue Overflow"
|
|
||||||
#define VI_ERROR_IO_MESSAGE "HAL - VISA: General IO Error"
|
|
||||||
#define VI_ERROR_ASRL_PARITY_MESSAGE "HAL - VISA: Parity Error"
|
|
||||||
#define VI_ERROR_ASRL_FRAMING_MESSAGE "HAL - VISA: Framing Error"
|
|
||||||
#define VI_ERROR_ASRL_OVERRUN_MESSAGE "HAL - VISA: Buffer Overrun Error"
|
|
||||||
#define VI_ERROR_RSRC_BUSY_MESSAGE "HAL - VISA: Resource Busy"
|
|
||||||
#define VI_ERROR_INV_PARAMETER_MESSAGE "HAL - VISA: Invalid Parameter"
|
|
||||||
@@ -1,271 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Copyright (c) FIRST 2013. 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 $(WIND_BASE)/WPILib. */
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "Accelerometer.hpp"
|
|
||||||
#include "Analog.hpp"
|
|
||||||
#include "Compressor.hpp"
|
|
||||||
#include "Digital.hpp"
|
|
||||||
#include "Solenoid.hpp"
|
|
||||||
#include "Notifier.hpp"
|
|
||||||
#include "Interrupts.hpp"
|
|
||||||
#include "Errors.hpp"
|
|
||||||
#include "PDP.hpp"
|
|
||||||
#include "Power.hpp"
|
|
||||||
#include "SerialPort.hpp"
|
|
||||||
|
|
||||||
#include "Utilities.hpp"
|
|
||||||
#include "Semaphore.hpp"
|
|
||||||
#include "Task.hpp"
|
|
||||||
|
|
||||||
#define HAL_IO_CONFIG_DATA_SIZE 32
|
|
||||||
#define HAL_SYS_STATUS_DATA_SIZE 44
|
|
||||||
#define HAL_USER_STATUS_DATA_SIZE (984 - HAL_IO_CONFIG_DATA_SIZE - HAL_SYS_STATUS_DATA_SIZE)
|
|
||||||
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Input 17
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Output 18
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Header 19
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra1 20
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices1 21
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Extra2 22
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Vertices2 23
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Joystick 24
|
|
||||||
#define HALFRC_NetworkCommunication_DynamicType_Kinect_Custom 25
|
|
||||||
|
|
||||||
namespace HALUsageReporting
|
|
||||||
{
|
|
||||||
enum tResourceType
|
|
||||||
{
|
|
||||||
kResourceType_Controller,
|
|
||||||
kResourceType_Module,
|
|
||||||
kResourceType_Language,
|
|
||||||
kResourceType_CANPlugin,
|
|
||||||
kResourceType_Accelerometer,
|
|
||||||
kResourceType_ADXL345,
|
|
||||||
kResourceType_AnalogChannel,
|
|
||||||
kResourceType_AnalogTrigger,
|
|
||||||
kResourceType_AnalogTriggerOutput,
|
|
||||||
kResourceType_CANJaguar,
|
|
||||||
kResourceType_Compressor,
|
|
||||||
kResourceType_Counter,
|
|
||||||
kResourceType_Dashboard,
|
|
||||||
kResourceType_DigitalInput,
|
|
||||||
kResourceType_DigitalOutput,
|
|
||||||
kResourceType_DriverStationCIO,
|
|
||||||
kResourceType_DriverStationEIO,
|
|
||||||
kResourceType_DriverStationLCD,
|
|
||||||
kResourceType_Encoder,
|
|
||||||
kResourceType_GearTooth,
|
|
||||||
kResourceType_Gyro,
|
|
||||||
kResourceType_I2C,
|
|
||||||
kResourceType_Framework,
|
|
||||||
kResourceType_Jaguar,
|
|
||||||
kResourceType_Joystick,
|
|
||||||
kResourceType_Kinect,
|
|
||||||
kResourceType_KinectStick,
|
|
||||||
kResourceType_PIDController,
|
|
||||||
kResourceType_Preferences,
|
|
||||||
kResourceType_PWM,
|
|
||||||
kResourceType_Relay,
|
|
||||||
kResourceType_RobotDrive,
|
|
||||||
kResourceType_SerialPort,
|
|
||||||
kResourceType_Servo,
|
|
||||||
kResourceType_Solenoid,
|
|
||||||
kResourceType_SPI,
|
|
||||||
kResourceType_Task,
|
|
||||||
kResourceType_Ultrasonic,
|
|
||||||
kResourceType_Victor,
|
|
||||||
kResourceType_Button,
|
|
||||||
kResourceType_Command,
|
|
||||||
kResourceType_AxisCamera,
|
|
||||||
kResourceType_PCVideoServer,
|
|
||||||
kResourceType_SmartDashboard,
|
|
||||||
kResourceType_Talon,
|
|
||||||
kResourceType_HiTechnicColorSensor,
|
|
||||||
kResourceType_HiTechnicAccel,
|
|
||||||
kResourceType_HiTechnicCompass,
|
|
||||||
kResourceType_SRF08,
|
|
||||||
kResourceType_AnalogOutput,
|
|
||||||
kResourceType_VictorSP,
|
|
||||||
kResourceType_TalonSRX,
|
|
||||||
kResourceType_CANTalonSRX,
|
|
||||||
kResourceType_ADXL362,
|
|
||||||
kResourceType_ADXRS450,
|
|
||||||
kResourceType_RevSPARK,
|
|
||||||
kResourceType_MindsensorsSD540,
|
|
||||||
kResourceType_DigitalFilter,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum tInstances
|
|
||||||
{
|
|
||||||
kLanguage_LabVIEW = 1,
|
|
||||||
kLanguage_CPlusPlus = 2,
|
|
||||||
kLanguage_Java = 3,
|
|
||||||
kLanguage_Python = 4,
|
|
||||||
|
|
||||||
kCANPlugin_BlackJagBridge = 1,
|
|
||||||
kCANPlugin_2CAN = 2,
|
|
||||||
|
|
||||||
kFramework_Iterative = 1,
|
|
||||||
kFramework_Sample = 2,
|
|
||||||
kFramework_CommandControl = 3,
|
|
||||||
|
|
||||||
kRobotDrive_ArcadeStandard = 1,
|
|
||||||
kRobotDrive_ArcadeButtonSpin = 2,
|
|
||||||
kRobotDrive_ArcadeRatioCurve = 3,
|
|
||||||
kRobotDrive_Tank = 4,
|
|
||||||
kRobotDrive_MecanumPolar = 5,
|
|
||||||
kRobotDrive_MecanumCartesian = 6,
|
|
||||||
|
|
||||||
kDriverStationCIO_Analog = 1,
|
|
||||||
kDriverStationCIO_DigitalIn = 2,
|
|
||||||
kDriverStationCIO_DigitalOut = 3,
|
|
||||||
|
|
||||||
kDriverStationEIO_Acceleration = 1,
|
|
||||||
kDriverStationEIO_AnalogIn = 2,
|
|
||||||
kDriverStationEIO_AnalogOut = 3,
|
|
||||||
kDriverStationEIO_Button = 4,
|
|
||||||
kDriverStationEIO_LED = 5,
|
|
||||||
kDriverStationEIO_DigitalIn = 6,
|
|
||||||
kDriverStationEIO_DigitalOut = 7,
|
|
||||||
kDriverStationEIO_FixedDigitalOut = 8,
|
|
||||||
kDriverStationEIO_PWM = 9,
|
|
||||||
kDriverStationEIO_Encoder = 10,
|
|
||||||
kDriverStationEIO_TouchSlider = 11,
|
|
||||||
|
|
||||||
kADXL345_SPI = 1,
|
|
||||||
kADXL345_I2C = 2,
|
|
||||||
|
|
||||||
kCommand_Scheduler = 1,
|
|
||||||
|
|
||||||
kSmartDashboard_Instance = 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HALControlWord {
|
|
||||||
uint32_t enabled : 1;
|
|
||||||
uint32_t autonomous : 1;
|
|
||||||
uint32_t test :1;
|
|
||||||
uint32_t eStop : 1;
|
|
||||||
uint32_t fmsAttached:1;
|
|
||||||
uint32_t dsAttached:1;
|
|
||||||
uint32_t control_reserved : 26;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum HALAllianceStationID {
|
|
||||||
kHALAllianceStationID_red1,
|
|
||||||
kHALAllianceStationID_red2,
|
|
||||||
kHALAllianceStationID_red3,
|
|
||||||
kHALAllianceStationID_blue1,
|
|
||||||
kHALAllianceStationID_blue2,
|
|
||||||
kHALAllianceStationID_blue3,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The maximum number of axes that will be stored in a single HALJoystickAxes
|
|
||||||
struct. This is used for allocating buffers, not bounds checking, since
|
|
||||||
there are usually less axes in practice. */
|
|
||||||
static const size_t kMaxJoystickAxes = 12;
|
|
||||||
static const size_t kMaxJoystickPOVs = 12;
|
|
||||||
|
|
||||||
struct HALJoystickAxes {
|
|
||||||
uint16_t count;
|
|
||||||
int16_t axes[kMaxJoystickAxes];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HALJoystickPOVs {
|
|
||||||
uint16_t count;
|
|
||||||
int16_t povs[kMaxJoystickPOVs];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HALJoystickButtons {
|
|
||||||
uint32_t buttons;
|
|
||||||
uint8_t count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HALJoystickDescriptor {
|
|
||||||
uint8_t isXbox;
|
|
||||||
uint8_t type;
|
|
||||||
char name[256];
|
|
||||||
uint8_t axisCount;
|
|
||||||
uint8_t axisTypes[kMaxJoystickAxes];
|
|
||||||
uint8_t buttonCount;
|
|
||||||
uint8_t povCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline float intToFloat(int value)
|
|
||||||
{
|
|
||||||
return (float)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int floatToInt(float value)
|
|
||||||
{
|
|
||||||
return round(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
extern const uint32_t dio_kNumSystems;
|
|
||||||
extern const uint32_t solenoid_kNumDO7_0Elements;
|
|
||||||
extern const uint32_t interrupt_kNumSystems;
|
|
||||||
extern const uint32_t kSystemClockTicksPerMicrosecond;
|
|
||||||
|
|
||||||
void* getPort(uint8_t pin);
|
|
||||||
void* getPortWithModule(uint8_t module, uint8_t pin);
|
|
||||||
void freePort(void* port);
|
|
||||||
const char* getHALErrorMessage(int32_t code);
|
|
||||||
|
|
||||||
uint16_t getFPGAVersion(int32_t *status);
|
|
||||||
uint32_t getFPGARevision(int32_t *status);
|
|
||||||
uint64_t getFPGATime(int32_t *status);
|
|
||||||
|
|
||||||
bool getFPGAButton(int32_t *status);
|
|
||||||
|
|
||||||
int HALSetErrorData(const char *errors, int errorsLength, int wait_ms);
|
|
||||||
int HALSendError(int isError, int32_t errorCode, int isLVCode,
|
|
||||||
const char *details, const char *location, const char *callStack,
|
|
||||||
int printMsg);
|
|
||||||
|
|
||||||
int HALGetControlWord(HALControlWord *data);
|
|
||||||
int HALGetAllianceStation(enum HALAllianceStationID *allianceStation);
|
|
||||||
int HALGetJoystickAxes(uint8_t joystickNum, HALJoystickAxes *axes);
|
|
||||||
int HALGetJoystickPOVs(uint8_t joystickNum, HALJoystickPOVs *povs);
|
|
||||||
int HALGetJoystickButtons(uint8_t joystickNum, HALJoystickButtons *buttons);
|
|
||||||
int HALGetJoystickDescriptor(uint8_t joystickNum, HALJoystickDescriptor *desc);
|
|
||||||
int HALGetJoystickIsXbox(uint8_t joystickNum);
|
|
||||||
int HALGetJoystickType(uint8_t joystickNum);
|
|
||||||
char* HALGetJoystickName(uint8_t joystickNum);
|
|
||||||
int HALGetJoystickAxisType(uint8_t joystickNum, uint8_t axis);
|
|
||||||
int HALSetJoystickOutputs(uint8_t joystickNum, uint32_t outputs, uint16_t leftRumble, uint16_t rightRumble);
|
|
||||||
int HALGetMatchTime(float *matchTime);
|
|
||||||
|
|
||||||
void HALSetNewDataSem(MULTIWAIT_ID sem);
|
|
||||||
|
|
||||||
bool HALGetSystemActive(int32_t *status);
|
|
||||||
bool HALGetBrownedOut(int32_t *status);
|
|
||||||
|
|
||||||
int HALInitialize(int mode = 0);
|
|
||||||
void HALNetworkCommunicationObserveUserProgramStarting();
|
|
||||||
void HALNetworkCommunicationObserveUserProgramDisabled();
|
|
||||||
void HALNetworkCommunicationObserveUserProgramAutonomous();
|
|
||||||
void HALNetworkCommunicationObserveUserProgramTeleop();
|
|
||||||
void HALNetworkCommunicationObserveUserProgramTest();
|
|
||||||
|
|
||||||
uint32_t HALReport(uint8_t resource, uint8_t instanceNumber, uint8_t context = 0,
|
|
||||||
const char *feature = NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: HACKS for now...
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
|
|
||||||
void NumericArrayResize();
|
|
||||||
void RTSetCleanupProc();
|
|
||||||
void EDVR_CreateReference();
|
|
||||||
void Occur();
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include "errno.h"
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
typedef void (*InterruptHandlerFunction)(uint32_t interruptAssertedMask, void *param);
|
|
||||||
|
|
||||||
void* initializeInterrupts(uint32_t interruptIndex, bool watcher, int32_t *status);
|
|
||||||
void cleanInterrupts(void* interrupt_pointer, int32_t *status);
|
|
||||||
|
|
||||||
uint32_t waitForInterrupt(void* interrupt_pointer, double timeout, bool ignorePrevious, int32_t *status);
|
|
||||||
void enableInterrupts(void* interrupt_pointer, int32_t *status);
|
|
||||||
void disableInterrupts(void* interrupt_pointer, int32_t *status);
|
|
||||||
double readRisingTimestamp(void* interrupt_pointer, int32_t *status);
|
|
||||||
double readFallingTimestamp(void* interrupt_pointer, int32_t *status);
|
|
||||||
void requestInterrupts(void* interrupt_pointer, uint8_t routing_module, uint32_t routing_pin,
|
|
||||||
bool routing_analog_trigger, int32_t *status);
|
|
||||||
void attachInterruptHandler(void* interrupt_pointer, InterruptHandlerFunction handler,
|
|
||||||
void* param, int32_t *status);
|
|
||||||
void setInterruptUpSourceEdge(void* interrupt_pointer, bool risingEdge, bool fallingEdge,
|
|
||||||
int32_t *status);
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
void* initializeNotifier(void (*process)(uint64_t, void*), void* param, int32_t *status);
|
|
||||||
void cleanNotifier(void* notifier_pointer, int32_t *status);
|
|
||||||
void* getNotifierParam(void* notifier_pointer, int32_t *status);
|
|
||||||
void updateNotifierAlarm(void* notifier_pointer, uint64_t triggerTime, int32_t *status);
|
|
||||||
void stopNotifierAlarm(void* notifier_pointer, int32_t *status);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
void initializePDP(uint8_t module);
|
|
||||||
double getPDPTemperature(uint8_t module, int32_t *status);
|
|
||||||
double getPDPVoltage(uint8_t module, int32_t *status);
|
|
||||||
double getPDPChannelCurrent(uint8_t module, uint8_t channel, int32_t *status);
|
|
||||||
double getPDPTotalCurrent(uint8_t module, int32_t *status);
|
|
||||||
double getPDPTotalPower(uint8_t module, int32_t *status);
|
|
||||||
double getPDPTotalEnergy(uint8_t module, int32_t *status);
|
|
||||||
void resetPDPTotalEnergy(uint8_t module, int32_t *status);
|
|
||||||
void clearPDPStickyFaults(uint8_t module, int32_t *status);
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user