From 03aedfd6724c6b263063682906102b8fcac91aa1 Mon Sep 17 00:00:00 2001 From: valentina-kustikova Date: Thu, 15 Feb 2018 10:09:51 +0300 Subject: [PATCH 01/16] lab1 sample --- KustikovaVD/lab1/include/tstack.h | 10 +++ KustikovaVD/lab1/sample/main.cpp | 7 ++ .../lab1/sln/sample/library/library.vcxproj | 80 +++++++++++++++++ .../sample/library/library.vcxproj.filters | 23 +++++ KustikovaVD/lab1/sln/sample/sample.sln | 29 ++++++ .../lab1/sln/sample/sample/sample.vcxproj | 88 +++++++++++++++++++ .../sln/sample/sample/sample.vcxproj.filters | 14 +++ KustikovaVD/lab1/src/tstack.cpp | 0 8 files changed, 251 insertions(+) create mode 100644 KustikovaVD/lab1/include/tstack.h create mode 100644 KustikovaVD/lab1/sample/main.cpp create mode 100644 KustikovaVD/lab1/sln/sample/library/library.vcxproj create mode 100644 KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters create mode 100644 KustikovaVD/lab1/sln/sample/sample.sln create mode 100644 KustikovaVD/lab1/sln/sample/sample/sample.vcxproj create mode 100644 KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters create mode 100644 KustikovaVD/lab1/src/tstack.cpp diff --git a/KustikovaVD/lab1/include/tstack.h b/KustikovaVD/lab1/include/tstack.h new file mode 100644 index 000000000..6f26683ed --- /dev/null +++ b/KustikovaVD/lab1/include/tstack.h @@ -0,0 +1,10 @@ +#ifndef CLASSSAMPLE_H +#define CLASSSAMPLE_H + +struct Node +{ + int key; + Node* pNext; +}; + +#endif diff --git a/KustikovaVD/lab1/sample/main.cpp b/KustikovaVD/lab1/sample/main.cpp new file mode 100644 index 000000000..17ad1cb49 --- /dev/null +++ b/KustikovaVD/lab1/sample/main.cpp @@ -0,0 +1,7 @@ +#include "tstack.h" + +int main() +{ + Node* n; + return 0; +} diff --git a/KustikovaVD/lab1/sln/sample/library/library.vcxproj b/KustikovaVD/lab1/sln/sample/library/library.vcxproj new file mode 100644 index 000000000..4d1ae8cc1 --- /dev/null +++ b/KustikovaVD/lab1/sln/sample/library/library.vcxproj @@ -0,0 +1,80 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + {A5813F0D-39E4-4CAC-A38E-8FD694C6E687} + Win32Proj + library + + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters b/KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters new file mode 100644 index 000000000..00608379f --- /dev/null +++ b/KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/KustikovaVD/lab1/sln/sample/sample.sln b/KustikovaVD/lab1/sln/sample/sample.sln new file mode 100644 index 000000000..cab1f4292 --- /dev/null +++ b/KustikovaVD/lab1/sln/sample/sample.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample\sample.vcxproj", "{38AF47B5-5FAA-4951-B929-EE62D627A2BF}" + ProjectSection(ProjectDependencies) = postProject + {A5813F0D-39E4-4CAC-A38E-8FD694C6E687} = {A5813F0D-39E4-4CAC-A38E-8FD694C6E687} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "library\library.vcxproj", "{A5813F0D-39E4-4CAC-A38E-8FD694C6E687}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Debug|Win32.ActiveCfg = Debug|Win32 + {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Debug|Win32.Build.0 = Debug|Win32 + {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Release|Win32.ActiveCfg = Release|Win32 + {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Release|Win32.Build.0 = Release|Win32 + {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Debug|Win32.ActiveCfg = Debug|Win32 + {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Debug|Win32.Build.0 = Debug|Win32 + {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Release|Win32.ActiveCfg = Release|Win32 + {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj b/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj new file mode 100644 index 000000000..e353c82b8 --- /dev/null +++ b/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {38AF47B5-5FAA-4951-B929-EE62D627A2BF} + Win32Proj + sample + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../../include + + + Console + true + library.lib;%(AdditionalDependencies) + ../Debug + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../../include + + + Console + true + true + true + library.lib;%(AdditionalDependencies) + ../Release + + + + + + + + + \ No newline at end of file diff --git a/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters b/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters new file mode 100644 index 000000000..e887328dd --- /dev/null +++ b/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/KustikovaVD/lab1/src/tstack.cpp b/KustikovaVD/lab1/src/tstack.cpp new file mode 100644 index 000000000..e69de29bb From f308877870491930cc3cd49e9fd101e4de444e88 Mon Sep 17 00:00:00 2001 From: valentina-kustikova Date: Fri, 16 Feb 2018 16:08:52 +0300 Subject: [PATCH 02/16] Sample --- KorolevAP/lab1/build/lab1/lab1.sln | 29 ++++++ KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj | 90 +++++++++++++++++++ .../lab1/build/lab1/lab1/lab1.vcxproj.filters | 14 +++ .../lab1/build/lab1/library/library.vcxproj | 86 ++++++++++++++++++ .../lab1/library/library.vcxproj.filters | 29 ++++++ KorolevAP/lab1/include/tlink.h | 9 ++ KorolevAP/lab1/include/tlist.h | 0 KorolevAP/lab1/include/tstack.h | 0 KorolevAP/lab1/sample/main.cpp | 7 ++ KorolevAP/lab1/src/tlink.cpp | 1 + 10 files changed, 265 insertions(+) create mode 100644 KorolevAP/lab1/build/lab1/lab1.sln create mode 100644 KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj create mode 100644 KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters create mode 100644 KorolevAP/lab1/build/lab1/library/library.vcxproj create mode 100644 KorolevAP/lab1/build/lab1/library/library.vcxproj.filters create mode 100644 KorolevAP/lab1/include/tlink.h create mode 100644 KorolevAP/lab1/include/tlist.h create mode 100644 KorolevAP/lab1/include/tstack.h create mode 100644 KorolevAP/lab1/sample/main.cpp create mode 100644 KorolevAP/lab1/src/tlink.cpp diff --git a/KorolevAP/lab1/build/lab1/lab1.sln b/KorolevAP/lab1/build/lab1/lab1.sln new file mode 100644 index 000000000..96588ef80 --- /dev/null +++ b/KorolevAP/lab1/build/lab1/lab1.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lab1", "lab1\lab1.vcxproj", "{B111E032-5082-4BC7-92E5-EA2B89A99884}" + ProjectSection(ProjectDependencies) = postProject + {7A1A924A-8268-416C-B8BB-107468B92BF4} = {7A1A924A-8268-416C-B8BB-107468B92BF4} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "library\library.vcxproj", "{7A1A924A-8268-416C-B8BB-107468B92BF4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B111E032-5082-4BC7-92E5-EA2B89A99884}.Debug|Win32.ActiveCfg = Debug|Win32 + {B111E032-5082-4BC7-92E5-EA2B89A99884}.Debug|Win32.Build.0 = Debug|Win32 + {B111E032-5082-4BC7-92E5-EA2B89A99884}.Release|Win32.ActiveCfg = Release|Win32 + {B111E032-5082-4BC7-92E5-EA2B89A99884}.Release|Win32.Build.0 = Release|Win32 + {7A1A924A-8268-416C-B8BB-107468B92BF4}.Debug|Win32.ActiveCfg = Debug|Win32 + {7A1A924A-8268-416C-B8BB-107468B92BF4}.Debug|Win32.Build.0 = Debug|Win32 + {7A1A924A-8268-416C-B8BB-107468B92BF4}.Release|Win32.ActiveCfg = Release|Win32 + {7A1A924A-8268-416C-B8BB-107468B92BF4}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj b/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj new file mode 100644 index 000000000..e0711ab42 --- /dev/null +++ b/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj @@ -0,0 +1,90 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {B111E032-5082-4BC7-92E5-EA2B89A99884} + Win32Proj + lab1 + + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../../include + + + Console + true + library.lib;%(AdditionalDependencies) + ../Debug + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ../../../include + + + Console + true + true + true + library.lib;%(AdditionalDependencies) + ../Release + + + + + + + + + \ No newline at end of file diff --git a/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters b/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters new file mode 100644 index 000000000..e887328dd --- /dev/null +++ b/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/KorolevAP/lab1/build/lab1/library/library.vcxproj b/KorolevAP/lab1/build/lab1/library/library.vcxproj new file mode 100644 index 000000000..140d149af --- /dev/null +++ b/KorolevAP/lab1/build/lab1/library/library.vcxproj @@ -0,0 +1,86 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + {7A1A924A-8268-416C-B8BB-107468B92BF4} + Win32Proj + library + + + + StaticLibrary + true + v110 + Unicode + + + StaticLibrary + false + v110 + true + Unicode + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ../../../include + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ../../../include + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/KorolevAP/lab1/build/lab1/library/library.vcxproj.filters b/KorolevAP/lab1/build/lab1/library/library.vcxproj.filters new file mode 100644 index 000000000..67ea62a30 --- /dev/null +++ b/KorolevAP/lab1/build/lab1/library/library.vcxproj.filters @@ -0,0 +1,29 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/KorolevAP/lab1/include/tlink.h b/KorolevAP/lab1/include/tlink.h new file mode 100644 index 000000000..735a23faf --- /dev/null +++ b/KorolevAP/lab1/include/tlink.h @@ -0,0 +1,9 @@ +#pragma once + +template +class TLink +{ +public: + T data; + TLink* pNext; +}; diff --git a/KorolevAP/lab1/include/tlist.h b/KorolevAP/lab1/include/tlist.h new file mode 100644 index 000000000..e69de29bb diff --git a/KorolevAP/lab1/include/tstack.h b/KorolevAP/lab1/include/tstack.h new file mode 100644 index 000000000..e69de29bb diff --git a/KorolevAP/lab1/sample/main.cpp b/KorolevAP/lab1/sample/main.cpp new file mode 100644 index 000000000..386acef56 --- /dev/null +++ b/KorolevAP/lab1/sample/main.cpp @@ -0,0 +1,7 @@ +#include "tlink.h" + +int main() +{ + TLink link; + return 0; +} diff --git a/KorolevAP/lab1/src/tlink.cpp b/KorolevAP/lab1/src/tlink.cpp new file mode 100644 index 000000000..9353c50e5 --- /dev/null +++ b/KorolevAP/lab1/src/tlink.cpp @@ -0,0 +1 @@ +#include "tlink.h" From 636b3349b2c380528277efa5643ce1a513208c77 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Wed, 28 Feb 2018 22:08:01 +0300 Subject: [PATCH 03/16] lab structure --- VihrevIB/lab1/gtest/gtest-all.cc | 9592 ++++++++ VihrevIB/lab1/gtest/gtest.h | 20063 ++++++++++++++++ VihrevIB/lab1/include/desktop.ini | 4 + VihrevIB/lab1/include/list.h | 0 VihrevIB/lab1/include/monom.h | 0 VihrevIB/lab1/include/node.h | 0 VihrevIB/lab1/include/polinom.h | 1 + VihrevIB/lab1/samples/main_polinom.cpp | 5 + VihrevIB/lab1/sln/polinom/polinom.sln | 61 + .../lab1/sln/polinom/polinom/polinom.vcxproj | 159 + .../polinom/polinom/polinom.vcxproj.filters | 23 + .../polinom/polinom_lib/polinom_lib.vcxproj | 160 + .../polinom_lib/polinom_lib.vcxproj.filters | 27 + .../polinom/polinom_test/polinom_test.vcxproj | 162 + .../polinom_test/polinom_test.vcxproj.filters | 17 + .../sample_polinom/sample_polinom.vcxproj | 161 + .../sample_polinom.vcxproj.filters | 14 + VihrevIB/lab1/src/list.cpp | 5 + VihrevIB/lab1/src/monom.cpp | 4 + VihrevIB/lab1/src/node.cpp | 4 + VihrevIB/lab1/src/polinom.cpp | 5 + VihrevIB/lab1/test/test_main.cpp | 6 + VihrevIB/lab1/test/test_polinom.cpp | 4 + 23 files changed, 30477 insertions(+) create mode 100644 VihrevIB/lab1/gtest/gtest-all.cc create mode 100644 VihrevIB/lab1/gtest/gtest.h create mode 100644 VihrevIB/lab1/include/desktop.ini create mode 100644 VihrevIB/lab1/include/list.h create mode 100644 VihrevIB/lab1/include/monom.h create mode 100644 VihrevIB/lab1/include/node.h create mode 100644 VihrevIB/lab1/include/polinom.h create mode 100644 VihrevIB/lab1/samples/main_polinom.cpp create mode 100644 VihrevIB/lab1/sln/polinom/polinom.sln create mode 100644 VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj create mode 100644 VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj.filters create mode 100644 VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj create mode 100644 VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj.filters create mode 100644 VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj create mode 100644 VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters create mode 100644 VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj create mode 100644 VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj.filters create mode 100644 VihrevIB/lab1/src/list.cpp create mode 100644 VihrevIB/lab1/src/monom.cpp create mode 100644 VihrevIB/lab1/src/node.cpp create mode 100644 VihrevIB/lab1/src/polinom.cpp create mode 100644 VihrevIB/lab1/test/test_main.cpp create mode 100644 VihrevIB/lab1/test/test_polinom.cpp diff --git a/VihrevIB/lab1/gtest/gtest-all.cc b/VihrevIB/lab1/gtest/gtest-all.cc new file mode 100644 index 000000000..ff9e51235 --- /dev/null +++ b/VihrevIB/lab1/gtest/gtest-all.cc @@ -0,0 +1,9592 @@ +// 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: mheule@google.com (Markus Heule) +// +// Google C++ Testing Framework (Google Test) +// +// Sometimes it's desirable to build Google Test by compiling a single file. +// This file serves this purpose. + +// This line ensures that gtest.h can be compiled on its own, even +// when it's fused. +#include "gtest.h" + +// The following lines pull in the real gtest *.cc files. +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) + +// 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) +// +// Utilities for testing Google Test itself and code that uses Google Test +// (e.g. frameworks built on top of Google Test). + +#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + + +namespace testing { + +// This helper class can be used to mock out Google Test failure reporting +// so that we can test Google Test or code that builds on Google Test. +// +// An object of this class appends a TestPartResult object to the +// TestPartResultArray object given in the constructor whenever a Google Test +// failure is reported. It can either intercept only failures that are +// generated in the same thread that created this object or it can intercept +// all generated failures. The scope of this mock object can be controlled with +// the second argument to the two arguments constructor. +class GTEST_API_ ScopedFakeTestPartResultReporter + : public TestPartResultReporterInterface { + public: + // The two possible mocking modes of this object. + enum InterceptMode { + INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. + INTERCEPT_ALL_THREADS // Intercepts all failures. + }; + + // The c'tor sets this object as the test part result reporter used + // by Google Test. The 'result' parameter specifies where to report the + // results. This reporter will only catch failures generated in the current + // thread. DEPRECATED + explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); + + // Same as above, but you can choose the interception scope of this object. + ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, + TestPartResultArray* result); + + // The d'tor restores the previous test part result reporter. + virtual ~ScopedFakeTestPartResultReporter(); + + // Appends the TestPartResult object to the TestPartResultArray + // received in the constructor. + // + // This method is from the TestPartResultReporterInterface + // interface. + virtual void ReportTestPartResult(const TestPartResult& result); + private: + void Init(); + + const InterceptMode intercept_mode_; + TestPartResultReporterInterface* old_reporter_; + TestPartResultArray* const result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); +}; + +namespace internal { + +// A helper class for implementing EXPECT_FATAL_FAILURE() and +// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +class GTEST_API_ SingleFailureChecker { + public: + // The constructor remembers the arguments. + SingleFailureChecker(const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr); + ~SingleFailureChecker(); + private: + const TestPartResultArray* const results_; + const TestPartResult::Type type_; + const string substr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); +}; + +} // namespace internal + +} // namespace testing + +// A set of macros for testing Google Test assertions or code that's expected +// to generate Google Test fatal failures. It verifies that the given +// statement will cause exactly one fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_FATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - 'statement' cannot reference local non-static variables or +// non-static members of the current object. +// - 'statement' cannot return a value. +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. The AcceptsMacroThatExpandsToUnprotectedComma test in +// gtest_unittest.cc will fail to compile if we do that. +#define EXPECT_FATAL_FAILURE(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ALL_THREADS, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +// A macro for testing Google Test assertions or code that's expected to +// generate Google Test non-fatal failures. It asserts that the given +// statement will cause exactly one non-fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// 'statement' is allowed to reference local variables and members of +// the current object. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. +#define EXPECT_NONFATAL_FAILURE(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ + >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // NOLINT +#include +#include + +#if GTEST_OS_LINUX + +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +# include // NOLINT +# include // NOLINT +# include // NOLINT +// Declares vsnprintf(). This header is not available on Windows. +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include + +#elif GTEST_OS_SYMBIAN +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +#elif GTEST_OS_ZOS +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +// On z/OS we additionally need strings.h for strcasecmp. +# include // NOLINT + +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. + +# include // NOLINT + +#elif GTEST_OS_WINDOWS // We are on Windows proper. + +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT + +# if GTEST_OS_WINDOWS_MINGW +// MinGW has gettimeofday() but not _ftime64(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +// TODO(kenton@google.com): There are other ways to get the time on +// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW +// supports these. consider using them instead. +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT +# endif // GTEST_OS_WINDOWS_MINGW + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT + +#else + +// Assume other platforms have gettimeofday(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT +# include // NOLINT + +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +// Copyright 2005, 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. + +// Utility functions and classes used by the Google C++ testing framework. +// +// Author: wan@google.com (Zhanyong Wan) +// +// This file contains purely Google Test's internal implementation. Please +// DO NOT #INCLUDE IT IN A USER PROGRAM. + +#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ +#define GTEST_SRC_GTEST_INTERNAL_INL_H_ + +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ +// A user is trying to include this from his code - just say no. +# error "gtest-internal-inl.h is part of Google Test's internal implementation." +# error "It must not be included except by Google Test itself." +#endif // GTEST_IMPLEMENTATION_ + +#ifndef _WIN32_WCE +# include +#endif // !_WIN32_WCE +#include +#include // For strtoll/_strtoul64/malloc/free. +#include // For memmove. + +#include +#include +#include + + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +#if GTEST_OS_WINDOWS +# include // NOLINT +#endif // GTEST_OS_WINDOWS + + +namespace testing { + +// Declares the flags. +// +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); + +namespace internal { + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; + +// Names of the flags (needed for parsing Google Test flags). +const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; +const char kBreakOnFailureFlag[] = "break_on_failure"; +const char kCatchExceptionsFlag[] = "catch_exceptions"; +const char kColorFlag[] = "color"; +const char kFilterFlag[] = "filter"; +const char kListTestsFlag[] = "list_tests"; +const char kOutputFlag[] = "output"; +const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; +const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kStreamResultToFlag[] = "stream_result_to"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Converts the given time in milliseconds to a date string in the ISO 8601 +// format, without the timezone information. N.B.: due to the use the +// non-reentrant localtime() function, this function is not thread safe. Do +// not use it in any code that can be called from multiple threads. +GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast(GetTimeInMillis()) : + static_cast(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast((raw_seed - 1U) % + static_cast(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} + +// This class saves the values of all Google Test flags in its c'tor, and +// restores them in its d'tor. +class GTestFlagSaver { + public: + // The c'tor. + GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); + break_on_failure_ = GTEST_FLAG(break_on_failure); + catch_exceptions_ = GTEST_FLAG(catch_exceptions); + color_ = GTEST_FLAG(color); + death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); + filter_ = GTEST_FLAG(filter); + internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); + list_tests_ = GTEST_FLAG(list_tests); + output_ = GTEST_FLAG(output); + print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); + repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + stream_result_to_ = GTEST_FLAG(stream_result_to); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); + } + + // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. + ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; + GTEST_FLAG(break_on_failure) = break_on_failure_; + GTEST_FLAG(catch_exceptions) = catch_exceptions_; + GTEST_FLAG(color) = color_; + GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; + GTEST_FLAG(filter) = filter_; + GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; + GTEST_FLAG(list_tests) = list_tests_; + GTEST_FLAG(output) = output_; + GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; + GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(stream_result_to) = stream_result_to_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; + } + + private: + // Fields for saving the original values of flags. + bool also_run_disabled_tests_; + bool break_on_failure_; + bool catch_exceptions_; + std::string color_; + std::string death_test_style_; + bool death_test_use_fork_; + std::string filter_; + std::string internal_run_death_test_; + bool list_tests_; + std::string output_; + bool print_time_; + internal::Int32 random_seed_; + internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + std::string stream_result_to_; + bool throw_on_failure_; +} GTEST_ATTRIBUTE_UNUSED_; + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template +inline int CountIf(const Container& c, Predicate predicate) { + // Implemented as an explicit loop since std::count_if() in libCstd on + // Solaris has a non-standard signature. + int count = 0; + for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { + if (predicate(*it)) + ++count; + } + return count; +} + +// Applies a function/functor to each element in the container. +template +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} + +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template +inline E GetElementOr(const std::vector& v, int i, E default_value) { + return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; +} + +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector* v) { + const int size = static_cast(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); + } +} + +// Performs an in-place shuffle of the vector's elements. +template +inline void Shuffle(internal::Random* random, std::vector* v) { + ShuffleRange(random, 0, static_cast(v->size()), v); +} + +// A function for deleting an object. Handy for being used as a +// functor. +template +static void Delete(T* x) { + delete x; +} + +// A predicate that checks the key of a TestProperty against a known key. +// +// TestPropertyKeyIs is copyable. +class TestPropertyKeyIs { + public: + // Constructor. + // + // TestPropertyKeyIs has NO default constructor. + explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} + + // Returns true iff the test name of test property matches on key_. + bool operator()(const TestProperty& test_property) const { + return test_property.key() == key_; + } + + private: + std::string key_; +}; + +// Class UnitTestOptions. +// +// This class contains functions for processing options the user +// specifies when running the tests. It has only static members. +// +// In most cases, the user can specify an option using either an +// environment variable or a command line flag. E.g. you can set the +// test filter using either GTEST_FILTER or --gtest_filter. If both +// the variable and the flag are present, the latter overrides the +// former. +class GTEST_API_ UnitTestOptions { + public: + // Functions for processing the gtest_output flag. + + // Returns the output format, or "" for normal printed output. + static std::string GetOutputFormat(); + + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static std::string GetAbsolutePathToOutputFile(); + + // Functions for processing the gtest_filter flag. + + // Returns true iff the wildcard pattern matches the string. The + // first ':' or '\0' character in pattern marks the end of it. + // + // This recursive algorithm isn't very efficient, but is clear and + // works well enough for matching test names, which are short. + static bool PatternMatchesString(const char *pattern, const char *str); + + // Returns true iff the user-specified filter matches the test case + // name and the test name. + static bool FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name); + +#if GTEST_OS_WINDOWS + // Function for supporting the gtest_catch_exception flag. + + // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the + // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. + // This function is useful as an __except condition. + static int GTestShouldProcessSEH(DWORD exception_code); +#endif // GTEST_OS_WINDOWS + + // Returns true if "name" matches the ':' separated list of glob-style + // filters in "filter". + static bool MatchesFilter(const std::string& name, const char* filter); +}; + +// Returns the current application's name, removing directory path if that +// is present. Used by UnitTestOptions::GetOutputFile. +GTEST_API_ FilePath GetCurrentExecutableName(); + +// The role interface for getting the OS stack trace as a string. +class OsStackTraceGetterInterface { + public: + OsStackTraceGetterInterface() {} + virtual ~OsStackTraceGetterInterface() {} + + // Returns the current OS stack trace as an std::string. Parameters: + // + // max_depth - the maximum number of stack frames to be included + // in the trace. + // skip_count - the number of top frames to be skipped; doesn't count + // against max_depth. + virtual string CurrentStackTrace(int max_depth, int skip_count) = 0; + + // UponLeavingGTest() should be called immediately before Google Test calls + // user code. It saves some information about the current stack that + // CurrentStackTrace() will use to find and hide Google Test stack frames. + virtual void UponLeavingGTest() = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); +}; + +// A working implementation of the OsStackTraceGetterInterface interface. +class OsStackTraceGetter : public OsStackTraceGetterInterface { + public: + OsStackTraceGetter() : caller_frame_(NULL) {} + + virtual string CurrentStackTrace(int max_depth, int skip_count) + GTEST_LOCK_EXCLUDED_(mutex_); + + virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_); + + // This string is inserted in place of stack frames that are part of + // Google Test's implementation. + static const char* const kElidedFramesMarker; + + private: + Mutex mutex_; // protects all internal state + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to CurrentStackTrace() from within the user code. + void* caller_frame_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); +}; + +// Information about a Google Test trace point. +struct TraceInfo { + const char* file; + int line; + std::string message; +}; + +// This is the default global test part result reporter used in UnitTestImpl. +// This class should only be used by UnitTestImpl. +class DefaultGlobalTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. Reports the test part + // result in the current test. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); +}; + +// This is the default per thread test part result reporter used in +// UnitTestImpl. This class should only be used by UnitTestImpl. +class DefaultPerThreadTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. The implementation just + // delegates to the current global test part result reporter of *unit_test_. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); +}; + +// The private implementation of the UnitTest class. We don't protect +// the methods under a mutex, as this class is not accessible by a +// user and the UnitTest class that delegates work to this class does +// proper locking. +class GTEST_API_ UnitTestImpl { + public: + explicit UnitTestImpl(UnitTest* parent); + virtual ~UnitTestImpl(); + + // There are two different ways to register your own TestPartResultReporter. + // You can register your own repoter to listen either only for test results + // from the current thread or for results from all threads. + // By default, each per-thread test result repoter just passes a new + // TestPartResult to the global test result reporter, which registers the + // test part result for the currently running test. + + // Returns the global test part result reporter. + TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); + + // Sets the global test part result reporter. + void SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter); + + // Returns the test part result reporter for the current thread. + TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); + + // Sets the test part result reporter for the current thread. + void SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter); + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const { return start_timestamp_; } + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const { return !Failed(); } + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const { + return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; + } + + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); + + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } + + // Sets the OS stack trace getter. + // + // Does nothing if the input and the current OS stack trace getter + // are the same; otherwise, deletes the old getter and makes the + // input the current getter. + void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); + + // Returns the current OS stack trace getter if it is not NULL; + // otherwise, creates an OsStackTraceGetter, makes it the current + // getter, and returns it. + OsStackTraceGetterInterface* os_stack_trace_getter(); + + // Returns the current OS stack trace as an std::string. + // + // The maximum number of stack frames to be included is specified by + // the gtest_stack_trace_depth flag. The skip_count parameter + // specifies the number of top frames to be skipped, which doesn't + // count against the number of frames to be included. + // + // For example, if Foo() calls Bar(), which in turn calls + // CurrentOsStackTraceExceptTop(1), Foo() will be included in the + // trace but Bar() and CurrentOsStackTraceExceptTop() won't. + std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; + + // Finds and returns a TestCase with the given name. If one doesn't + // exist, creates one and returns it. + // + // Arguments: + // + // test_case_name: name of the test case + // type_param: the name of the test's type parameter, or NULL if + // this is not a typed or a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase* GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Adds a TestInfo to the unit test. + // + // Arguments: + // + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + // test_info: the TestInfo object + void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + TestInfo* test_info) { + // In order to support thread-safe death tests, we need to + // remember the original working directory when the test program + // was first invoked. We cannot do this in RUN_ALL_TESTS(), as + // the user may have changed the current directory before calling + // RUN_ALL_TESTS(). Therefore we capture the current directory in + // AddTestInfo(), which is called to register a TEST or TEST_F + // before main() is reached. + if (original_working_dir_.IsEmpty()) { + original_working_dir_.Set(FilePath::GetCurrentDir()); + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; + } + + GetTestCase(test_info->test_case_name(), + test_info->type_param(), + set_up_tc, + tear_down_tc)->AddTestInfo(test_info); + } + +#if GTEST_HAS_PARAM_TEST + // Returns ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + return parameterized_test_registry_; + } +#endif // GTEST_HAS_PARAM_TEST + + // Sets the TestCase object for the test that's currently running. + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; + } + + // Sets the TestInfo object for the test that's currently running. If + // current_test_info is NULL, the assertion results will be stored in + // ad_hoc_test_result_. + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; + } + + // Registers all parameterized tests defined using TEST_P and + // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // combination. This method can be called more then once; it has guards + // protecting from registering the tests more then once. If + // value-parameterized tests are disabled, RegisterParameterizedTests is + // present but does nothing. + void RegisterParameterizedTests(); + + // Runs all tests in this UnitTest object, prints the result, and + // returns true if all tests are successful. If any exception is + // thrown during a test, this test is considered to be failed, but + // the rest of the tests will still be run. + bool RunAllTests(); + + // Clears the results of all tests, except the ad hoc tests. + void ClearNonAdHocTestResult() { + ForEach(test_cases_, TestCase::ClearTestCaseResult); + } + + // Clears the results of ad-hoc test assertions. + void ClearAdHocTestResult() { + ad_hoc_test_result_.Clear(); + } + + // Adds a TestProperty to the current TestResult object when invoked in a + // context of a test or a test case, or to the global property set. If the + // result already contains a property with the same key, the value will be + // updated. + void RecordProperty(const TestProperty& test_property); + + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + + // Matches the full name of each test against the user-specified + // filter to decide whether the test should run, then records the + // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. + // Returns the number of tests that should run. + int FilterTests(ReactionToSharding shard_tests); + + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); + + const TestCase* current_test_case() const { return current_test_case_; } + TestInfo* current_test_info() { return current_test_info_; } + const TestInfo* current_test_info() const { return current_test_info_; } + + // Returns the vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector& environments() { return environments_; } + + // Getters for the per-thread Google Test trace stack. + std::vector& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); + } + const std::vector& gtest_trace_stack() const { + return gtest_trace_stack_.get(); + } + +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } + // Returns a pointer to the parsed --gtest_internal_run_death_test + // flag, or NULL if that flag was not specified. + // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. + const InternalRunDeathTestFlag* internal_run_death_test_flag() const { + return internal_run_death_test_flag_.get(); + } + + // Returns a pointer to the current death test factory. + internal::DeathTestFactory* death_test_factory() { + return death_test_factory_.get(); + } + + void SuppressTestEventsIfInSubprocess(); + + friend class ReplaceDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Initializes the event listener for streaming test results to a socket. + // Must not be called before InitGoogleTest. + void ConfigureStreamingOutput(); +#endif + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + + // Returns the value of GTEST_FLAG(catch_exceptions) at the moment + // UnitTest::Run() starts. + bool catch_exceptions() const { return catch_exceptions_; } + + private: + friend class ::testing::UnitTest; + + // Used by UnitTest::Run() to capture the state of + // GTEST_FLAG(catch_exceptions) at the moment it starts. + void set_catch_exceptions(bool value) { catch_exceptions_ = value; } + + // The UnitTest object that owns this implementation object. + UnitTest* const parent_; + + // The working directory when the first TEST() or TEST_F() was + // executed. + internal::FilePath original_working_dir_; + + // The default test part result reporters. + DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; + DefaultPerThreadTestPartResultReporter + default_per_thread_test_part_result_reporter_; + + // Points to (but doesn't own) the global test part result reporter. + TestPartResultReporterInterface* global_test_part_result_repoter_; + + // Protects read and write access to global_test_part_result_reporter_. + internal::Mutex global_test_part_result_reporter_mutex_; + + // Points to (but doesn't own) the per-thread test part result reporter. + internal::ThreadLocal + per_thread_test_part_result_reporter_; + + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector test_cases_; + + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector test_case_indices_; + +#if GTEST_HAS_PARAM_TEST + // ParameterizedTestRegistry object used to register value-parameterized + // tests. + internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + + // Indicates whether RegisterParameterizedTests() has been called already. + bool parameterized_tests_registered_; +#endif // GTEST_HAS_PARAM_TEST + + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; + + // This points to the TestCase for the currently running test. It + // changes as Google Test goes through one test case after another. + // When no test is running, this is set to NULL and Google Test + // stores assertion results in ad_hoc_test_result_. Initially NULL. + TestCase* current_test_case_; + + // This points to the TestInfo for the currently running test. It + // changes as Google Test goes through one test after another. When + // no test is running, this is set to NULL and Google Test stores + // assertion results in ad_hoc_test_result_. Initially NULL. + TestInfo* current_test_info_; + + // Normally, a user only writes assertions inside a TEST or TEST_F, + // or inside a function called by a TEST or TEST_F. Since Google + // Test keeps track of which test is current running, it can + // associate such an assertion with the test it belongs to. + // + // If an assertion is encountered when no TEST or TEST_F is running, + // Google Test attributes the assertion result to an imaginary "ad hoc" + // test, and records the result in ad_hoc_test_result_. + TestResult ad_hoc_test_result_; + + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; + + // The OS stack trace getter. Will be deleted when the UnitTest + // object is destructed. By default, an OsStackTraceGetter is used, + // but the user can set this field to use a custom getter if that is + // desired. + OsStackTraceGetterInterface* os_stack_trace_getter_; + + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + + // The time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp_; + + // How long the test took to run, in milliseconds. + TimeInMillis elapsed_time_; + +#if GTEST_HAS_DEATH_TEST + // The decomposed components of the gtest_internal_run_death_test flag, + // parsed when RUN_ALL_TESTS is called. + internal::scoped_ptr internal_run_death_test_flag_; + internal::scoped_ptr death_test_factory_; +#endif // GTEST_HAS_DEATH_TEST + + // A per-thread stack of traces created by the SCOPED_TRACE() macro. + internal::ThreadLocal > gtest_trace_stack_; + + // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() + // starts. + bool catch_exceptions_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); +}; // class UnitTestImpl + +// Convenience function for accessing the global UnitTest +// implementation object. +inline UnitTestImpl* GetUnitTestImpl() { + return UnitTest::GetInstance()->impl(); +} + +#if GTEST_USES_SIMPLE_RE + +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsAsciiDigit(char ch); +GTEST_API_ bool IsAsciiPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsAsciiWhiteSpace(char ch); +GTEST_API_ bool IsAsciiWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + +#endif // GTEST_USES_SIMPLE_RE + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +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 +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !IsDigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. + +# if GTEST_OS_WINDOWS && !defined(__GNUC__) + + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); + +# else + + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); + +# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast(parsed); + if (parse_success && static_cast(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const std::string& xml_element, + const TestProperty& property) { + test_result->RecordProperty(xml_element, property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; + +#if GTEST_CAN_STREAM_RESULTS_ + +// Streams test results to the given port on the given host machine. +class StreamingListener : public EmptyTestEventListener { + public: + // Abstract base class for writing strings to a socket. + class AbstractSocketWriter { + public: + virtual ~AbstractSocketWriter() {} + + // Sends a string to the socket. + virtual void Send(const string& message) = 0; + + // Closes the socket. + virtual void CloseConnection() {} + + // Sends a string and a newline to the socket. + void SendLn(const string& message) { + Send(message + "\n"); + } + }; + + // Concrete class for actually writing strings to a socket. + class SocketWriter : public AbstractSocketWriter { + public: + SocketWriter(const string& host, const string& port) + : sockfd_(-1), host_name_(host), port_num_(port) { + MakeConnection(); + } + + virtual ~SocketWriter() { + if (sockfd_ != -1) + CloseConnection(); + } + + // Sends a string to the socket. + virtual void Send(const string& message) { + GTEST_CHECK_(sockfd_ != -1) + << "Send() can be called only when there is a connection."; + + const int len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != len) { + GTEST_LOG_(WARNING) + << "stream_result_to: failed to stream to " + << host_name_ << ":" << port_num_; + } + } + + private: + // Creates a client socket and connects to the server. + void MakeConnection(); + + // Closes the socket. + void CloseConnection() { + GTEST_CHECK_(sockfd_ != -1) + << "CloseConnection() can be called only when there is a connection."; + + close(sockfd_); + sockfd_ = -1; + } + + int sockfd_; // socket file descriptor + const string host_name_; + const string port_num_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); + }; // class SocketWriter + + // Escapes '=', '&', '%', and '\n' characters in str as "%xx". + static string UrlEncode(const char* str); + + StreamingListener(const string& host, const string& port) + : socket_writer_(new SocketWriter(host, port)) { Start(); } + + explicit StreamingListener(AbstractSocketWriter* socket_writer) + : socket_writer_(socket_writer) { Start(); } + + void OnTestProgramStart(const UnitTest& /* unit_test */) { + SendLn("event=TestProgramStart"); + } + + void OnTestProgramEnd(const UnitTest& unit_test) { + // Note that Google Test current only report elapsed time for each + // test iteration, not for the entire test program. + SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); + + // Notify the streaming server to stop. + socket_writer_->CloseConnection(); + } + + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + SendLn("event=TestIterationStart&iteration=" + + StreamableToString(iteration)); + } + + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + SendLn("event=TestIterationEnd&passed=" + + FormatBool(unit_test.Passed()) + "&elapsed_time=" + + StreamableToString(unit_test.elapsed_time()) + "ms"); + } + + void OnTestCaseStart(const TestCase& test_case) { + SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); + } + + void OnTestCaseEnd(const TestCase& test_case) { + SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + + "ms"); + } + + void OnTestStart(const TestInfo& test_info) { + SendLn(std::string("event=TestStart&name=") + test_info.name()); + } + + void OnTestEnd(const TestInfo& test_info) { + SendLn("event=TestEnd&passed=" + + FormatBool((test_info.result())->Passed()) + + "&elapsed_time=" + + StreamableToString((test_info.result())->elapsed_time()) + "ms"); + } + + void OnTestPartResult(const TestPartResult& test_part_result) { + const char* file_name = test_part_result.file_name(); + if (file_name == NULL) + file_name = ""; + SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + + "&line=" + StreamableToString(test_part_result.line_number()) + + "&message=" + UrlEncode(test_part_result.message())); + } + + private: + // Sends the given message and a newline to the socket. + void SendLn(const string& message) { socket_writer_->SendLn(message); } + + // Called at the start of streaming to notify the receiver what + // protocol we are using. + void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } + + string FormatBool(bool value) { return value ? "1" : "0"; } + + const scoped_ptr socket_writer_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); +}; // class StreamingListener + +#endif // GTEST_CAN_STREAM_RESULTS_ + +} // namespace internal +} // namespace testing + +#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ +#undef GTEST_IMPLEMENTATION_ + +#if GTEST_OS_WINDOWS +# define vsnprintf _vsnprintf +#endif // GTEST_OS_WINDOWS + +namespace testing { + +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + +// Constants. + +// A test whose test case name or test name matches this filter is +// disabled and not run. +static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; + +// A test case whose name matches this filter is considered a death +// test case and will be run before test cases whose name doesn't +// match this filter. +static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; + +// A test filter that matches everything. +static const char kUniversalFilter[] = "*"; + +// The default output file for XML output. +static const char kDefaultOutputFile[] = "test_detail.xml"; + +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + +namespace internal { + +// The text used in failure messages to indicate the start of the +// stack trace. +const char kStackTraceMarker[] = "\nStack trace:\n"; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + +} // namespace internal + +static const char* GetDefaultFilter() { + return kUniversalFilter; +} + +GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( + break_on_failure, + internal::BoolFromGTestEnv("break_on_failure", false), + "True iff a failed assertion should be a debugger break-point."); + +GTEST_DEFINE_bool_( + catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True iff " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); + +GTEST_DEFINE_string_( + color, + internal::StringFromGTestEnv("color", "auto"), + "Whether to use colors in the output. Valid values: yes, no, " + "and auto. 'auto' means to use colors if the output is " + "being sent to a terminal and the TERM environment variable " + "is set to a terminal type that supports colors."); + +GTEST_DEFINE_string_( + filter, + internal::StringFromGTestEnv("filter", GetDefaultFilter()), + "A colon-separated list of glob (not regex) patterns " + "for filtering the tests to run, optionally followed by a " + "'-' and a : separated list of negative patterns (tests to " + "exclude). A test is run if it matches one of the positive " + "patterns and does not match any of the negative patterns."); + +GTEST_DEFINE_bool_(list_tests, false, + "List all tests without running them."); + +GTEST_DEFINE_string_( + output, + internal::StringFromGTestEnv("output", ""), + "A format (currently must be \"xml\"), optionally followed " + "by a colon and an output file name or directory. A directory " + "is indicated by a trailing pathname separator. " + "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " + "If a directory is specified, output files will be created " + "within that directory, with file-names based on the test " + "executable's name and, if necessary, made unique by adding " + "digits."); + +GTEST_DEFINE_bool_( + print_time, + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( + repeat, + internal::Int32FromGTestEnv("repeat", 1), + "How many times to repeat each test. Specify a negative number " + "for repeating forever. Useful for shaking out flaky tests."); + +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + +GTEST_DEFINE_int32_( + stack_trace_depth, + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + "The maximum number of stack frames to print when an " + "assertion fails. The valid range is 0 through 100, inclusive."); + +GTEST_DEFINE_string_( + stream_result_to, + internal::StringFromGTestEnv("stream_result_to", ""), + "This flag specifies the host name and the port number on which to stream " + "test results. Example: \"localhost:555\". The flag is effective only on " + "Linux."); + +GTEST_DEFINE_bool_( + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); + +namespace internal { + +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + +// GTestIsInitialized() returns true iff the user has initialized +// Google Test. Useful for catching the user mistake of not initializing +// Google Test before calling RUN_ALL_TESTS(). +// +// A user must call testing::InitGoogleTest() to initialize Google +// Test. g_init_gtest_count is set to the number of times +// InitGoogleTest() has been called. We don't protect this variable +// under a mutex as it is only accessed in the main thread. +GTEST_API_ int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } + +// Iterates over a vector of TestCases, keeping a running sum of the +// results of calling a given int-returning method on each. +// Returns the sum. +static int SumOverTestCaseList(const std::vector& case_list, + int (TestCase::*method)() const) { + int sum = 0; + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); + } + return sum; +} + +// Returns true iff the test case passed. +static bool TestCasePassed(const TestCase* test_case) { + return test_case->should_run() && test_case->Passed(); +} + +// Returns true iff the test case failed. +static bool TestCaseFailed(const TestCase* test_case) { + return test_case->should_run() && test_case->Failed(); +} + +// Returns true iff test_case contains at least one test that should +// run. +static bool ShouldRunTestCase(const TestCase* test_case) { + return test_case->should_run(); +} + +// AssertHelper constructor. +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; +} + +// Message assignment, for assertion streaming support. +void AssertHelper::operator=(const Message& message) const { + UnitTest::GetInstance()-> + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), + UnitTest::GetInstance()->impl() + ->CurrentOsStackTraceExceptTop(1) + // Skips the stack frame for this function itself. + ); // NOLINT +} + +// Mutex for linked pointers. +GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// Application pathname gotten in InitGoogleTest. +std::string g_executable_path; + +// Returns the current application's name, removing directory path if that +// is present. +FilePath GetCurrentExecutableName() { + FilePath result; + +#if GTEST_OS_WINDOWS + result.Set(FilePath(g_executable_path).RemoveExtension("exe")); +#else + result.Set(FilePath(g_executable_path)); +#endif // GTEST_OS_WINDOWS + + return result.RemoveDirectoryName(); +} + +// Functions for processing the gtest_output flag. + +// Returns the output format, or "" for normal printed output. +std::string UnitTestOptions::GetOutputFormat() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) return std::string(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + return (colon == NULL) ? + std::string(gtest_output_flag) : + std::string(gtest_output_flag, colon - gtest_output_flag); +} + +// Returns the name of the requested output file, or the default if none +// was explicitly specified. +std::string UnitTestOptions::GetAbsolutePathToOutputFile() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) + return ""; + + const char* const colon = strchr(gtest_output_flag, ':'); + if (colon == NULL) + return internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).string(); + + internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + + if (!output_name.IsDirectory()) + return output_name.string(); + + internal::FilePath result(internal::FilePath::GenerateUniqueFileName( + output_name, internal::GetCurrentExecutableName(), + GetOutputFormat().c_str())); + return result.string(); +} + +// Returns true iff the wildcard pattern matches the string. The +// first ':' or '\0' character in pattern marks the end of it. +// +// This recursive algorithm isn't very efficient, but is clear and +// works well enough for matching test names, which are short. +bool UnitTestOptions::PatternMatchesString(const char *pattern, + const char *str) { + switch (*pattern) { + case '\0': + case ':': // Either ':' or '\0' marks the end of the pattern. + return *str == '\0'; + case '?': // Matches any single character. + return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); + case '*': // Matches any string (possibly empty) of characters. + return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || + PatternMatchesString(pattern + 1, str); + default: // Non-special character. Matches itself. + return *pattern == *str && + PatternMatchesString(pattern + 1, str + 1); + } +} + +bool UnitTestOptions::MatchesFilter( + const std::string& name, const char* filter) { + const char *cur_pattern = filter; + for (;;) { + if (PatternMatchesString(cur_pattern, name.c_str())) { + return true; + } + + // Finds the next pattern in the filter. + cur_pattern = strchr(cur_pattern, ':'); + + // Returns if no more pattern can be found. + if (cur_pattern == NULL) { + return false; + } + + // Skips the pattern separater (the ':' character). + cur_pattern++; + } +} + +// Returns true iff the user-specified filter matches the test case +// name and the test name. +bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name) { + const std::string& full_name = test_case_name + "." + test_name.c_str(); + + // Split --gtest_filter at '-', if there is one, to separate into + // positive filter and negative filter portions + const char* const p = GTEST_FLAG(filter).c_str(); + const char* const dash = strchr(p, '-'); + std::string positive; + std::string negative; + if (dash == NULL) { + positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter + negative = ""; + } else { + positive = std::string(p, dash); // Everything up to the dash + negative = std::string(dash + 1); // Everything after the dash + if (positive.empty()) { + // Treat '-test1' as the same as '*-test1' + positive = kUniversalFilter; + } + } + + // A filter is a colon-separated list of patterns. It matches a + // test if any pattern in it matches the test. + return (MatchesFilter(full_name, positive.c_str()) && + !MatchesFilter(full_name, negative.c_str())); +} + +#if GTEST_HAS_SEH +// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the +// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. +// This function is useful as an __except condition. +int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { + // Google Test should handle a SEH exception if: + // 1. the user wants it to, AND + // 2. this is not a breakpoint exception, AND + // 3. this is not a C++ exception (VC++ implements them via SEH, + // apparently). + // + // SEH exception code for C++ exceptions. + // (see http://support.microsoft.com/kb/185294 for more information). + const DWORD kCxxExceptionCode = 0xe06d7363; + + bool should_handle = true; + + if (!GTEST_FLAG(catch_exceptions)) + should_handle = false; + else if (exception_code == EXCEPTION_BREAKPOINT) + should_handle = false; + else if (exception_code == kCxxExceptionCode) + should_handle = false; + + return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +} +#endif // GTEST_HAS_SEH + +} // namespace internal + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. Intercepts only failures from the current thread. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + TestPartResultArray* result) + : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), + result_(result) { + Init(); +} + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + InterceptMode intercept_mode, TestPartResultArray* result) + : intercept_mode_(intercept_mode), + result_(result) { + Init(); +} + +void ScopedFakeTestPartResultReporter::Init() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + old_reporter_ = impl->GetGlobalTestPartResultReporter(); + impl->SetGlobalTestPartResultReporter(this); + } else { + old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); + impl->SetTestPartResultReporterForCurrentThread(this); + } +} + +// The d'tor restores the test part result reporter used by Google Test +// before. +ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + impl->SetGlobalTestPartResultReporter(old_reporter_); + } else { + impl->SetTestPartResultReporterForCurrentThread(old_reporter_); + } +} + +// Increments the test part result count and remembers the result. +// This method is from the TestPartResultReporterInterface interface. +void ScopedFakeTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + result_->Append(result); +} + +namespace internal { + +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + +// This predicate-formatter checks that 'results' contains a test part +// failure of the given type and that the failure message contains the +// given substring. +AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const string& substr) { + const std::string expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); + Message msg; + if (results.size() != 1) { + msg << "Expected: " << expected << "\n" + << " Actual: " << results.size() << " failures"; + for (int i = 0; i < results.size(); i++) { + msg << "\n" << results.GetTestPartResult(i); + } + return AssertionFailure() << msg; + } + + const TestPartResult& r = results.GetTestPartResult(0); + if (r.type() != type) { + return AssertionFailure() << "Expected: " << expected << "\n" + << " Actual:\n" + << r; + } + + if (strstr(r.message(), substr.c_str()) == NULL) { + return AssertionFailure() << "Expected: " << expected << " containing \"" + << substr << "\"\n" + << " Actual:\n" + << r; + } + + return AssertionSuccess(); +} + +// The constructor of SingleFailureChecker remembers where to look up +// test part results, what type of failure we expect, and what +// substring the failure message should contain. +SingleFailureChecker:: SingleFailureChecker( + const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr) + : results_(results), + type_(type), + substr_(substr) {} + +// The destructor of SingleFailureChecker verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +SingleFailureChecker::~SingleFailureChecker() { + EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); +} + +DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultGlobalTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->current_test_result()->AddTestPartResult(result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); +} + +DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); +} + +// Returns the global test part result reporter. +TestPartResultReporterInterface* +UnitTestImpl::GetGlobalTestPartResultReporter() { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + return global_test_part_result_repoter_; +} + +// Sets the global test part result reporter. +void UnitTestImpl::SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter) { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + global_test_part_result_repoter_ = reporter; +} + +// Returns the test part result reporter for the current thread. +TestPartResultReporterInterface* +UnitTestImpl::GetTestPartResultReporterForCurrentThread() { + return per_thread_test_part_result_reporter_.get(); +} + +// Sets the test part result reporter for the current thread. +void UnitTestImpl::SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter) { + per_thread_test_part_result_reporter_.set(reporter); +} + +// Gets the number of successful test cases. +int UnitTestImpl::successful_test_case_count() const { + return CountIf(test_cases_, TestCasePassed); +} + +// Gets the number of failed test cases. +int UnitTestImpl::failed_test_case_count() const { + return CountIf(test_cases_, TestCaseFailed); +} + +// Gets the number of all test cases. +int UnitTestImpl::total_test_case_count() const { + return static_cast(test_cases_.size()); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTestImpl::test_case_to_run_count() const { + return CountIf(test_cases_, ShouldRunTestCase); +} + +// Gets the number of successful tests. +int UnitTestImpl::successful_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); +} + +// Gets the number of failed tests. +int UnitTestImpl::failed_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTestImpl::reportable_disabled_test_count() const { + return SumOverTestCaseList(test_cases_, + &TestCase::reportable_disabled_test_count); +} + +// Gets the number of disabled tests. +int UnitTestImpl::disabled_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTestImpl::reportable_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count); +} + +// Gets the number of all tests. +int UnitTestImpl::total_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); +} + +// Gets the number of tests that should run. +int UnitTestImpl::test_to_run_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// CurrentOsStackTraceExceptTop(1), Foo() will be included in the +// trace but Bar() and CurrentOsStackTraceExceptTop() won't. +std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { + (void)skip_count; + return ""; +} + +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. + // http://analogous.blogspot.com/2005/04/epoch.html + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast(116444736UL) * 100000UL; + const DWORD kTenthMicrosInMilliSecond = 10000; + + SYSTEMTIME now_systime; + FILETIME now_filetime; + ULARGE_INTEGER now_int64; + // TODO(kenton@google.com): Shouldn't this just use + // GetSystemTimeAsFileTime()? + GetSystemTime(&now_systime); + if (SystemTimeToFileTime(&now_systime, &now_filetime)) { + now_int64.LowPart = now_filetime.dwLowDateTime; + now_int64.HighPart = now_filetime.dwHighDateTime; + now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - + kJavaEpochToWinFileTimeDelta; + return now_int64.QuadPart; + } + return 0; +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ + __timeb64 now; + +# ifdef _MSC_VER + + // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 + // (deprecated function) there. + // TODO(kenton@google.com): Use GetTickCount()? Or use + // SystemTimeToFileTime() +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + _ftime64(&now); +# pragma warning(pop) // Restores the warning state. +# else + + _ftime64(&now); + +# endif // _MSC_VER + + return static_cast(now.time) * 1000 + now.millitm; +#elif GTEST_HAS_GETTIMEOFDAY_ + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; +#else +# error "Don't know how to get the current time on your system." +#endif +} + +// Utilities + +// class String. + +#if GTEST_OS_WINDOWS_MOBILE +// Creates a UTF-16 wide string from the given ANSI string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the wide string, or NULL if the +// input is NULL. +LPCWSTR String::AnsiToUtf16(const char* ansi) { + if (!ansi) return NULL; + const int length = strlen(ansi); + const int unicode_length = + MultiByteToWideChar(CP_ACP, 0, ansi, length, + NULL, 0); + WCHAR* unicode = new WCHAR[unicode_length + 1]; + MultiByteToWideChar(CP_ACP, 0, ansi, length, + unicode, unicode_length); + unicode[unicode_length] = 0; + return unicode; +} + +// Creates an ANSI string from the given wide string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the ANSI string, or NULL if the +// input is NULL. +const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { + if (!utf16_str) return NULL; + const int ansi_length = + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + NULL, 0, NULL, NULL); + char* ansi = new char[ansi_length + 1]; + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + ansi, ansi_length, NULL, NULL); + ansi[ansi_length] = 0; + return ansi; +} + +#endif // GTEST_OS_WINDOWS_MOBILE + +// Compares two C strings. Returns true iff they have the same content. +// +// Unlike strcmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CStringEquals(const char * lhs, const char * rhs) { + if ( lhs == NULL ) return rhs == NULL; + + if ( rhs == NULL ) return false; + + return strcmp(lhs, rhs) == 0; +} + +#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +// Converts an array of wide chars to a narrow string using the UTF-8 +// encoding, and streams the result to the given Message object. +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, + Message* msg) { + for (size_t i = 0; i != length; ) { // NOLINT + if (wstr[i] != L'\0') { + *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); + while (i != length && wstr[i] != L'\0') + i++; + } else { + *msg << '\0'; + i++; + } + } +} + +#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +} // namespace internal + +// Constructs an empty Message. +// We allocate the stringstream separately because otherwise each use of +// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's +// stack frame leading to huge stack frames in some cases; gcc does not reuse +// the stack space. +Message::Message() : ss_(new ::std::stringstream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); +} + +// These two overloads allow streaming a wide C string to a Message +// using the UTF-8 encoding. +Message& Message::operator <<(const wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} +Message& Message::operator <<(wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} + +#if GTEST_HAS_STD_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::std::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Gets the text streamed to this object so far as an std::string. +// Each '\0' character in the buffer is replaced with "\\0". +std::string Message::GetString() const { + return internal::StringStreamToString(ss_.get()); +} + +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new ::std::string(*other.message_) : + static_cast< ::std::string*>(NULL)) { +} + +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} + +// Makes a successful assertion result. +AssertionResult AssertionSuccess() { + return AssertionResult(true); +} + +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. +AssertionResult AssertionFailure(const Message& message) { + return AssertionFailure() << message; +} + +namespace internal { + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case) { + Message msg; + msg << "Value of: " << actual_expression; + if (actual_value != actual_expression) { + msg << "\n Actual: " << actual_value; + } + + msg << "\nExpected: " << expected_expression; + if (ignoring_case) { + msg << " (ignoring case)"; + } + if (expected_value != expected_expression) { + msg << "\nWhich is: " << expected_value; + } + + return AssertionFailure() << msg; +} + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +// Helper function for implementing ASSERT_NEAR. +AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error) { + const double diff = fabs(val1 - val2); + if (diff <= abs_error) return AssertionSuccess(); + + // TODO(wan): do not print the value of an expression if it's + // already a literal. + return AssertionFailure() + << "The difference between " << expr1 << " and " << expr2 + << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} + + +// Helper template for implementing FloatLE() and DoubleLE(). +template +AssertionResult FloatingPointLE(const char* expr1, + const char* expr2, + RawType val1, + RawType val2) { + // Returns success if val1 is less than val2, + if (val1 < val2) { + return AssertionSuccess(); + } + + // or if val1 is almost equal to val2. + const FloatingPoint lhs(val1), rhs(val2); + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + // Note that the above two checks will both fail if either val1 or + // val2 is NaN, as the IEEE floating-point standard requires that + // any predicate involving a NaN must return false. + + ::std::stringstream val1_ss; + val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val1; + + ::std::stringstream val2_ss; + val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val2; + + return AssertionFailure() + << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" + << " Actual: " << StringStreamToString(&val1_ss) << " vs " + << StringStreamToString(&val2_ss); +} + +} // namespace internal + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +namespace internal { + +// The helper function for {ASSERT|EXPECT}_EQ with int or enum +// arguments. +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + if (expected == actual) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here +// just to avoid copy-and-paste of similar code. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + BiggestInt val1, BiggestInt val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +} + +// Implements the helper function for {ASSERT|EXPECT}_NE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(NE, !=) +// Implements the helper function for {ASSERT|EXPECT}_LE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LE, <=) +// Implements the helper function for {ASSERT|EXPECT}_LT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LT, < ) +// Implements the helper function for {ASSERT|EXPECT}_GE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GE, >=) +// Implements the helper function for {ASSERT|EXPECT}_GT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GT, > ) + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CaseInsensitiveCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + true); +} + +// The helper function for {ASSERT|EXPECT}_STRNE. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CaseInsensitiveCStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() + << "Expected: (" << s1_expression << ") != (" + << s2_expression << ") (ignoring case), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +} // namespace internal + +namespace { + +// Helper functions for implementing IsSubString() and IsNotSubstring(). + +// This group of overloaded functions return true iff needle is a +// substring of haystack. NULL is considered a substring of itself +// only. + +bool IsSubstringPred(const char* needle, const char* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return strstr(haystack, needle) != NULL; +} + +bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return wcsstr(haystack, needle) != NULL; +} + +// StringType here can be either ::std::string or ::std::wstring. +template +bool IsSubstringPred(const StringType& needle, + const StringType& haystack) { + return haystack.find(needle) != StringType::npos; +} + +// This function implements either IsSubstring() or IsNotSubstring(), +// depending on the value of the expected_to_be_substring parameter. +// StringType here can be const char*, const wchar_t*, ::std::string, +// or ::std::wstring. +template +AssertionResult IsSubstringImpl( + bool expected_to_be_substring, + const char* needle_expr, const char* haystack_expr, + const StringType& needle, const StringType& haystack) { + if (IsSubstringPred(needle, haystack) == expected_to_be_substring) + return AssertionSuccess(); + + const bool is_wide_string = sizeof(needle[0]) > 1; + const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; + return AssertionFailure() + << "Value of: " << needle_expr << "\n" + << " Actual: " << begin_string_quote << needle << "\"\n" + << "Expected: " << (expected_to_be_substring ? "" : "not ") + << "a substring of " << haystack_expr << "\n" + << "Which is: " << begin_string_quote << haystack << "\""; +} + +} // namespace + +// IsSubstring() and IsNotSubstring() check whether needle is a +// substring of haystack (NULL is considered a substring of itself +// only), and return an appropriate error message when they fail. + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +#if GTEST_HAS_STD_WSTRING +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +#if GTEST_OS_WINDOWS + +namespace { + +// Helper function for IsHRESULT{SuccessFailure} predicates +AssertionResult HRESULTFailureHelper(const char* expr, + const char* expected, + long hr) { // NOLINT +# if GTEST_OS_WINDOWS_MOBILE + + // Windows CE doesn't support FormatMessage. + const char error_text[] = ""; + +# else + + // Looks up the human-readable system message for the HRESULT code + // and since we're not passing any params to FormatMessage, we don't + // want inserts expanded. + const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + const DWORD kBufSize = 4096; + // Gets the system's human readable message string for this HRESULT. + char error_text[kBufSize] = { '\0' }; + DWORD message_length = ::FormatMessageA(kFlags, + 0, // no source, we're asking system + hr, // the error + 0, // no line width restrictions + error_text, // output buffer + kBufSize, // buf size + NULL); // no arguments for inserts + // Trims tailing white space (FormatMessage leaves a trailing CR-LF) + for (; message_length && IsSpace(error_text[message_length - 1]); + --message_length) { + error_text[message_length - 1] = '\0'; + } + +# endif // GTEST_OS_WINDOWS_MOBILE + + const std::string error_hex("0x" + String::FormatHexInt(hr)); + return ::testing::AssertionFailure() + << "Expected: " << expr << " " << expected << ".\n" + << " Actual: " << error_hex << " " << error_text << "\n"; +} + +} // namespace + +AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT + if (SUCCEEDED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "succeeds", hr); +} + +AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT + if (FAILED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "fails", hr); +} + +#endif // GTEST_OS_WINDOWS + +// Utility functions for encoding Unicode text (wide strings) in +// UTF-8. + +// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// like this: +// +// Code-point length Encoding +// 0 - 7 bits 0xxxxxxx +// 8 - 11 bits 110xxxxx 10xxxxxx +// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx +// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +// The maximum code-point a one-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; + +// The maximum code-point a two-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; + +// The maximum code-point a three-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; + +// The maximum code-point a four-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; + +// Chops off the n lowest bits from a bit pattern. Returns the n +// lowest bits. As a side effect, the original bit pattern will be +// shifted to the right by n bits. +inline UInt32 ChopLowBits(UInt32* bits, int n) { + const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); + *bits >>= n; + return low_bits; +} + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +std::string CodePointToUtf8(UInt32 code_point) { + if (code_point > kMaxCodePoint4) { + return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; + } + + char str[5]; // Big enough for the largest valid code point. + if (code_point <= kMaxCodePoint1) { + str[1] = '\0'; + str[0] = static_cast(code_point); // 0xxxxxxx + } else if (code_point <= kMaxCodePoint2) { + str[2] = '\0'; + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xC0 | code_point); // 110xxxxx + } else if (code_point <= kMaxCodePoint3) { + str[3] = '\0'; + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xE0 | code_point); // 1110xxxx + } else { // code_point <= kMaxCodePoint4 + str[4] = '\0'; + str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xF0 | code_point); // 11110xxx + } + return str; +} + +// The following two functions only make sense if the the system +// uses UTF-16 for wide string encoding. All supported systems +// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. + +// Determines if the arguments constitute UTF-16 surrogate pair +// and thus should be combined into a single Unicode code point +// using CreateCodePointFromUtf16SurrogatePair. +inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; +} + +// Creates a Unicode code point from UTF16 surrogate pair. +inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, + wchar_t second) { + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast(first); +} + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +std::string WideStringToUtf8(const wchar_t* str, int num_chars) { + if (num_chars == -1) + num_chars = static_cast(wcslen(str)); + + ::std::stringstream stream; + for (int i = 0; i < num_chars; ++i) { + UInt32 unicode_code_point; + + if (str[i] == L'\0') { + break; + } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { + unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], + str[i + 1]); + i++; + } else { + unicode_code_point = static_cast(str[i]); + } + + stream << CodePointToUtf8(unicode_code_point); + } + return StringStreamToString(&stream); +} + +// Converts a wide C string to an std::string using the UTF-8 encoding. +// NULL will be converted to "(null)". +std::string String::ShowWideCString(const wchar_t * wide_c_str) { + if (wide_c_str == NULL) return "(null)"; + + return internal::WideStringToUtf8(wide_c_str, -1); +} + +// Compares two wide C strings. Returns true iff they have the same +// content. +// +// Unlike wcscmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + + return wcscmp(lhs, rhs) == 0; +} + +// Helper function for *_STREQ on wide strings. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual) { + if (String::WideCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// Helper function for *_STRNE on wide strings. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2) { + if (!String::WideCStringEquals(s1, s2)) { + return AssertionSuccess(); + } + + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: " + << PrintToString(s1) + << " vs " << PrintToString(s2); +} + +// Compares two C strings, ignoring case. Returns true iff they have +// the same content. +// +// Unlike strcasecmp(), this function can handle NULL argument(s). A +// NULL C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; +} + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. +bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + +#if GTEST_OS_WINDOWS + return _wcsicmp(lhs, rhs) == 0; +#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID + return wcscasecmp(lhs, rhs) == 0; +#else + // Android, Mac OS X and Cygwin don't define wcscasecmp. + // Other unknown OSes may not define it either. + wint_t left, right; + do { + left = towlower(*lhs++); + right = towlower(*rhs++); + } while (left && left == right); + return left == right; +#endif // OS selector +} + +// Returns true iff str ends with the given suffix, ignoring case. +// Any string is considered to end with an empty suffix. +bool String::EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix) { + const size_t str_len = str.length(); + const size_t suffix_len = suffix.length(); + return (str_len >= suffix_len) && + CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len, + suffix.c_str()); +} + +// Formats an int value as "%02d". +std::string String::FormatIntWidth2(int value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << value; + return ss.str(); +} + +// Formats an int value as "%X". +std::string String::FormatHexInt(int value) { + std::stringstream ss; + ss << std::hex << std::uppercase << value; + return ss.str(); +} + +// Formats a byte as "%02X". +std::string String::FormatByte(unsigned char value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase + << static_cast(value); + return ss.str(); +} + +// Converts the buffer in a stringstream to an std::string, converting NUL +// bytes to "\\0" along the way. +std::string StringStreamToString(::std::stringstream* ss) { + const ::std::string& str = ss->str(); + const char* const start = str.c_str(); + const char* const end = start + str.length(); + + std::string result; + result.reserve(2 * (end - start)); + for (const char* ch = start; ch != end; ++ch) { + if (*ch == '\0') { + result += "\\0"; // Replaces NUL with "\\0"; + } else { + result += *ch; + } + } + + return result; +} + +// Appends the user-supplied message to the Google-Test-generated message. +std::string AppendUserMessage(const std::string& gtest_msg, + const Message& user_msg) { + // Appends the user message if it's non-empty. + const std::string user_msg_string = user_msg.GetString(); + if (user_msg_string.empty()) { + return gtest_msg; + } + + return gtest_msg + "\n" + user_msg_string; +} + +} // namespace internal + +// class TestResult + +// Creates an empty TestResult. +TestResult::TestResult() + : death_test_count_(0), + elapsed_time_(0) { +} + +// D'tor. +TestResult::~TestResult() { +} + +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + +// Adds a test part result to the list. +void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { + test_part_results_.push_back(test_part_result); +} + +// Adds a test property to the list. If a property with the same key as the +// supplied property is already represented, the value of this test_property +// replaces the old value for that key. +void TestResult::RecordProperty(const std::string& xml_element, + const TestProperty& test_property) { + if (!ValidateTestProperty(xml_element, test_property)) { + return; + } + internal::MutexLock lock(&test_properites_mutex_); + const std::vector::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); + return; + } + property_with_matching_key->SetValue(test_property.value()); +} + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuitesAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "random_seed", + "tests", + "time", + "timestamp" +}; + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuiteAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "tests", + "time" +}; + +// The list of reserved attributes used in the element of XML output. +static const char* const kReservedTestCaseAttributes[] = { + "classname", + "name", + "status", + "time", + "type_param", + "value_param" +}; + +template +std::vector ArrayAsVector(const char* const (&array)[kSize]) { + return std::vector(array, array + kSize); +} + +static std::vector GetReservedAttributesForElement( + const std::string& xml_element) { + if (xml_element == "testsuites") { + return ArrayAsVector(kReservedTestSuitesAttributes); + } else if (xml_element == "testsuite") { + return ArrayAsVector(kReservedTestSuiteAttributes); + } else if (xml_element == "testcase") { + return ArrayAsVector(kReservedTestCaseAttributes); + } else { + GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; + } + // This code is unreachable but some compilers may not realizes that. + return std::vector(); +} + +static std::string FormatWordList(const std::vector& words) { + Message word_list; + for (size_t i = 0; i < words.size(); ++i) { + if (i > 0 && words.size() > 2) { + word_list << ", "; + } + if (i == words.size() - 1) { + word_list << "and "; + } + word_list << "'" << words[i] << "'"; + } + return word_list.GetString(); +} + +bool ValidateTestPropertyName(const std::string& property_name, + const std::vector& reserved_names) { + if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != + reserved_names.end()) { + ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name + << " (" << FormatWordList(reserved_names) + << " are reserved by " << GTEST_NAME_ << ")"; + return false; + } + return true; +} + +// Adds a failure if the key is a reserved attribute of the element named +// xml_element. Returns true if the property is valid. +bool TestResult::ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property) { + return ValidateTestPropertyName(test_property.key(), + GetReservedAttributesForElement(xml_element)); +} + +// Clears the object. +void TestResult::Clear() { + test_part_results_.clear(); + test_properties_.clear(); + death_test_count_ = 0; + elapsed_time_ = 0; +} + +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; +} + +// Returns true iff the test part fatally failed. +static bool TestPartFatallyFailed(const TestPartResult& result) { + return result.fatally_failed(); +} + +// Returns true iff the test fatally failed. +bool TestResult::HasFatalFailure() const { + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; +} + +// Gets the number of all test parts. This is the sum of the number +// of successful test parts and the number of failed test parts. +int TestResult::total_part_count() const { + return static_cast(test_part_results_.size()); +} + +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast(test_properties_.size()); +} + +// class Test + +// Creates a Test object. + +// The c'tor saves the values of all Google Test flags. +Test::Test() + : gtest_flag_saver_(new internal::GTestFlagSaver) { +} + +// The d'tor restores the values of all Google Test flags. +Test::~Test() { + delete gtest_flag_saver_; +} + +// Sets up the test fixture. +// +// A sub-class may override this. +void Test::SetUp() { +} + +// Tears down the test fixture. +// +// A sub-class may override this. +void Test::TearDown() { +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, const std::string& value) { + UnitTest::GetInstance()->RecordProperty(key, value); +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, int value) { + Message value_message; + value_message << value; + RecordProperty(key, value_message.GetString().c_str()); +} + +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + ""); // No stack trace, either. +} + +} // namespace internal + +// Google Test requires all tests in the same test case to use the same test +// fixture class. This function checks if the current test has the +// same fixture class as the first test in the current test case. If +// yes, it returns true; otherwise it generates a Google Test failure and +// returns false. +bool Test::HasSameFixtureClass() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + const TestCase* const test_case = impl->current_test_case(); + + // Info about the first test in the current test case. + const TestInfo* const first_test_info = test_case->test_info_list()[0]; + const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; + const char* const first_test_name = first_test_info->name(); + + // Info about the current test. + const TestInfo* const this_test_info = impl->current_test_info(); + const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; + const char* const this_test_name = this_test_info->name(); + + if (this_fixture_id != first_fixture_id) { + // Is the first test defined using TEST? + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); + // Is this test defined using TEST? + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); + + if (first_is_TEST || this_is_TEST) { + // The user mixed TEST and TEST_F in this test case - we'll tell + // him/her how to fix it. + + // Gets the name of the TEST and the name of the TEST_F. Note + // that first_is_TEST and this_is_TEST cannot both be true, as + // the fixture IDs are different for the two tests. + const char* const TEST_name = + first_is_TEST ? first_test_name : this_test_name; + const char* const TEST_F_name = + first_is_TEST ? this_test_name : first_test_name; + + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test case is\n" + << "illegal. In test case " << this_test_info->test_case_name() + << ",\n" + << "test " << TEST_F_name << " is defined using TEST_F but\n" + << "test " << TEST_name << " is defined using TEST. You probably\n" + << "want to change the TEST to TEST_F or move it to another test\n" + << "case."; + } else { + // The user defined two fixture classes with the same name in + // two namespaces - we'll tell him/her how to fix it. + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " + << this_test_info->test_case_name() << ",\n" + << "you defined test " << first_test_name + << " and test " << this_test_name << "\n" + << "using two different test fixture classes. This can happen if\n" + << "the two classes are from different namespaces or translation\n" + << "units and have the same name. You should probably rename one\n" + << "of the classes to put the tests into different test cases."; + } + return false; + } + + return true; +} + +#if GTEST_HAS_SEH + +// Adds an "exception thrown" fatal failure to the current test. This +// function returns its result via an output parameter pointer because VC++ +// prohibits creation of objects with destructors on stack in functions +// using __try (see error C2712). +static std::string* FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << + exception_code << std::setbase(10) << " thrown in " << location << "."; + + return new std::string(message.GetString()); +} + +#endif // GTEST_HAS_SEH + +namespace internal { + +#if GTEST_HAS_EXCEPTIONS + +// Adds an "exception thrown" fatal failure to the current test. +static std::string FormatCxxExceptionMessage(const char* description, + const char* location) { + Message message; + if (description != NULL) { + message << "C++ exception with description \"" << description << "\""; + } else { + message << "Unknown C++ exception"; + } + message << " thrown in " << location << "."; + + return message.GetString(); +} + +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result); + +GoogleTestFailureException::GoogleTestFailureException( + const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} + +#endif // GTEST_HAS_EXCEPTIONS + +// We put these helper functions in the internal namespace as IBM's xlC +// compiler rejects the code if they were declared static. + +// Runs the given method and handles SEH exceptions it throws, when +// SEH is supported; returns the 0-value for type Result in case of an +// SEH exception. (Microsoft compilers cannot handle SEH and C++ +// exceptions in the same function. Therefore, we provide a separate +// wrapper function for handling SEH exceptions.) +template +Result HandleSehExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { +#if GTEST_HAS_SEH + __try { + return (object->*method)(); + } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT + GetExceptionCode())) { + // We create the exception message on the heap because VC++ prohibits + // creation of objects with destructors on stack in functions using __try + // (see error C2712). + std::string* exception_message = FormatSehExceptionMessage( + GetExceptionCode(), location); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + *exception_message); + delete exception_message; + return static_cast(0); + } +#else + (void)location; + return (object->*method)(); +#endif // GTEST_HAS_SEH +} + +// Runs the given method and catches and reports C++ and/or SEH-style +// exceptions, if they are supported; returns the 0-value for type +// Result in case of an SEH exception. +template +Result HandleExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { + // NOTE: The user code can affect the way in which Google Test handles + // exceptions by setting GTEST_FLAG(catch_exceptions), but only before + // RUN_ALL_TESTS() starts. It is technically possible to check the flag + // after the exception is caught and either report or re-throw the + // exception based on the flag's value: + // + // try { + // // Perform the test method. + // } catch (...) { + // if (GTEST_FLAG(catch_exceptions)) + // // Report the exception as failure. + // else + // throw; // Re-throws the original exception. + // } + // + // However, the purpose of this flag is to allow the program to drop into + // the debugger when the exception is thrown. On most platforms, once the + // control enters the catch block, the exception origin information is + // lost and the debugger will stop the program at the point of the + // re-throw in this function -- instead of at the point of the original + // throw statement in the code under test. For this reason, we perform + // the check early, sacrificing the ability to affect Google Test's + // exception handling in the method where the exception is thrown. + if (internal::GetUnitTestImpl()->catch_exceptions()) { +#if GTEST_HAS_EXCEPTIONS + try { + return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const internal::GoogleTestFailureException&) { // NOLINT + // This exception type can only be thrown by a failed Google + // Test assertion with the intention of letting another testing + // framework catch it. Therefore we just re-throw it. + throw; + } catch (const std::exception& e) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(e.what(), location)); + } catch (...) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(NULL, location)); + } + return static_cast(0); +#else + return HandleSehExceptionsInMethodIfSupported(object, method, location); +#endif // GTEST_HAS_EXCEPTIONS + } else { + return (object->*method)(); + } +} + +} // namespace internal + +// Runs the test and updates the test result. +void Test::Run() { + if (!HasSameFixtureClass()) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); + // We will run the test only if SetUp() was successful. + if (!HasFatalFailure()) { + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TestBody, "the test body"); + } + + // However, we want to clean up as much as possible. Hence we will + // always call TearDown(), even if SetUp() or the test body has + // failed. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TearDown, "TearDown()"); +} + +// Returns true iff the current test has a fatal failure. +bool Test::HasFatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); +} + +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + +// class TestInfo + +// Constructs a TestInfo object. It assumes ownership of the test factory +// object. +TestInfo::TestInfo(const std::string& a_test_case_name, + const std::string& a_name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory) + : test_case_name_(a_test_case_name), + name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + value_param_(a_value_param ? new std::string(a_value_param) : NULL), + fixture_class_id_(fixture_class_id), + should_run_(false), + is_disabled_(false), + matches_filter_(false), + factory_(factory), + result_() {} + +// Destructs a TestInfo object. +TestInfo::~TestInfo() { delete factory_; } + +namespace internal { + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param: the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param: text representation of the test's value parameter, +// or NULL if this is not a value-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory) { + TestInfo* const test_info = + new TestInfo(test_case_name, name, type_param, value_param, + fixture_class_id, factory); + GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); + return test_info; +} + +#if GTEST_HAS_PARAM_TEST +void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line) { + Message errors; + errors + << "Attempted redefinition of test case " << test_case_name << ".\n" + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " << test_case_name << ", you tried\n" + << "to define a test using a fixture class different from the one\n" + << "used earlier. This can happen if the two fixture classes are\n" + << "from different namespaces and have the same name. You should\n" + << "probably rename one of the classes to put the tests into different\n" + << "test cases."; + + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors.GetString().c_str()); +} +#endif // GTEST_HAS_PARAM_TEST + +} // namespace internal + +namespace { + +// A predicate that checks the test name of a TestInfo against a known +// value. +// +// This is used for implementation of the TestCase class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestNameIs is copyable. +class TestNameIs { + public: + // Constructor. + // + // TestNameIs has NO default constructor. + explicit TestNameIs(const char* name) + : name_(name) {} + + // Returns true iff the test name of test_info matches name_. + bool operator()(const TestInfo * test_info) const { + return test_info && test_info->name() == name_; + } + + private: + std::string name_; +}; + +} // namespace + +namespace internal { + +// This method expands all parameterized tests registered with macros TEST_P +// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// This will be done just once during the program runtime. +void UnitTestImpl::RegisterParameterizedTests() { +#if GTEST_HAS_PARAM_TEST + if (!parameterized_tests_registered_) { + parameterized_test_registry_.RegisterTests(); + parameterized_tests_registered_ = true; + } +#endif +} + +} // namespace internal + +// Creates the test object, runs it, records its result, and then +// deletes it. +void TestInfo::Run() { + if (!should_run_) return; + + // Tells UnitTest where to store test result. + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_info(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*this); + + const TimeInMillis start = internal::GetTimeInMillis(); + + impl->os_stack_trace_getter()->UponLeavingGTest(); + + // Creates the test object. + Test* const test = internal::HandleExceptionsInMethodIfSupported( + factory_, &internal::TestFactoryBase::CreateTest, + "the test fixture's constructor"); + + // Runs the test only if the test object was created and its + // constructor didn't generate a fatal failure. + if ((test != NULL) && !Test::HasFatalFailure()) { + // This doesn't throw as all user code that can throw are wrapped into + // exception handling code. + test->Run(); + } + + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + + result_.set_elapsed_time(internal::GetTimeInMillis() - start); + + // Notifies the unit test event listener that a test has just finished. + repeater->OnTestEnd(*this); + + // Tells UnitTest to stop associating assertion results to this + // test. + impl->set_current_test_info(NULL); +} + +// class TestCase + +// Gets the number of successful tests in this test case. +int TestCase::successful_test_count() const { + return CountIf(test_info_list_, TestPassed); +} + +// Gets the number of failed tests in this test case. +int TestCase::failed_test_count() const { + return CountIf(test_info_list_, TestFailed); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int TestCase::reportable_disabled_test_count() const { + return CountIf(test_info_list_, TestReportableDisabled); +} + +// Gets the number of disabled tests in this test case. +int TestCase::disabled_test_count() const { + return CountIf(test_info_list_, TestDisabled); +} + +// Gets the number of tests to be printed in the XML report. +int TestCase::reportable_test_count() const { + return CountIf(test_info_list_, TestReportable); +} + +// Get the number of tests in this test case that should run. +int TestCase::test_to_run_count() const { + return CountIf(test_info_list_, ShouldRunTest); +} + +// Gets the number of all tests. +int TestCase::total_test_count() const { + return static_cast(test_info_list_.size()); +} + +// Creates a TestCase with the given name. +// +// Arguments: +// +// name: name of the test case +// a_type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase::TestCase(const char* a_name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) + : name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + set_up_tc_(set_up_tc), + tear_down_tc_(tear_down_tc), + should_run_(false), + elapsed_time_(0) { +} + +// Destructor of TestCase. +TestCase::~TestCase() { + // Deletes every Test in the collection. + ForEach(test_info_list_, internal::Delete); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Adds a test to this test case. Will delete the test upon +// destruction of the TestCase object. +void TestCase::AddTestInfo(TestInfo * test_info) { + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast(test_indices_.size())); +} + +// Runs every test in this TestCase. +void TestCase::Run() { + if (!should_run_) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_case(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + repeater->OnTestCaseStart(*this); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + + const internal::TimeInMillis start = internal::GetTimeInMillis(); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->Run(); + } + elapsed_time_ = internal::GetTimeInMillis() - start; + + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + + repeater->OnTestCaseEnd(*this); + impl->set_current_test_case(NULL); +} + +// Clears the results of all tests in this test case. +void TestCase::ClearResult() { + ad_hoc_test_result_.Clear(); + ForEach(test_info_list_, TestInfo::ClearTestResult); +} + +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast(i); + } +} + +// Formats a countable noun. Depending on its quantity, either the +// singular form or the plural form is used. e.g. +// +// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". +// FormatCountableNoun(5, "book", "books") returns "5 books". +static std::string FormatCountableNoun(int count, + const char * singular_form, + const char * plural_form) { + return internal::StreamableToString(count) + " " + + (count == 1 ? singular_form : plural_form); +} + +// Formats the count of tests. +static std::string FormatTestCount(int test_count) { + return FormatCountableNoun(test_count, "test", "tests"); +} + +// Formats the count of test cases. +static std::string FormatTestCaseCount(int test_case_count) { + return FormatCountableNoun(test_case_count, "test case", "test cases"); +} + +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { + switch (type) { + case TestPartResult::kSuccess: + return "Success"; + + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: +#ifdef _MSC_VER + return "error: "; +#else + return "Failure\n"; +#endif + default: + return "Unknown result type"; + } +} + +namespace internal { + +// Prints a TestPartResult to an std::string. +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + +// Prints a TestPartResult. +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const std::string& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); + fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif +} + +// class PrettyUnitTestResultPrinter + +enum GTestColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW +}; + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns the character attribute for the given color. +WORD GetColorAttribute(GTestColor color) { + switch (color) { + case COLOR_RED: return FOREGROUND_RED; + case COLOR_GREEN: return FOREGROUND_GREEN; + case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; + } +} + +#else + +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. +const char* GetAnsiColorCode(GTestColor color) { + switch (color) { + case COLOR_RED: return "1"; + case COLOR_GREEN: return "2"; + case COLOR_YELLOW: return "3"; + default: return NULL; + }; +} + +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns true iff Google Test should use colors in the output. +bool ShouldUseColor(bool stdout_is_tty) { + const char* const gtest_color = GTEST_FLAG(color).c_str(); + + if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { +#if GTEST_OS_WINDOWS + // On Windows the TERM variable is usually not set, but the + // console there does support colors. + return stdout_is_tty; +#else + // On non-Windows platforms, we rely on the TERM variable. + const char* const term = posix::GetEnv("TERM"); + const bool term_supports_color = + String::CStringEquals(term, "xterm") || + String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "screen") || + String::CStringEquals(term, "screen-256color") || + String::CStringEquals(term, "linux") || + String::CStringEquals(term, "cygwin"); + return stdout_is_tty && term_supports_color; +#endif // GTEST_OS_WINDOWS + } + + return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || + String::CaseInsensitiveCStringEquals(gtest_color, "true") || + String::CaseInsensitiveCStringEquals(gtest_color, "t") || + String::CStringEquals(gtest_color, "1"); + // We take "yes", "true", "t", and "1" as meaning "yes". If the + // value is neither one of these nor "auto", we treat it as "no" to + // be conservative. +} + +// Helpers for printing colored strings to stdout. Note that on Windows, we +// cannot simply emit special characters and have the terminal change colors. +// This routine must actually emit the characters rather than return a string +// that would be colored when printed, as can be done on Linux. +void ColoredPrintf(GTestColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS + const bool use_color = false; +#else + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + // The '!= 0' comparison is necessary to satisfy MSVC 7.1. + + if (!use_color) { + vprintf(fmt, args); + va_end(args); + return; + } + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetColorAttribute(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + printf("\033[0;3%sm", GetAnsiColorCode(color)); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + va_end(args); +} + +// Text printed in Google Test's text output and --gunit_list_tests +// output to label the type parameter and value parameter for a test. +static const char kTypeParamLabel[] = "TypeParam"; +static const char kValueParamLabel[] = "GetParam()"; + +void PrintFullTestCommentIfPresent(const TestInfo& test_info) { + const char* const type_param = test_info.type_param(); + const char* const value_param = test_info.value_param(); + + if (type_param != NULL || value_param != NULL) { + printf(", where "); + if (type_param != NULL) { + printf("%s = %s", kTypeParamLabel, type_param); + if (value_param != NULL) + printf(" and "); + } + if (value_param != NULL) { + printf("%s = %s", kValueParamLabel, value_param); + } + } +} + +// This class implements the TestEventListener interface. +// +// Class PrettyUnitTestResultPrinter is copyable. +class PrettyUnitTestResultPrinter : public TestEventListener { + public: + PrettyUnitTestResultPrinter() {} + static void PrintTestName(const char * test_case, const char * test) { + printf("%s.%s", test_case, test); + } + + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + + private: + static void PrintFailedTests(const UnitTest& unit_test); +}; + + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); + + // Prints the filter if it's not *. This reminds the user that some + // tests may be skipped. + if (!String::CStringEquals(filter, kUniversalFilter)) { + ColoredPrintf(COLOR_YELLOW, + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %d of %s.\n", + static_cast(shard_index) + 1, + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); + } + + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("Running %s from %s.\n", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment set-up.\n"); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_case.name()); + if (test_case.type_param() == NULL) { + printf("\n"); + } else { + printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { + ColoredPrintf(COLOR_GREEN, "[ RUN ] "); + PrintTestName(test_info.test_case_name(), test_info.name()); + printf("\n"); + fflush(stdout); +} + +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { + ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else { + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + } + PrintTestName(test_info.test_case_name(), test_info.name()); + if (test_info.result()->Failed()) + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", internal::StreamableToString( + test_info.result()->elapsed_time()).c_str()); + } else { + printf("\n"); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; + + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case.name(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment tear-down\n"); + fflush(stdout); +} + +// Internal helper for printing the list of failed tests. +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); + if (failed_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { + continue; + } + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s.%s", test_case.name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + printf("\n"); + } + } +} + +void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); + PrintFailedTests(unit_test); + printf("\n%2d FAILED %s\n", num_failures, + num_failures == 1 ? "TEST" : "TESTS"); + } + + int num_disabled = unit_test.reportable_disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (!num_failures) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(COLOR_YELLOW, + " YOU HAVE %d DISABLED %s\n\n", + num_disabled, + num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End PrettyUnitTestResultPrinter + +// class TestEventRepeater +// +// This class forwards events to other event listeners. +class TestEventRepeater : public TestEventListener { + public: + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); + + private: + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector listeners_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); +}; + +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete); +} + +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); +} + +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. +#define GTEST_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} + +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) + +#undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ + +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater + +// This class generates an XML output file. +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit XmlUnitTestResultPrinter(const char* output_file); + + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + + private: + // Is c a whitespace character that is normalized to a space character + // when it appears in an XML attribute value? + static bool IsNormalizableWhitespace(char c) { + return c == 0x9 || c == 0xA || c == 0xD; + } + + // May c appear in a well-formed XML document? + static bool IsValidXmlCharacter(char c) { + return IsNormalizableWhitespace(c) || c >= 0x20; + } + + // Returns an XML-escaped copy of the input string str. If + // is_attribute is true, the text is meant to appear as an attribute + // value, and normalizable whitespace is preserved by replacing it + // with character references. + static std::string EscapeXml(const std::string& str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static std::string RemoveInvalidXmlCharacters(const std::string& str); + + // Convenience wrapper around EscapeXml when str is an attribute value. + static std::string EscapeXmlAttribute(const std::string& str) { + return EscapeXml(str, true); + } + + // Convenience wrapper around EscapeXml when str is not an attribute value. + static std::string EscapeXmlText(const char* str) { + return EscapeXml(str, false); + } + + // Verifies that the given attribute belongs to the given element and + // streams the attribute as XML. + static void OutputXmlAttribute(std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value); + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); + + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); + + // Prints an XML representation of a TestCase object + static void PrintXmlTestCase(::std::ostream* stream, + const TestCase& test_case); + + // Prints an XML summary of unit_test to output stream out. + static void PrintXmlUnitTest(::std::ostream* stream, + const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as space + // delimited XML attributes based on the property key="value" pairs. + // When the std::string is not empty, it includes a space at the beginning, + // to delimit this attribute from prior attributes. + static std::string TestPropertiesAsXmlAttributes(const TestResult& result); + + // The output file. + const std::string output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); +}; + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.c_str() == NULL || output_file_.empty()) { + fprintf(stderr, "XML output file may not be null\n"); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = NULL; + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + xmlout = posix::FOpen(output_file_.c_str(), "w"); + } + if (xmlout == NULL) { + // TODO(wan): report the reason of the failure. + // + // We don't do it for now as: + // + // 1. There is no urgent need for it. + // 2. It's a bit involved to make the errno variable thread-safe on + // all three operating systems (Linux, Windows, and Mac OS). + // 3. To interpret the meaning of errno in a thread-safe way, + // we need the strerror_r() function, which is not available on + // Windows. + fprintf(stderr, + "Unable to open file \"%s\"\n", + output_file_.c_str()); + fflush(stderr); + exit(EXIT_FAILURE); + } + std::stringstream stream; + PrintXmlUnitTest(&stream, unit_test); + fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); + fclose(xmlout); +} + +// Returns an XML-escaped copy of the input string str. If is_attribute +// is true, the text is meant to appear as an attribute value, and +// normalizable whitespace is preserved by replacing it with character +// references. +// +// Invalid XML characters in str, if any, are stripped from the output. +// It is expected that most, if not all, of the text processed by this +// module will consist of ordinary English text. +// If this module is ever modified to produce version 1.1 XML output, +// most invalid characters can be retained using character references. +// TODO(wan): It might be nice to have a minimally invasive, human-readable +// escaping scheme for invalid characters, rather than dropping them. +std::string XmlUnitTestResultPrinter::EscapeXml( + const std::string& str, bool is_attribute) { + Message m; + + for (size_t i = 0; i < str.size(); ++i) { + const char ch = str[i]; + switch (ch) { + case '<': + m << "<"; + break; + case '>': + m << ">"; + break; + case '&': + m << "&"; + break; + case '\'': + if (is_attribute) + m << "'"; + else + m << '\''; + break; + case '"': + if (is_attribute) + m << """; + else + m << '"'; + break; + default: + if (IsValidXmlCharacter(ch)) { + if (is_attribute && IsNormalizableWhitespace(ch)) + m << "&#x" << String::FormatByte(static_cast(ch)) + << ";"; + else + m << ch; + } + break; + } + } + + return m.GetString(); +} + +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( + const std::string& str) { + std::string output; + output.reserve(str.size()); + for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) + if (IsValidXmlCharacter(*it)) + output.push_back(*it); + + return output; +} + +// The following routines generate an XML representation of a UnitTest +// object. +// +// This is how Google Test concepts map to the DTD: +// +// <-- corresponds to a UnitTest object +// <-- corresponds to a TestCase object +// <-- corresponds to a TestInfo object +// ... +// ... +// ... +// <-- individual assertion failures +// +// +// + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Converts the given epoch time in milliseconds to a date string in the ISO +// 8601 format, without the timezone information. +std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { + // Using non-reentrant version as localtime_r is not portable. + time_t seconds = static_cast(ms / 1000); +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# 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 + const struct tm* const time_struct = localtime(&seconds); // NOLINT +#endif + if (time_struct == NULL) + return ""; // Invalid ms value + + // YYYY-MM-DDThh:mm:ss + return StreamableToString(time_struct->tm_year + 1900) + "-" + + String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + + String::FormatIntWidth2(time_struct->tm_mday) + "T" + + String::FormatIntWidth2(time_struct->tm_hour) + ":" + + String::FormatIntWidth2(time_struct->tm_min) + ":" + + String::FormatIntWidth2(time_struct->tm_sec); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << ""); + if (next_segment != NULL) { + stream->write( + segment, static_cast(next_segment - segment)); + *stream << "]]>]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; +} + +void XmlUnitTestResultPrinter::OutputXmlAttribute( + std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value) { + const std::vector& allowed_names = + GetReservedAttributesForElement(element_name); + + GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != + allowed_names.end()) + << "Attribute " << name << " is not allowed for element <" << element_name + << ">."; + + *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\""; +} + +// Prints an XML representation of a TestInfo object. +// TODO(wan): There is also value in printing properties with the plain printer. +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + const std::string kTestcase = "testcase"; + + *stream << " \n"; + } + const string location = internal::FormatCompilerIndependentFileLocation( + part.file_name(), part.line_number()); + const string summary = location + "\n" + part.summary(); + *stream << " "; + const string detail = location + "\n" + part.message(); + OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str()); + *stream << "\n"; + } + } + + if (failures == 0) + *stream << " />\n"; + else + *stream << " \n"; +} + +// Prints an XML representation of a TestCase object +void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, + const TestCase& test_case) { + const std::string kTestsuite = "testsuite"; + *stream << " <" << kTestsuite; + OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); + OutputXmlAttribute(stream, kTestsuite, "tests", + StreamableToString(test_case.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuite, "failures", + StreamableToString(test_case.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuite, "disabled", + StreamableToString(test_case.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuite, "errors", "0"); + OutputXmlAttribute(stream, kTestsuite, "time", + FormatTimeInMillisAsSeconds(test_case.elapsed_time())); + *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) + << ">\n"; + + for (int i = 0; i < test_case.total_test_count(); ++i) { + if (test_case.GetTestInfo(i)->is_reportable()) + OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); + } + *stream << " \n"; +} + +// Prints an XML summary of unit_test to output stream out. +void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, + const UnitTest& unit_test) { + const std::string kTestsuites = "testsuites"; + + *stream << "\n"; + *stream << "<" << kTestsuites; + + OutputXmlAttribute(stream, kTestsuites, "tests", + StreamableToString(unit_test.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuites, "failures", + StreamableToString(unit_test.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuites, "disabled", + StreamableToString(unit_test.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuites, "errors", "0"); + OutputXmlAttribute( + stream, kTestsuites, "timestamp", + FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); + OutputXmlAttribute(stream, kTestsuites, "time", + FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); + + if (GTEST_FLAG(shuffle)) { + OutputXmlAttribute(stream, kTestsuites, "random_seed", + StreamableToString(unit_test.random_seed())); + } + + *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); + + OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); + *stream << ">\n"; + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + if (unit_test.GetTestCase(i)->reportable_test_count() > 0) + PrintXmlTestCase(stream, *unit_test.GetTestCase(i)); + } + *stream << "\n"; +} + +// Produces a string representing the test properties in a result as space +// delimited XML attributes based on the property key="value" pairs. +std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << " " << property.key() << "=" + << "\"" << EscapeXmlAttribute(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End XmlUnitTestResultPrinter + +#if GTEST_CAN_STREAM_RESULTS_ + +// Checks if str contains '=', '&', '%' or '\n' characters. If yes, +// replaces them by "%xx" where xx is their hexadecimal value. For +// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) +// in both time and space -- important as the input str may contain an +// arbitrarily long test failure message and stack trace. +string StreamingListener::UrlEncode(const char* str) { + string result; + result.reserve(strlen(str) + 1); + for (char ch = *str; ch != '\0'; ch = *++str) { + switch (ch) { + case '%': + case '=': + case '&': + case '\n': + result.append("%" + String::FormatByte(static_cast(ch))); + break; + default: + result.push_back(ch); + break; + } + } + return result; +} + +void StreamingListener::SocketWriter::MakeConnection() { + GTEST_CHECK_(sockfd_ == -1) + << "MakeConnection() can't be called when there is already a connection."; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. + hints.ai_socktype = SOCK_STREAM; + addrinfo* servinfo = NULL; + + // Use the getaddrinfo() to get a linked list of IP addresses for + // the given host name. + const int error_num = getaddrinfo( + host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); + if (error_num != 0) { + GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " + << gai_strerror(error_num); + } + + // Loop through all the results and connect to the first we can. + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + cur_addr = cur_addr->ai_next) { + sockfd_ = socket( + cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); + if (sockfd_ != -1) { + // Connect the client socket to the server socket. + if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { + close(sockfd_); + sockfd_ = -1; + } + } + } + + freeaddrinfo(servinfo); // all done with this structure + + if (sockfd_ == -1) { + GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " + << host_name_ << ":" << port_num_; + } +} + +// End of class Streaming Listener +#endif // GTEST_CAN_STREAM_RESULTS__ + +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message = message.GetString(); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +ScopedTrace::~ScopedTrace() + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + UnitTest::GetInstance()->PopGTestTrace(); +} + + +// class OsStackTraceGetter + +// Returns the current OS stack trace as an std::string. Parameters: +// +// max_depth - the maximum number of stack frames to be included +// in the trace. +// skip_count - the number of top frames to be skipped; doesn't count +// against max_depth. +// +string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */, + int /* skip_count */) + GTEST_LOCK_EXCLUDED_(mutex_) { + return ""; +} + +void OsStackTraceGetter::UponLeavingGTest() + GTEST_LOCK_EXCLUDED_(mutex_) { +} + +const char* const +OsStackTraceGetter::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; + +// A helper class that creates the premature-exit file in its +// constructor and deletes the file in its destructor. +class ScopedPrematureExitFile { + public: + explicit ScopedPrematureExitFile(const char* premature_exit_filepath) + : premature_exit_filepath_(premature_exit_filepath) { + // If a path to the premature-exit file is specified... + if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { + // create the file with a single "0" character in it. I/O + // errors are ignored as there's nothing better we can do and we + // don't want to fail the test because of this. + FILE* pfile = posix::FOpen(premature_exit_filepath, "w"); + fwrite("0", 1, 1, pfile); + fclose(pfile); + } + } + + ~ScopedPrematureExitFile() { + if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { + remove(premature_exit_filepath_); + } + } + + private: + const char* const premature_exit_filepath_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); +}; + +} // namespace internal + +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + +// class UnitTest + +// Gets the singleton UnitTest object. The first time this method is +// called, a UnitTest object is constructed and returned. Consecutive +// calls will return the same object. +// +// We don't protect this under mutex_ as a user is not supposed to +// call this before main() starts, from which point on the return +// value will never change. +UnitTest* UnitTest::GetInstance() { + // When compiled with MSVC 7.1 in optimized mode, destroying the + // UnitTest object upon exiting the program messes up the exit code, + // causing successful tests to appear failed. We have to use a + // different implementation in this case to bypass the compiler bug. + // This implementation makes the compiler happy, at the cost of + // leaking the UnitTest object. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) + static UnitTest* const instance = new UnitTest; + return instance; +#else + static UnitTest instance; + return &instance; +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTest::reportable_disabled_test_count() const { + return impl()->reportable_disabled_test_count(); +} + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTest::reportable_test_count() const { + return impl()->reportable_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the time of the test program start, in ms from the start of the +// UNIX epoch. +internal::TimeInMillis UnitTest::start_timestamp() const { + return impl()->start_timestamp(); +} + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Returns the TestResult containing information on test failures and +// properties logged outside of individual test cases. +const TestResult& UnitTest::ad_hoc_test_result() const { + return *impl()->ad_hoc_test_result(); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); +} + +// Registers and returns a global test environment. When a test +// program is run, all global test environments will be set-up in the +// order they were registered. After all tests in the program have +// finished, all global test environments will be torn-down in the +// *reverse* order they were registered. +// +// The UnitTest object takes ownership of the given environment. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +Environment* UnitTest::AddEnvironment(Environment* env) { + if (env == NULL) { + return NULL; + } + + impl_->environments().push_back(env); + return env; +} + +// Adds a TestPartResult to the current TestResult object. All Google Test +// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call +// this to report their results. The user code should use the +// assertion macros instead of calling this directly. +void UnitTest::AddTestPartResult( + TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) { + Message msg; + msg << message; + + internal::MutexLock lock(&mutex_); + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; + } + } + + if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + msg << internal::kStackTraceMarker << os_stack_trace; + } + + const TestPartResult result = + TestPartResult(result_type, file_name, line_number, + msg.GetString().c_str()); + impl_->GetTestPartResultReporterForCurrentThread()-> + ReportTestPartResult(result); + + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + // Dereference NULL through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: Symbian doesn't implement abort() well, and some debuggers + // don't correctly trap abort(). + *static_cast(NULL) = 1; +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw internal::GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } + } +} + +// Adds a TestProperty to the current TestResult object when invoked from +// inside a test, to current TestCase's ad_hoc_test_result_ when invoked +// from SetUpTestCase or TearDownTestCase, or to the global property set +// when invoked elsewhere. If the result already contains a property with +// the same key, the value will be updated. +void UnitTest::RecordProperty(const std::string& key, + const std::string& value) { + impl_->RecordProperty(TestProperty(key, value)); +} + +// Runs all tests in this UnitTest object and prints the result. +// Returns 0 if successful, or 1 otherwise. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +int UnitTest::Run() { + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Google Test implements this protocol for catching that a test + // program exits before returning control to Google Test: + // + // 1. Upon start, Google Test creates a file whose absolute path + // is specified by the environment variable + // TEST_PREMATURE_EXIT_FILE. + // 2. When Google Test has finished its work, it deletes the file. + // + // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before + // running a Google-Test-based test program and check the existence + // of the file at the end of the test execution to see if it has + // exited prematurely. + + // If we are in the child process of a death test, don't + // create/delete the premature exit file, as doing so is unnecessary + // and will confuse the parent process. Otherwise, create/delete + // the file upon entering/leaving this function. If the program + // somehow exits before this function has a chance to return, the + // premature-exit file will be left undeleted, causing a test runner + // that understands the premature-exit-file protocol to report the + // test as having failed. + const internal::ScopedPrematureExitFile premature_exit_file( + in_death_test_child_process ? + NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); + + // Captures the value of GTEST_FLAG(catch_exceptions). This value will be + // used for the duration of the program. + impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); + +#if GTEST_HAS_SEH + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected. + if (impl()->catch_exceptions() || in_death_test_child_process) { +# if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +# endif // !GTEST_OS_WINDOWS_MOBILE + +# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +# endif + +# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +# endif + } +#endif // GTEST_HAS_SEH + + return internal::HandleExceptionsInMethodIfSupported( + impl(), + &internal::UnitTestImpl::RunAllTests, + "auxiliary test code (environments or event listeners)") ? 0 : 1; +} + +// Returns the working directory when the first TEST() or TEST_F() was +// executed. +const char* UnitTest::original_working_dir() const { + return impl_->original_working_dir_.c_str(); +} + +// Returns the TestCase object for the test that's currently running, +// or NULL if no test is running. +const TestCase* UnitTest::current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_case(); +} + +// Returns the TestInfo object for the test that's currently running, +// or NULL if no test is running. +const TestInfo* UnitTest::current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_info(); +} + +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST +// Returns ParameterizedTestCaseRegistry object used to keep track of +// value-parameterized tests and instantiate and register them. +internal::ParameterizedTestCaseRegistry& + UnitTest::parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_) { + return impl_->parameterized_test_registry(); +} +#endif // GTEST_HAS_PARAM_TEST + +// Creates an empty UnitTest. +UnitTest::UnitTest() { + impl_ = new internal::UnitTestImpl(this); +} + +// Destructor of UnitTest. +UnitTest::~UnitTest() { + delete impl_; +} + +// Pushes a trace defined by SCOPED_TRACE() on to the per-thread +// Google Test trace stack. +void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().push_back(trace); +} + +// Pops a trace from the per-thread Google Test trace stack. +void UnitTest::PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().pop_back(); +} + +namespace internal { + +UnitTestImpl::UnitTestImpl(UnitTest* parent) + : parent_(parent), +#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_per_thread_test_part_result_reporter_(this), +# 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_( + &default_global_test_part_result_reporter_), + per_thread_test_part_result_reporter_( + &default_per_thread_test_part_result_reporter_), +#if GTEST_HAS_PARAM_TEST + parameterized_test_registry_(), + parameterized_tests_registered_(false), +#endif // GTEST_HAS_PARAM_TEST + last_death_test_case_(-1), + current_test_case_(NULL), + current_test_info_(NULL), + ad_hoc_test_result_(), + os_stack_trace_getter_(NULL), + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. + start_timestamp_(0), + elapsed_time_(0), +#if GTEST_HAS_DEATH_TEST + death_test_factory_(new DefaultDeathTestFactory), +#endif + // Will be overridden by the flag before first use. + catch_exceptions_(false) { + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); +} + +UnitTestImpl::~UnitTestImpl() { + // Deletes every TestCase. + ForEach(test_cases_, internal::Delete); + + // Deletes every Environment. + ForEach(environments_, internal::Delete); + + delete os_stack_trace_getter_; +} + +// Adds a TestProperty to the current TestResult object when invoked in a +// context of a test, to current test case's ad_hoc_test_result when invoke +// from SetUpTestCase/TearDownTestCase, or to the global property set +// otherwise. If the result already contains a property with the same key, +// the value will be updated. +void UnitTestImpl::RecordProperty(const TestProperty& test_property) { + std::string xml_element; + TestResult* test_result; // TestResult appropriate for property recording. + + if (current_test_info_ != NULL) { + xml_element = "testcase"; + test_result = &(current_test_info_->result_); + } else if (current_test_case_ != NULL) { + xml_element = "testsuite"; + test_result = &(current_test_case_->ad_hoc_test_result_); + } else { + xml_element = "testsuites"; + test_result = &ad_hoc_test_result_; + } + test_result->RecordProperty(xml_element, test_property); +} + +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const std::string& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +#if GTEST_CAN_STREAM_RESULTS_ +// Initializes event listeners for streaming test results in string form. +// Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureStreamingOutput() { + const std::string& target = GTEST_FLAG(stream_result_to); + if (!target.empty()) { + const size_t pos = target.find(':'); + if (pos != std::string::npos) { + listeners()->Append(new StreamingListener(target.substr(0, pos), + target.substr(pos+1))); + } else { + printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", + target.c_str()); + fflush(stdout); + } + } +} +#endif // GTEST_CAN_STREAM_RESULTS_ + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Configures listeners for streaming test results to the specified server. + ConfigureStreamingOutput(); +#endif // GTEST_CAN_STREAM_RESULTS_ + } +} + +// A predicate that checks the name of a TestCase against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestCaseNameIs is copyable. +class TestCaseNameIs { + public: + // Constructor. + explicit TestCaseNameIs(const std::string& name) + : name_(name) {} + + // Returns true iff the name of test_case matches name_. + bool operator()(const TestCase* test_case) const { + return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + } + + private: + std::string name_; +}; + +// Finds and returns a TestCase with the given name. If one doesn't +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. +// +// Arguments: +// +// test_case_name: name of the test case +// type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) { + // Can we find a TestCase with the given name? + const std::vector::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; + + // No. Let's create one. + TestCase* const new_test_case = + new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(test_case_name, + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); + } + + test_case_indices_.push_back(static_cast(test_case_indices_.size())); + return new_test_case; +} + +// Helpers for setting up / tearing down the given environment. They +// are for use in the ForEach() function. +static void SetUpEnvironment(Environment* env) { env->SetUp(); } +static void TearDownEnvironment(Environment* env) { env->TearDown(); } + +// Runs all tests in this UnitTest object, prints the result, and +// returns true if all tests are successful. If any exception is +// thrown during a test, the test is considered to be failed, but the +// rest of the tests will still be run. +// +// When parameterized tests are enabled, it expands and registers +// parameterized tests first in RegisterParameterizedTests(). +// All other functions called from RunAllTests() may safely assume that +// parameterized tests are ready to be counted and run. +bool UnitTestImpl::RunAllTests() { + // Makes sure InitGoogleTest() was called. + if (!GTestIsInitialized()) { + printf("%s", + "\nThis test program did NOT call ::testing::InitGoogleTest " + "before calling RUN_ALL_TESTS(). Please fix it.\n"); + return false; + } + + // Do not run any test if the --help flag was specified. + if (g_help_flag) + return true; + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); + + // True iff we are in a subprocess for running a thread-safe-style + // death test. + bool in_subprocess_for_death_test = false; + +#if GTEST_HAS_DEATH_TEST + in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); +#endif // GTEST_HAS_DEATH_TEST + + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); + + // Compares the full test names with the filter to decide which + // tests to run. + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return true; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + + // True iff at least one test has failed. + bool failed = false; + + TestEventListener* repeater = listeners()->repeater(); + + start_timestamp_ = GetTimeInMillis(); + repeater->OnTestProgramStart(*parent_); + + // How many times to repeat the tests? We don't want to repeat them + // when we are inside the subprocess of a death test. + const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); + // Repeats forever if the repeat count is negative. + const bool forever = repeat < 0; + for (int i = 0; forever || i != repeat; i++) { + // We want to preserve failures generated by ad-hoc test + // assertions executed before RUN_ALL_TESTS(). + ClearNonAdHocTestResult(); + + const TimeInMillis start = GetTimeInMillis(); + + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + + // Runs each test case if there is at least one test to run. + if (has_tests_to_run) { + // Sets up all environments beforehand. + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); + + // Runs the tests only if there was no fatal failure during global + // set-up. + if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } + } + + // Tears down all environments in reverse order afterwards. + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); + } + + elapsed_time_ = GetTimeInMillis() - start; + + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); + + // Gets the result and clears it. + if (!Passed()) { + failed = true; + } + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } + } + + repeater->OnTestProgramEnd(*parent_); + + return !failed; +} + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + +// Compares the name of each test with the user-specified filter to +// decide whether the test should be run, then records the result in +// each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. +// Returns the number of tests that should run. +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. + int num_runnable_tests = 0; + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; + const std::string &test_case_name = test_case->name(); + test_case->set_should_run(false); + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; + const std::string test_name(test_info->name()); + // A test is disabled if test case name or test name matches + // kDisableTestFilter. + const bool is_disabled = + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); + test_info->is_disabled_ = is_disabled; + + const bool matches_filter = + internal::UnitTestOptions::FilterMatchesTest(test_case_name, + test_name); + test_info->matches_filter_ = matches_filter; + + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; + + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); + + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; + + test_info->should_run_ = is_selected; + test_case->set_should_run(test_case->should_run() || is_selected); + } + } + return num_selected_tests; +} + +// Prints the given C-string on a single line by replacing all '\n' +// characters with string "\\n". If the output takes more than +// max_length characters, only prints the first max_length characters +// and "...". +static void PrintOnOneLine(const char* str, int max_length) { + if (str != NULL) { + for (int i = 0; *str != '\0'; ++str) { + if (i >= max_length) { + printf("..."); + break; + } + if (*str == '\n') { + printf("\\n"); + i += 2; + } else { + printf("%c", *str); + ++i; + } + } + } +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + // Print at most this many characters for each type/value parameter. + const int kMaxParamLength = 250; + + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter_) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.", test_case->name()); + if (test_case->type_param() != NULL) { + printf(" # %s = ", kTypeParamLabel); + // We print the type parameter on a single line to make + // the output easy to parse by a program. + PrintOnOneLine(test_case->type_param(), kMaxParamLength); + } + printf("\n"); + } + printf(" %s", test_info->name()); + if (test_info->value_param() != NULL) { + printf(" # %s = ", kValueParamLabel); + // We print the value parameter on a single line to make the + // output easy to parse by a program. + PrintOnOneLine(test_info->value_param(), kMaxParamLength); + } + printf("\n"); + } + } + } + fflush(stdout); +} + +// Sets the OS stack trace getter. +// +// Does nothing if the input and the current OS stack trace getter are +// the same; otherwise, deletes the old getter and makes the input the +// current getter. +void UnitTestImpl::set_os_stack_trace_getter( + OsStackTraceGetterInterface* getter) { + if (os_stack_trace_getter_ != getter) { + delete os_stack_trace_getter_; + os_stack_trace_getter_ = getter; + } +} + +// Returns the current OS stack trace getter if it is not NULL; +// otherwise, creates an OsStackTraceGetter, makes it the current +// getter, and returns it. +OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { + if (os_stack_trace_getter_ == NULL) { + os_stack_trace_getter_ = new OsStackTraceGetter; + } + + return os_stack_trace_getter_; +} + +// Returns the TestResult for the test that's currently running, or +// the TestResult for the ad hoc test if no test is running. +TestResult* UnitTestImpl::current_test_result() { + return current_test_info_ ? + &(current_test_info_->result_) : &ad_hoc_test_result_; +} + +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast(i); + } +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { + // We pass skip_count + 1 to skip this wrapper function in addition + // to what the user really wants to skip. + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); +} + +// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to +// suppress unreachable code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Parses a string as a command line flag. The string should have +// the format "--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. +const char* ParseFlagValue(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 "--" followed by GTEST_FLAG_PREFIX_. + const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + 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 bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(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 an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, std::string* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(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; +} + +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", std::string(str, p).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +#if GTEST_CAN_STREAM_RESULTS_ +" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" +" Stream test results to the given server.\n" +#endif // GTEST_CAN_STREAM_RESULTS_ +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" +" Do not report exceptions as test failures. Instead, allow them\n" +" to crash the program or throw a pop-up (on Windows).\n" +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. +template +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { + const std::string arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + using internal::ParseBoolFlag; + using internal::ParseInt32Flag; + using internal::ParseStringFlag; + + // Do we see a Google Test flag? + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, + >EST_FLAG(throw_on_failure)) + ) { + // 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--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; + } + } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } +} + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#if GTEST_HAS_DEATH_TEST + + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } + +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); +} + +} // namespace internal + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +void InitGoogleTest(int* argc, char** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleTest(int* argc, wchar_t** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +} // namespace testing +// Copyright 2005, 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), vladl@google.com (Vlad Losev) +// +// This file implements death tests. + + +#if GTEST_HAS_DEATH_TEST + +# if GTEST_OS_MAC +# include +# endif // GTEST_OS_MAC + +# include +# include +# include + +# if GTEST_OS_LINUX +# include +# endif // GTEST_OS_LINUX + +# include + +# if GTEST_OS_WINDOWS +# include +# else +# include +# include +# endif // GTEST_OS_WINDOWS + +# if GTEST_OS_QNX +# include +# endif // GTEST_OS_QNX + +#endif // GTEST_HAS_DEATH_TEST + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +// Constants. + +// The default death test style. +static const char kDefaultDeathTestStyle[] = "fast"; + +GTEST_DEFINE_string_( + death_test_style, + internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), + "Indicates how to run a death test in a forked child process: " + "\"threadsafe\" (child process re-executes the test binary " + "from the beginning, running only the specific death test) or " + "\"fast\" (child process runs the death test immediately " + "after forking)."); + +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + +namespace internal { +GTEST_DEFINE_string_( + internal_run_death_test, "", + "Indicates the file, line number, temporal index of " + "the single death test to run, and a file descriptor to " + "which a success code may be sent, all separated by " + "the '|' characters. This flag is specified if and only if the current " + "process is a sub-process launched for running a thread-safe " + "death test. FOR INTERNAL USE ONLY."); +} // namespace internal + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Valid only for fast death tests. Indicates the code is running in the +// child process of a fast style death test. +static bool g_in_fast_death_test_child = false; + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +bool InDeathTestChild() { +# if GTEST_OS_WINDOWS + + // On Windows, death tests are thread-safe regardless of the value of the + // death_test_style flag. + return !GTEST_FLAG(internal_run_death_test).empty(); + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") + return !GTEST_FLAG(internal_run_death_test).empty(); + else + return g_in_fast_death_test_child; +#endif +} + +} // namespace internal + +// ExitedWithCode constructor. +ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { +} + +// ExitedWithCode function-call operator. +bool ExitedWithCode::operator()(int exit_status) const { +# if GTEST_OS_WINDOWS + + return exit_status == exit_code_; + +# else + + return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; + +# endif // GTEST_OS_WINDOWS +} + +# if !GTEST_OS_WINDOWS +// KilledBySignal constructor. +KilledBySignal::KilledBySignal(int signum) : signum_(signum) { +} + +// KilledBySignal function-call operator. +bool KilledBySignal::operator()(int exit_status) const { + return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; +} +# endif // !GTEST_OS_WINDOWS + +namespace internal { + +// Utilities needed for death tests. + +// Generates a textual description of a given exit code, in the format +// specified by wait(2). +static std::string ExitSummary(int exit_code) { + Message m; + +# if GTEST_OS_WINDOWS + + m << "Exited with exit status " << exit_code; + +# else + + if (WIFEXITED(exit_code)) { + m << "Exited with exit status " << WEXITSTATUS(exit_code); + } else if (WIFSIGNALED(exit_code)) { + m << "Terminated by signal " << WTERMSIG(exit_code); + } +# ifdef WCOREDUMP + if (WCOREDUMP(exit_code)) { + m << " (core dumped)"; + } +# endif +# endif // GTEST_OS_WINDOWS + + return m.GetString(); +} + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +bool ExitedUnsuccessfully(int exit_status) { + return !ExitedWithCode(0)(exit_status); +} + +# if !GTEST_OS_WINDOWS +// Generates a textual failure message when a death test finds more than +// one thread running, or cannot determine the number of threads, prior +// to executing the given statement. It is the responsibility of the +// caller not to pass a thread_count of 1. +static std::string DeathTestThreadWarning(size_t thread_count) { + Message msg; + msg << "Death tests use fork(), which is unsafe particularly" + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; + if (thread_count == 0) + msg << "couldn't detect the number of threads."; + else + msg << "detected " << thread_count << " threads."; + return msg.GetString(); +} +# endif // !GTEST_OS_WINDOWS + +// Flag characters for reporting a death test that did not die. +static const char kDeathTestLived = 'L'; +static const char kDeathTestReturned = 'R'; +static const char kDeathTestThrew = 'T'; +static const char kDeathTestInternalError = 'I'; + +// An enumeration describing all of the possible ways that a death test can +// conclude. DIED means that the process died while executing the test +// code; LIVED means that process lived beyond the end of the test code; +// RETURNED means that the test statement attempted to execute a return +// statement, which is not allowed; THREW means that the test statement +// returned control by throwing an exception. IN_PROGRESS means the test +// has not yet concluded. +// TODO(vladl@google.com): Unify names and possibly values for +// AbortReason, DeathTestOutcome, and flag characters above. +enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; + +// Routine for aborting the program which is safe to call from an +// exec-style death test child process, in which case the error +// message is propagated back to the parent process. Otherwise, the +// message is simply printed to stderr. In either case, the program +// then exits with status 1. +void DeathTestAbort(const std::string& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. + const InternalRunDeathTestFlag* const flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + if (flag != NULL) { + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); + fputc(kDeathTestInternalError, parent); + fprintf(parent, "%s", message.c_str()); + fflush(parent); + _exit(1); + } else { + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); + posix::Abort(); + } +} + +// A replacement for CHECK that calls DeathTestAbort if the assertion +// fails. +# define GTEST_DEATH_TEST_CHECK_(expression) \ + do { \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for +// evaluating any system call that fulfills two conditions: it must return +// -1 on failure, and set errno to EINTR when it is interrupted and +// should be tried again. The macro expands to a loop that repeatedly +// evaluates the expression as long as it evaluates to -1 and sets +// errno to EINTR. If the expression evaluates to -1 but errno is +// something other than EINTR, DeathTestAbort is called. +# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ + do { \ + int gtest_retval; \ + do { \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression + " != -1"); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +std::string GetLastErrnoDescription() { + return errno == 0 ? "" : posix::StrError(errno); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} + +// Death test constructor. Increments the running death test count +// for the current test. +DeathTest::DeathTest() { + TestInfo* const info = GetUnitTestImpl()->current_test_info(); + if (info == NULL) { + DeathTestAbort("Cannot run a death test outside of a TEST or " + "TEST_F construct"); + } +} + +// Creates and returns a death test by dispatching to the current +// death test factory. +bool DeathTest::Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) { + return GetUnitTestImpl()->death_test_factory()->Create( + statement, regex, file, line, test); +} + +const char* DeathTest::LastMessage() { + return last_death_test_message_.c_str(); +} + +void DeathTest::set_last_death_test_message(const std::string& message) { + last_death_test_message_ = message; +} + +std::string DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } + void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } + void set_write_fd(int fd) { write_fd_ = fd; } + + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + + private: + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. + const char* const statement_; + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // True if the death test child process has been successfully spawned. + bool spawned_; + // The exit status of the child process. + int status_; + // How the death test concluded. + DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; +}; + +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; + + // The read() here blocks until data is available (signifying the + // failure of the death test) or until the pipe is closed (signifying + // its success), so it's okay to call this in the parent before + // the child process has exited. + do { + bytes_read = posix::Read(read_fd(), &flag, 1); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestThrew: + set_outcome(THREW); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_fd()); // Does not return. + break; + default: + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast(flag) << ")"; + } + } else { + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); + } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} + +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : + reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; + + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + // We are leaking the descriptor here because on some platforms (i.e., + // when built as Windows DLL), destructors of global objects will still + // run after calling _exit(). On such systems, write_fd_ will be + // indirectly closed from the destructor of UnitTestImpl, causing double + // close if it is also closed here. On debug configurations, double close + // may assert. As there are no in-process buffers to flush here, we are + // relying on the OS to close the descriptor after the process terminates + // when the destructors are not run. + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// Returns an indented copy of stderr output for a death test. +// This makes distinguishing death test output lines from regular log lines +// much easier. +static ::std::string FormatDeathTestOutput(const ::std::string& output) { + ::std::string ret; + for (size_t at = 0; ; ) { + const size_t line_end = output.find('\n', at); + ret += "[ DEATH ] "; + if (line_end == ::std::string::npos) { + ret += output.substr(at); + break; + } + ret += output.substr(at, line_end + 1 - at); + at = line_end + 1; + } + return ret; +} + +// Assesses the success or failure of a death test, using both private +// members which have previously been set, and one argument: +// +// Private data members: +// outcome: An enumeration describing how the death test +// concluded: DIED, LIVED, THREW, or RETURNED. The death test +// fails in the latter three cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to +// the test's captured standard error output; the death test +// fails if it does not match. +// +// Argument: +// status_ok: true if exit_status is acceptable in the context of +// this particular death test, which fails if it is false +// +// Returns true iff all of the above conditions are met. Otherwise, the +// first failing condition, in the order given above, is the one that is +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) + return false; + + const std::string error_message = GetCapturedStderr(); + + bool success = false; + Message buffer; + + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { + case LIVED: + buffer << " Result: failed to die.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case THREW: + buffer << " Result: threw an exception.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case RETURNED: + buffer << " Result: illegal return in test statement.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case DIED: + if (status_ok) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { + success = true; + } else { + buffer << " Result: died but not with expected error.\n" + << " Expected: " << regex()->pattern() << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + } else { + buffer << " Result: died but not with expected exit code:\n" + << " " << ExitSummary(status()) << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + break; + case IN_PROGRESS: + default: + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; + } + + DeathTest::set_last_death_test_message(buffer.GetString()); + return success; +} + +# if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status_code; + GTEST_DEATH_TEST_CHECK_( + ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); + child_handle_.Reset(); + set_status(static_cast(status_code)); + return status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + + "=" + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(static_cast(::GetCurrentProcessId())) + + // size_t has the same width as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + "|" + StreamableToString(reinterpret_cast(write_handle)) + + "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + std::string command_line = + std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + + internal_flag + "\""; + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +# else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; +} + +// A concrete death test class that forks, then immediately runs the test +// in the child process. +class NoExecDeathTest : public ForkingDeathTest { + public: + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } + virtual TestRole AssumeRole(); +}; + +// The AssumeRole process for a fork-and-run death test. It implements a +// straightforward fork, with a simple pipe to transmit the status byte. +DeathTest::TestRole NoExecDeathTest::AssumeRole() { + const size_t thread_count = GetThreadCount(); + if (thread_count != 1) { + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + + DeathTest::set_last_death_test_message(""); + CaptureStderr(); + // When we fork the process below, the log file buffers are copied, but the + // file descriptors are shared. We flush all log files here so that closing + // the file descriptors in the child process doesn't throw off the + // synchronization between descriptors and buffers in the parent process. + // This is as close to the fork as possible to avoid a race condition in case + // there are multiple threads running before the death test, and another + // thread writes to the log file. + FlushInfoLog(); + + const pid_t child_pid = fork(); + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + set_child_pid(child_pid); + if (child_pid == 0) { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); + set_write_fd(pipe_fd[1]); + // Redirects all logging to stderr in the child process to prevent + // concurrent writes to the log files. We capture stderr in the parent + // process and append the child process' output to a log. + LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); + g_in_fast_death_test_child = true; + return EXECUTE_TEST; + } else { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; + } +} + +// A concrete death test class that forks and re-executes the main +// program from the beginning, with command-line flags set that cause +// only this specific death test to be run. +class ExecDeathTest : public ForkingDeathTest { + public: + ExecDeathTest(const char* a_statement, const RE* a_regex, + const char* file, int line) : + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } + virtual TestRole AssumeRole(); + private: + static ::std::vector + GetArgvsForDeathTestChildProcess() { + ::std::vector args = GetInjectableArgvs(); + return args; + } + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + + private: + std::vector args_; +}; + +// A struct that encompasses the arguments to the child process of a +// threadsafe-style death test process. +struct ExecDeathTestArgs { + char* const* argv; // Command-line arguments for the child's call to exec + int close_fd; // File descriptor to close; the read end of a pipe +}; + +# if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +# else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +# endif // GTEST_OS_MAC + +# if !GTEST_OS_QNX +// The main function for a threadsafe-style death test child process. +// This function is called in a clone()-ed process and thus must avoid +// any potentially unsafe operations like malloc or libc functions. +static int ExecDeathTestChildMain(void* child_arg) { + ExecDeathTestArgs* const args = static_cast(child_arg); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); + + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + // We can safely call execve() as it's a direct system call. We + // cannot use execvp() as it's a libc function and thus potentially + // unsafe. Since execve() doesn't search the PATH, the user must + // invoke the test program via a valid path that contains at least + // one path separator. + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " + + original_dir + " failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; +} +# endif // !GTEST_OS_QNX + +// Two utility routines that together determine the direction the stack +// grows. +// This could be accomplished more elegantly by a single recursive +// function, but we want to guard against the unlikely possibility of +// a smart compiler optimizing the recursion away. +// +// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining +// StackLowerThanAddress into StackGrowsDown, which then doesn't give +// correct answer. +void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; +void StackLowerThanAddress(const void* ptr, bool* result) { + int dummy; + *result = (&dummy < ptr); +} + +bool StackGrowsDown() { + int dummy; + bool result; + StackLowerThanAddress(&dummy, &result); + return result; +} + +// Spawns a child process with the same executable as the current process in +// a thread-safe manner and instructs it to run the death test. The +// implementation uses fork(2) + exec. On systems where clone(2) is +// available, it is used instead, being slightly more thread-safe. On QNX, +// fork supports only single-threaded environments, so this function uses +// spawn(2) there instead. The function dies with an error message if +// anything goes wrong. +static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { + ExecDeathTestArgs args = { argv, close_fd }; + pid_t child_pid = -1; + +# if GTEST_OS_QNX + // Obtains the current directory and sets it to be closed in the child + // process. + const int cwd_fd = open(".", O_RDONLY); + GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + int fd_flags; + // Set close_fd to be closed after spawn. + GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, + fd_flags | FD_CLOEXEC)); + struct inheritance inherit = {0}; + // spawn is a system call. + child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); + // Restores the current working directory. + GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); + +# else // GTEST_OS_QNX +# if GTEST_OS_LINUX + // When a SIGPROF signal is received while fork() or clone() are executing, + // the process may hang. To avoid this, we ignore SIGPROF here and re-enable + // it after the call to fork()/clone() is complete. + struct sigaction saved_sigprof_action; + struct sigaction ignore_sigprof_action; + memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); + sigemptyset(&ignore_sigprof_action.sa_mask); + ignore_sigprof_action.sa_handler = SIG_IGN; + GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( + SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); +# endif // GTEST_OS_LINUX + +# if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + + // Maximum stack alignment in bytes: For a downward-growing stack, this + // amount is subtracted from size of the stack space to get an address + // that is within the stack space and is aligned on all systems we care + // about. As far as I know there is no ABI with stack alignment greater + // than 64. We assume stack and stack_size already have alignment of + // kMaxStackAlignment. + const size_t kMaxStackAlignment = 64; + void* const stack_top = + static_cast(stack) + + (stack_grows_down ? stack_size - kMaxStackAlignment : 0); + GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && + reinterpret_cast(stack_top) % kMaxStackAlignment == 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +# else + const bool use_fork = true; +# endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } +# endif // GTEST_OS_QNX +# if GTEST_OS_LINUX + GTEST_DEATH_TEST_CHECK_SYSCALL_( + sigaction(SIGPROF, &saved_sigprof_action, NULL)); +# endif // GTEST_OS_LINUX + + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + return child_pid; +} + +// The AssumeRole process for a fork-and-exec death test. It re-executes the +// main program from the beginning, setting the --gtest_filter +// and --gtest_internal_run_death_test flags to cause only the current +// death test to be re-run. +DeathTest::TestRole ExecDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + // Clear the close-on-exec flag on the write end of the pipe, lest + // it be closed when the child process does an exec: + GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); + + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(pipe_fd[1]); + Arguments args; + args.AddArguments(GetArgvsForDeathTestChildProcess()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // See the comment in NoExecDeathTest::AssumeRole for why the next line + // is necessary. + FlushInfoLog(); + + const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_child_pid(child_pid); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; +} + +# endif // !GTEST_OS_WINDOWS + +// Creates a concrete DeathTest-derived class that depends on the +// --gtest_death_test_style flag, and sets the pointer pointed to +// by the "test" argument to its address. If the test should be +// skipped, sets that pointer to NULL. Returns true, unless the +// flag is set to an invalid value. +bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, + const char* file, int line, + DeathTest** test) { + UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const int death_test_index = impl->current_test_info() + ->increment_death_test_count(); + + if (flag != NULL) { + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message( + "Death test count (" + StreamableToString(death_test_index) + + ") somehow exceeded expected maximum (" + + StreamableToString(flag->index()) + ")"); + return false; + } + + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { + *test = NULL; + return true; + } + } + +# if GTEST_OS_WINDOWS + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") { + *test = new ExecDeathTest(statement, regex, file, line); + } else if (GTEST_FLAG(death_test_style) == "fast") { + *test = new NoExecDeathTest(statement, regex); + } + +# endif // GTEST_OS_WINDOWS + + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message( + "Unknown death test style \"" + GTEST_FLAG(death_test_style) + + "\" encountered"); + return false; + } + + return true; +} + +// Splits a given string on a given delimiter, populating a given +// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have +// ::std::string, so we can use it here. +static void SplitString(const ::std::string& str, char delimiter, + ::std::vector< ::std::string>* dest) { + ::std::vector< ::std::string> parsed; + ::std::string::size_type pos = 0; + while (::testing::internal::AlwaysTrue()) { + const ::std::string::size_type colon = str.find(delimiter, pos); + if (colon == ::std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, colon - pos)); + pos = colon + 1; + } + } + dest->swap(parsed); +} + +# if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort("Unable to open parent process " + + StreamableToString(parent_process_id)); + } + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the pipe handle " + + StreamableToString(write_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the event handle " + + StreamableToString(event_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort("Unable to convert pipe handle " + + StreamableToString(write_handle_as_size_t) + + " to a file descriptor"); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; +} +# endif // GTEST_OS_WINDOWS + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { + if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + + // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we + // can use it here. + int line = -1; + int index = -1; + ::std::vector< ::std::string> fields; + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +# if GTEST_OS_WINDOWS + + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +# else + + if (fields.size() != 4 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + +# endif // GTEST_OS_WINDOWS + + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); +} + +} // namespace internal + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace testing +// 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. +// +// Authors: keith.ray@gmail.com (Keith Ray) + + +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include +#elif GTEST_OS_WINDOWS +# include +# include +#elif GTEST_OS_SYMBIAN +// Symbian OpenC has PATH_MAX in sys/syslimits.h +# include +#else +# include +# include // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_MAX_ _MAX_PATH +#elif defined(PATH_MAX) +# define GTEST_PATH_MAX_ PATH_MAX +#elif defined(_XOPEN_PATH_MAX) +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX +#else +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX +#endif // GTEST_OS_WINDOWS + + +namespace testing { +namespace internal { + +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. +const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; +const char kPathSeparatorString[] = "\\"; +const char kAlternatePathSeparatorString[] = "/"; +# if GTEST_OS_WINDOWS_MOBILE +// Windows CE doesn't have a current directory. You should not use +// the current directory in tests on Windows CE, but this at least +// provides a reasonable fallback. +const char kCurrentDirectoryString[] = "\\"; +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES +const DWORD kInvalidFileAttributes = 0xffffffff; +# else +const char kCurrentDirectoryString[] = ".\\"; +# endif // GTEST_OS_WINDOWS_MOBILE +#else +const char kPathSeparator = '/'; +const char kPathSeparatorString[] = "/"; +const char kCurrentDirectoryString[] = "./"; +#endif // GTEST_OS_WINDOWS + +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + +// Returns the current working directory, or "" if unsuccessful. +FilePath FilePath::GetCurrentDir() { +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. + return FilePath(kCurrentDirectoryString); +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#else + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns a copy of the FilePath with the case-insensitive extension removed. +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns +// FilePath("dir/file"). If a case-insensitive extension is not +// found, returns a copy of the original FilePath. +FilePath FilePath::RemoveExtension(const char* extension) const { + const std::string dot_extension = std::string(".") + extension; + if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { + return FilePath(pathname_.substr( + 0, pathname_.length() - dot_extension.length())); + } + return *this; +} + +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + +// Returns a copy of the FilePath with the directory part removed. +// Example: FilePath("path/to/file").RemoveDirectoryName() returns +// FilePath("file"). If there is no directory part ("just_a_file"), it returns +// the FilePath unmodified. If there is no file part ("just_a_dir/") it +// returns an empty FilePath (""). +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveDirectoryName() const { + const char* const last_sep = FindLastPathSeparator(); + return last_sep ? FilePath(last_sep + 1) : *this; +} + +// RemoveFileName returns the directory path with the filename removed. +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does +// not have a file, like "just/a/dir/", it returns the FilePath unmodified. +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveFileName() const { + const char* const last_sep = FindLastPathSeparator(); + std::string dir; + if (last_sep) { + dir = std::string(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); +} + +// Helper functions for naming files in a directory for xml output. + +// Given directory = "dir", base_name = "test", number = 0, +// extension = "xml", returns "dir/test.xml". If number is greater +// than zero (e.g., 12), returns "dir/test_12.xml". +// On Windows platform, uses \ as the separator rather than /. +FilePath FilePath::MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension) { + std::string file; + if (number == 0) { + file = base_name.string() + "." + extension; + } else { + file = base_name.string() + "_" + StreamableToString(number) + + "." + extension; + } + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(dir.string() + kPathSeparator + relative_path.string()); +} + +// Returns true if pathname describes something findable in the file-system, +// either a file, directory, or whatever. +bool FilePath::FileOrDirectoryExists() const { +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + return attributes != kInvalidFileAttributes; +#else + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns true if pathname describes a directory in the file-system +// that exists. +bool FilePath::DirectoryExists() const { + bool result = false; +#if GTEST_OS_WINDOWS + // Don't strip off trailing separator if path is a root directory on + // Windows (like "C:\\"). + const FilePath& path(IsRootDirectory() ? *this : + RemoveTrailingPathSeparator()); +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + if ((attributes != kInvalidFileAttributes) && + (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = true; + } +#else + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + + return result; +} + +// Returns true if pathname describes a root directory. (Windows has one +// root directory per disk drive.) +bool FilePath::IsRootDirectory() const { +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { + const char* const name = pathname_.c_str(); +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && + ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && + name[1] == ':' && + IsPathSeparator(name[2]); +#else + return IsPathSeparator(name[0]); +#endif +} + +// Returns a pathname for a file that does not currently exist. The pathname +// will be directory/base_name.extension or +// directory/base_name_.extension if directory/base_name.extension +// already exists. The number will be incremented until a pathname is found +// that does not already exist. +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. +// There could be a race condition if two or more processes are calling this +// function at the same time -- they could both pick the same filename. +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension) { + FilePath full_pathname; + int number = 0; + do { + full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); + } while (full_pathname.FileOrDirectoryExists()); + return full_pathname; +} + +// Returns true if FilePath ends with a path separator, which indicates that +// it is intended to represent a directory. Returns false otherwise. +// This does NOT check that a directory (or file) actually exists. +bool FilePath::IsDirectory() const { + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); +} + +// Create directories so that path exists. Returns true if successful or if +// the directories already exist; returns false if unable to create directories +// for any reason. +bool FilePath::CreateDirectoriesRecursively() const { + if (!this->IsDirectory()) { + return false; + } + + if (pathname_.length() == 0 || this->DirectoryExists()) { + return true; + } + + const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); + return parent.CreateDirectoriesRecursively() && this->CreateFolder(); +} + +// Create the directory so that path exists. Returns true if successful or +// if the directory already exists; returns false if unable to create the +// directory for any reason, including if the parent directory does not +// exist. Not named "CreateDirectory" because that's a macro on Windows. +bool FilePath::CreateFolder() const { +#if GTEST_OS_WINDOWS_MOBILE + FilePath removed_sep(this->RemoveTrailingPathSeparator()); + LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); + int result = CreateDirectory(unicode, NULL) ? 0 : -1; + delete [] unicode; +#elif GTEST_OS_WINDOWS + int result = _mkdir(pathname_.c_str()); +#else + int result = mkdir(pathname_.c_str(), 0777); +#endif // GTEST_OS_WINDOWS_MOBILE + + if (result == -1) { + return this->DirectoryExists(); // An error is OK if the directory exists. + } + return true; // No error. +} + +// If input name has a trailing separator character, remove it and return the +// name, otherwise return the name string unmodified. +// On Windows platform, uses \ as the separator, other platforms use /. +FilePath FilePath::RemoveTrailingPathSeparator() const { + return IsDirectory() + ? FilePath(pathname_.substr(0, pathname_.length() - 1)) + : *this; +} + +// Removes any redundant separators that might be in the pathname. +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other +// redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). +void FilePath::Normalize() { + if (pathname_.c_str() == NULL) { + pathname_ = ""; + return; + } + const char* src = pathname_.c_str(); + char* const dest = new char[pathname_.length() + 1]; + char* dest_ptr = dest; + memset(dest_ptr, 0, pathname_.length() + 1); + + while (*src != '\0') { + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { + src++; + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) + src++; + } + dest_ptr++; + } + *dest_ptr = '\0'; + pathname_ = dest; + delete[] dest; +} + +} // namespace internal +} // namespace testing +// 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 +#include +#include +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include // For TerminateProcess() +#elif GTEST_OS_WINDOWS +# include +# include +#else +# include +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +# include +# include +# include +#endif // GTEST_OS_MAC + +#if GTEST_OS_QNX +# include +# include +#endif // GTEST_OS_QNX + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { +namespace internal { + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast(thread_list), + sizeof(thread_t) * thread_count); + return static_cast(thread_count); + } else { + return 0; + } +} + +#elif GTEST_OS_QNX + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const int fd = open("/proc/self/as", O_RDONLY); + if (fd < 0) { + return 0; + } + procfs_info process_info; + const int status = + devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); + close(fd); + if (status == EOK) { + return static_cast(process_info.num_threads); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE + +// Implements RE. Currently only needed for death tests. + +RE::~RE() { + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } + free(const_cast(pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.full_regex_, str, 1, &match, 0) == 0; +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = posix::StrDup(regex); + + // Reserves enough bytes to hold the regular expression used for a + // full match. + const size_t full_regex_len = strlen(regex) + 10; + char* const full_pattern = new char[full_regex_len]; + + snprintf(full_pattern, full_regex_len, "^(%s)$", regex); + is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; + // We want to call regcomp(&partial_regex_, ...) even if the + // previous expression returns false. Otherwise partial_regex_ may + // not be properly initialized can may cause trouble when it's + // freed. + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } + EXPECT_TRUE(is_valid_) + << "Regular expression \"" << regex + << "\" is not a valid POSIX Extended regular expression."; + + delete[] full_pattern; +} + +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in , these aren't affected by the +// current locale. +bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsAsciiPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsAsciiWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsAsciiDigit(ch); + case 'D': return !IsAsciiDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsAsciiWhiteSpace(ch); + case 'S': return !IsAsciiWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsAsciiWordChar(ch); + case 'W': return !IsAsciiWordChar(ch); + } + return IsAsciiPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +std::string FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast(pattern_)); + free(const_cast(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. + + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + +const char kUnknownFile[] = "unknown file"; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) { + return file_name + ":"; + } +#ifdef _MSC_VER + return file_name + "(" + StreamableToString(line) + "):"; +#else + return file_name + ":" + StreamableToString(line) + ":"; +#endif // _MSC_VER +} + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +// Note that FormatCompilerIndependentFileLocation() does NOT append colon +// to the file location it produces, unlike FormatFileLocation(). +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( + const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) + return file_name; + else + return file_name + ":" + StreamableToString(line); +} + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { + const char* const marker = + severity == GTEST_INFO ? "[ INFO ]" : + severity == GTEST_WARNING ? "[WARNING]" : + severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; +} + +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4996) +#endif // _MSC_VER + +#if GTEST_HAS_STREAM_REDIRECTION + +// Object that captures an output stream (stdout/stderr). +class CapturedStream { + public: + // The ctor redirects the stream to a temporary file. + explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { +# if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +# else + // There's no guarantee that a test has write access to the current + // directory, so we create the temporary file in the /tmp directory + // instead. We use /tmp on most systems, and /sdcard on Android. + // That's because Android doesn't have /tmp. +# if GTEST_OS_LINUX_ANDROID + // Note: Android applications are expected to call the framework's + // Context.getExternalStorageDirectory() method through JNI to get + // the location of the world-writable SD Card directory. However, + // this requires a Context handle, which cannot be retrieved + // globally from native code. Doing so also precludes running the + // code as part of a regular standalone executable, which doesn't + // run in a Dalvik process (e.g. when running it through 'adb shell'). + // + // The location /sdcard is directly accessible from native code + // and is the only location (unofficially) supported by the Android + // team. It's generally a symlink to the real SD Card mount point + // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or + // other OEM-customized locations. Never rely on these, and always + // use /sdcard. + char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX"; +# else + char name_template[] = "/tmp/captured_stream.XXXXXX"; +# endif // GTEST_OS_LINUX_ANDROID + const int captured_fd = mkstemp(name_template); + filename_ = name_template; +# endif // GTEST_OS_WINDOWS + fflush(NULL); + dup2(captured_fd, fd_); + close(captured_fd); + } + + ~CapturedStream() { + remove(filename_.c_str()); + } + + std::string GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const std::string content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + // Reads the entire content of a file as an std::string. + static std::string ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; + +// Returns the size (in bytes) of a file. +size_t CapturedStream::GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + return static_cast(ftell(file)); +} + +// Reads the entire content of a file as a string. +std::string CapturedStream::ReadEntireFile(FILE* file) { + const size_t file_size = GetFileSize(file); + char* const buffer = new char[file_size]; + + size_t bytes_last_read = 0; // # of bytes read in the last fread() + size_t bytes_read = 0; // # of bytes read so far + + fseek(file, 0, SEEK_SET); + + // Keeps reading the file until we cannot read further or the + // pre-determined file size is reached. + do { + bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); + bytes_read += bytes_last_read; + } while (bytes_last_read > 0 && bytes_read < file_size); + + const std::string content(buffer, bytes_read); + delete[] buffer; + + return content; +} + +# ifdef _MSC_VER +# pragma warning(pop) +# endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +std::string GetCapturedStream(CapturedStream** captured_stream) { + const std::string content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = NULL; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +std::string GetCapturedStdout() { + return GetCapturedStream(&g_captured_stdout); +} + +// Stops capturing stderr and returns the captured string. +std::string GetCapturedStderr() { + return GetCapturedStream(&g_captured_stderr); +} + +#endif // GTEST_HAS_STREAM_REDIRECTION + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +::std::vector g_argvs; + +static const ::std::vector* g_injected_test_argvs = + NULL; // Owned. + +void SetInjectableArgvs(const ::std::vector* argvs) { + if (g_injected_test_argvs != argvs) + delete g_injected_test_argvs; + g_injected_test_argvs = argvs; +} + +const ::std::vector& GetInjectableArgvs() { + if (g_injected_test_argvs != NULL) { + return *g_injected_test_argvs; + } + return g_argvs; +} +#endif // GTEST_HAS_DEATH_TEST + +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { + DebugBreak(); + TerminateProcess(GetCurrentProcess(), 1); +} +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "GTEST_FOO" in the open-source version. +static std::string FlagToEnvVar(const char* flag) { + const std::string full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); + + Message env_var; + for (size_t i = 0; i != full_flag.length(); i++) { + env_var << ToUpper(full_flag.c_str()[i]); + } + + return env_var.GetString(); +} + +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const Message& src_text, const char* str, Int32* value) { + // Parses the environment variable as a decimal integer. + char* end = NULL; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value \"" << str << "\".\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + // Is the parsed value in the range of an Int32? + const Int32 result = static_cast(long_value); + if (long_value == LONG_MAX || long_value == LONG_MIN || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value " << str << ", which overflows.\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + *value = result; + return true; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + if (string_value == NULL) { + // The environment variable is not set. + return default_value; + } + + Int32 result = default_value; + if (!ParseInt32(Message() << "Environment variable " << env_var, + string_value, &result)) { + printf("The default value %s is used.\n", + (Message() << default_value).GetString().c_str()); + fflush(stdout); + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromGTestEnv(const char* flag, const char* default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value = posix::GetEnv(env_var.c_str()); + return value == NULL ? default_value : value; +} + +} // namespace internal +} // namespace testing +// 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 Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include // NOLINT +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) + *os << ' '; + else + *os << '-'; + } + GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Depending on the value of a char (or wchar_t), we print it in one +// of three formats: +// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), +// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a special escape sequence (e.g. '\r', '\n'). +enum CharFormat { + kAsIs, + kHexEscape, + kSpecialEscape +}; + +// Returns true if c is a printable ASCII character. We test the +// value of c directly instead of calling isprint(), which is buggy on +// Windows Mobile. +inline bool IsPrintableAscii(wchar_t c) { + return 0x20 <= c && c <= 0x7E; +} + +// Prints a wide or narrow char c as a character literal without the +// quotes, escaping it when necessary; returns how c was formatted. +// The template argument UnsignedChar is the unsigned version of Char, +// which is the type of c. +template +static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { + switch (static_cast(c)) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + if (IsPrintableAscii(c)) { + *os << static_cast(c); + return kAsIs; + } else { + *os << "\\x" + String::FormatHexInt(static_cast(c)); + return kHexEscape; + } + } + return kSpecialEscape; +} + +// Prints a wchar_t c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + return kAsIs; + case L'"': + *os << "\\\""; + return kSpecialEscape; + default: + return PrintAsCharLiteralTo(c, os); + } +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { + return PrintAsStringLiteralTo( + static_cast(static_cast(c)), os); +} + +// Prints a wide or narrow character c and its code. '\0' is printed +// as "'\\0'", other unprintable characters are also properly escaped +// using the standard C++ escape sequence. The template argument +// UnsignedChar is the unsigned version of Char, which is the type of c. +template +void PrintCharAndCodeTo(Char c, ostream* os) { + // First, print c as a literal in the most readable form we can find. + *os << ((sizeof(c) > 1) ? "L'" : "'"); + const CharFormat format = PrintAsCharLiteralTo(c, os); + *os << "'"; + + // To aid user debugging, we also print c's code in decimal, unless + // it's 0 (in which case c was printed as '\\0', making the code + // obvious). + if (c == 0) + return; + *os << " (" << static_cast(c); + + // For more convenience, we print c's code again in hexidecimal, + // unless c was already printed in the form '\x##' or the code is in + // [1, 9]. + if (format == kHexEscape || (1 <= c && c <= 9)) { + // Do nothing. + } else { + *os << ", 0x" << String::FormatHexInt(static_cast(c)); + } + *os << ")"; +} + +void PrintTo(unsigned char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} +void PrintTo(signed char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its code. L'\0' is printed as "L'\\0'". +void PrintTo(wchar_t wc, ostream* os) { + PrintCharAndCodeTo(wc, os); +} + +// Prints the given array of characters to the ostream. CharType must be either +// char or wchar_t. +// The array starts at begin, the length is len, it may include '\0' characters +// and may not be NUL-terminated. +template +static void PrintCharsAsStringTo( + const CharType* begin, size_t len, ostream* os) { + const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; + *os << kQuoteBegin; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const CharType cur = begin[index]; + if (is_previous_hex && IsXDigit(cur)) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" " << kQuoteBegin; + } + is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints a (const) char/wchar_t array of 'len' elements, starting at address +// 'begin'. CharType must be either char or wchar_t. +template +static void UniversalPrintCharArray( + const CharType* begin, size_t len, ostream* os) { + // The code + // const char kFoo[] = "foo"; + // generates an array of 4, not 3, elements, with the last one being '\0'. + // + // Therefore when printing a char array, we don't print the last element if + // it's '\0', such that the output matches the string literal as it's + // written in the source code. + if (len > 0 && begin[len - 1] == '\0') { + PrintCharsAsStringTo(begin, len - 1, os); + return; + } + + // If, however, the last element in the array is not '\0', e.g. + // const char kFoo[] = { 'f', 'o', 'o' }; + // we must print the entire array. We also print a message to indicate + // that the array is not NUL-terminated. + PrintCharsAsStringTo(begin, len, os); + *os << " (no terminating NUL)"; +} + +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints a (const) wchar_t array of 'len' elements, starting at address +// 'begin'. +void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing +// 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: mheule@google.com (Markus Heule) +// +// The Google C++ Testing Framework (Google Test) + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +using internal::GetUnitTestImpl; + +// Gets the summary of the failure message by omitting the stack trace +// in it. +std::string TestPartResult::ExtractSummary(const char* message) { + const char* const stack_trace = strstr(message, internal::kStackTraceMarker); + return stack_trace == NULL ? message : + std::string(message, stack_trace); +} + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; +} + +// Appends a TestPartResult to the array. +void TestPartResultArray::Append(const TestPartResult& result) { + array_.push_back(result); +} + +// Returns the TestPartResult at the given index (0-based). +const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { + if (index < 0 || index >= size()) { + printf("\nInvalid index (%d) into TestPartResultArray.\n", index); + internal::posix::Abort(); + } + + return array_[index]; +} + +// Returns the number of TestPartResult objects in the array. +int TestPartResultArray::size() const { + return static_cast(array_.size()); +} + +namespace internal { + +HasNewFatalFailureHelper::HasNewFatalFailureHelper() + : has_new_fatal_failure_(false), + original_reporter_(GetUnitTestImpl()-> + GetTestPartResultReporterForCurrentThread()) { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); +} + +HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( + original_reporter_); +} + +void HasNewFatalFailureHelper::ReportTestPartResult( + const TestPartResult& result) { + if (result.fatally_failed()) + has_new_fatal_failure_ = true; + original_reporter_->ReportTestPartResult(result); +} + +} // namespace internal + +} // namespace testing +// 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) + + +namespace testing { +namespace internal { + +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (IsSpace(*str)) + str++; + return str; +} + +// Verifies that registered_tests match the test names in +// defined_test_names_; returns registered_tests if successful, or +// aborts the program otherwise. +const char* TypedTestCasePState::VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests) { + typedef ::std::set::const_iterator DefinedTestIter; + registered_ = true; + + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + + Message errors; + ::std::set tests; + for (const char* names = registered_tests; names != NULL; + names = SkipComma(names)) { + const std::string name = GetPrefixUntilComma(names); + if (tests.count(name) != 0) { + errors << "Test " << name << " is listed more than once.\n"; + continue; + } + + bool found = false; + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (name == *it) { + found = true; + break; + } + } + + if (found) { + tests.insert(name); + } else { + errors << "No test named " << name + << " can be found in this test case.\n"; + } + } + + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (tests.count(*it) == 0) { + errors << "You forgot to list test " << *it << ".\n"; + } + } + + const std::string& errors_str = errors.GetString(); + if (errors_str != "") { + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors_str.c_str()); + fflush(stderr); + posix::Abort(); + } + + return registered_tests; +} + +#endif // GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing diff --git a/VihrevIB/lab1/gtest/gtest.h b/VihrevIB/lab1/gtest/gtest.h new file mode 100644 index 000000000..6e7cfc2be --- /dev/null +++ b/VihrevIB/lab1/gtest/gtest.h @@ -0,0 +1,20063 @@ +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for Google Test. It should be +// included by any test program that uses Google Test. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! +// +// Acknowledgment: Google Test borrowed the idea of automatic test +// registration from Barthelemy Dagenais' (barthelemy@prologique.com) +// easyUnit framework. + +#define _VARIADIC_MAX 10 + +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_H_ + +#include +#include +#include + +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares functions and macros used internally by +// Google Test. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ + +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan) +// +// Low-level types and utilities for porting Google Test to various +// platforms. They are subject to change without notice. DO NOT USE +// THEM IN USER CODE. +// +// This file is fundamental to Google Test. All other Google Test source +// files are expected to #include this. Therefore, it cannot #include +// any other Google Test header. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +// 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. +// +// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) +// is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. +// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::string, which is different to std::string). +// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::wstring, which is different to std::wstring). +// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular +// expressions are/aren't available. +// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that +// is/isn't available. +// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't +// enabled. +// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that +// std::wstring does/doesn't work (Google Test can +// be used where std::wstring is unavailable). +// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple +// is/isn't available. +// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the +// compiler supports Microsoft's "Structured +// Exception Handling". +// GTEST_HAS_STREAM_REDIRECTION +// - Define it to 1/0 to indicate whether the +// platform supports I/O stream redirection using +// dup() and dup2(). +// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google +// Test's own tr1 tuple implementation should be +// used. Unused when the user sets +// GTEST_HAS_TR1_TUPLE to 0. +// GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test +// is building in C++11/C++98 mode. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. + +// This header defines the following utilities: +// +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HPUX - HP-UX +// GTEST_OS_LINUX - Linux +// GTEST_OS_LINUX_ANDROID - Google Android +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_IOS - iOS +// GTEST_OS_IOS_SIMULATOR - iOS simulator +// GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_OPENBSD - OpenBSD +// GTEST_OS_QNX - QNX +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS +// +// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// most stable support. Since core members of the Google Test project +// don't have access to other platforms, support for them may be less +// stable. If you notice any problems on your platform, please notify +// googletestframework@googlegroups.com (patches for fixing them are +// even more welcome!). +// +// Note that it is possible that none of the GTEST_OS_* macros are defined. +// +// 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 +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with +// GTEST_HAS_POSIX_RE (see above) which users can +// define themselves. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// +// Macros for basic C++ coding: +// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. +// +// Synchronization: +// Mutex, MutexLock, ThreadLocal, GetThreadCount() +// - 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: +// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. +// IteratorTraits - partial implementation of std::iterator_traits, which +// is not available in libCstd when compiled with Sun C++. +// +// Smart pointers: +// scoped_ptr - as in TR2. +// +// Regular expressions: +// RE - a simple regular expression class using the POSIX +// Extended Regular Expression syntax on UNIX-like +// platforms, or a reduced regular exception syntax on +// other platforms, including Windows. +// +// Logging: +// GTEST_LOG_() - logs messages at the specified severity level. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. +// +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. +// CaptureStderr() - starts capturing stderr. +// GetCapturedStderr() - stops capturing stderr and returns the captured +// string. +// +// Integer types: +// TypeWithSize - maps an integer to a int type. +// Int32, UInt32, Int64, UInt64, TimeInMillis +// - integers of known sizes. +// BiggestInt - the biggest signed integer type. +// +// Command-line utilities: +// GTEST_FLAG() - references a flag. +// GTEST_DECLARE_*() - declares a flag. +// GTEST_DEFINE_*() - defines a flag. +// GetInjectableArgvs() - returns the command line as a vector of strings. +// +// Environment variable utilities: +// GetEnv() - gets the value of an environment variable. +// BoolFromGTestEnv() - parses a bool environment variable. +// Int32FromGTestEnv() - parses an Int32 environment variable. +// StringFromGTestEnv() - parses a string environment variable. + +#include // for isspace, etc +#include // for ptrdiff_t +#include +#include +#include +#ifndef _WIN32_WCE +# include +# include +#endif // !_WIN32_WCE + +#if defined __APPLE__ +# include +# include +#endif + +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" + +// Determines the version of gcc that is used to compile this. +#ifdef __GNUC__ +// 40302 means version 4.3.2. +# define GTEST_GCC_VER_ \ + (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + +// Determines the platform on which Google Test is compiled. +#ifdef __CYGWIN__ +# define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +# define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +# define GTEST_OS_WINDOWS 1 +# ifdef _WIN32_WCE +# define GTEST_OS_WINDOWS_MOBILE 1 +# elif defined(__MINGW__) || defined(__MINGW32__) +# define GTEST_OS_WINDOWS_MINGW 1 +# else +# define GTEST_OS_WINDOWS_DESKTOP 1 +# endif // _WIN32_WCE +#elif defined __APPLE__ +# define GTEST_OS_MAC 1 +# if TARGET_OS_IPHONE +# define GTEST_OS_IOS 1 +# if TARGET_IPHONE_SIMULATOR +# define GTEST_OS_IOS_SIMULATOR 1 +# endif +# endif +#elif defined __linux__ +# define GTEST_OS_LINUX 1 +# if defined __ANDROID__ +# define GTEST_OS_LINUX_ANDROID 1 +# endif +#elif defined __MVS__ +# define GTEST_OS_ZOS 1 +#elif defined(__sun) && defined(__SVR4) +# define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +# define GTEST_OS_AIX 1 +#elif defined(__hpux) +# define GTEST_OS_HPUX 1 +#elif defined __native_client__ +# define GTEST_OS_NACL 1 +#elif defined __OpenBSD__ +# define GTEST_OS_OPENBSD 1 +#elif defined __QNX__ +# define GTEST_OS_QNX 1 +#endif // __CYGWIN__ + +#ifndef GTEST_LANG_CXX11 +// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when +// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a +// value for __cplusplus, and recent versions of clang, gcc, and +// probably other compilers set that too in C++11 mode. +# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L +// Compiling in at least C++11 mode. +# define GTEST_LANG_CXX11 1 +# else +# define GTEST_LANG_CXX11 0 +# endif +#endif + +// Brings in definitions for functions used in the testing::internal::posix +// namespace (read, write, close, chdir, isatty, stat). We do not currently +// use them on Windows Mobile. +#if !GTEST_OS_WINDOWS +// 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 +// mentioned above. +# include +# include +#elif !GTEST_OS_WINDOWS_MOBILE +# include +# include +#endif + +#if GTEST_OS_LINUX_ANDROID +// Used to define __ANDROID_API__ matching the target NDK API level. +# include // NOLINT +#endif + +// Defines this to true iff Google Test can use POSIX regular expressions. +#ifndef GTEST_HAS_POSIX_RE +# if GTEST_OS_LINUX_ANDROID +// On Android, is only available starting with Gingerbread. +# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) +# else +# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +# endif +#endif + +#if GTEST_HAS_POSIX_RE + +// On some platforms, needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included , which is guaranteed to define size_t through +// . +# include // NOLINT + +# define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +// is not available on Windows. Use our own simple regex +// implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#else + +// may not be available on this platform. Use our own +// simple regex implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_HAS_POSIX_RE + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +# if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. +// Assumes that exceptions are enabled by default. +# ifndef _HAS_EXCEPTIONS +# define _HAS_EXCEPTIONS 1 +# endif // _HAS_EXCEPTIONS +# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS +# elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__HP_aCC) +// Exception handling is in effect by default in HP aCC compiler. It has to +// be turned of by +noeh compiler option if desired. +# define GTEST_HAS_EXCEPTIONS 1 +# else +// For other compilers, we assume exceptions are disabled to be +// conservative. +# define GTEST_HAS_EXCEPTIONS 0 +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS + +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +# define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +# error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) + +#ifndef GTEST_HAS_GLOBAL_STRING +// The user didn't tell us whether ::string is available, so we need +// to figure it out. + +# define GTEST_HAS_GLOBAL_STRING 0 + +#endif // GTEST_HAS_GLOBAL_STRING + +#ifndef GTEST_HAS_STD_WSTRING +// The user didn't tell us whether ::std::wstring is available, so we need +// to figure it out. +// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring +// is available. + +// Cygwin 1.7 and below doesn't support ::std::wstring. +// Solaris' libc++ doesn't support it either. Android has +// no support for it at least as recent as Froyo (2.2). +# define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) + +#endif // GTEST_HAS_STD_WSTRING + +#ifndef GTEST_HAS_GLOBAL_WSTRING +// The user didn't tell us whether ::wstring is available, so we need +// to figure it out. +# define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Determines whether RTTI is available. +#ifndef GTEST_HAS_RTTI +// The user didn't tell us whether RTTI is enabled, so we need to +// figure it out. + +# ifdef _MSC_VER + +# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + +# ifdef __GXX_RTTI +// When building against STLport with the Android NDK and with +// -frtti -fno-exceptions, the build fails at link time with undefined +// references to __cxa_bad_typeid. Note sure if STL or toolchain bug, +// so disable RTTI when detected. +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \ + !defined(__EXCEPTIONS) +# define GTEST_HAS_RTTI 0 +# else +# define GTEST_HAS_RTTI 1 +# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS +# else +# define GTEST_HAS_RTTI 0 +# endif // __GXX_RTTI + +// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends +// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the +// first version with C++ support. +# elif defined(__clang__) + +# define GTEST_HAS_RTTI __has_feature(cxx_rtti) + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +# ifdef __RTTI_ALL__ +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +# else + +// For all other compilers, we assume RTTI is enabled. +# define GTEST_HAS_RTTI 1 + +# endif // _MSC_VER + +#endif // GTEST_HAS_RTTI + +// It's this header's responsibility to #include when RTTI +// is enabled. +#if GTEST_HAS_RTTI +# include +#endif + +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \ + || GTEST_OS_QNX) +#endif // GTEST_HAS_PTHREAD + +#if GTEST_HAS_PTHREAD +// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is +// true. +# include // NOLINT + +// For timespec and nanosleep, used below. +# include // NOLINT +#endif + +// Determines whether Google Test can use tr1/tuple. You can define +// this macro to 0 to prevent Google Test from using tuple (any +// feature depending on tuple with be disabled in this mode). +#ifndef GTEST_HAS_TR1_TUPLE +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) +// STLport, provided with the Android NDK, has neither or . +# define GTEST_HAS_TR1_TUPLE 0 +# else +// The user didn't tell us not to do it, so we assume it's OK. +# define GTEST_HAS_TR1_TUPLE 1 +# endif +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether Google Test's own tr1 tuple implementation +// should be used. +#ifndef GTEST_USE_OWN_TR1_TUPLE +// The user didn't tell us, so we need to figure it out. + +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, libstdc++ 4.0.0+ and +// MSVC 2010 are the only mainstream standard libraries that come +// with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler +// pretends to be GCC by defining __GNUC__ and friends, but cannot +// compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1 +// tuple in a 323 MB Feature Pack download, which we cannot assume the +// user has. QNX's QCC compiler is a modified GCC but it doesn't +// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, +// and it can be used with some compilers that define __GNUC__. +# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ + && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600 +# define GTEST_ENV_HAS_TR1_TUPLE_ 1 +# endif + +// C++11 specifies that provides std::tuple. 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_ENV_HAS_STD_TUPLE_ 1 +# endif + +# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_ +# define GTEST_USE_OWN_TR1_TUPLE 0 +# else +# define GTEST_USE_OWN_TR1_TUPLE 1 +# endif + +#endif // GTEST_USE_OWN_TR1_TUPLE + +// To avoid conditional compilation everywhere, we make it +// gtest-port.h's responsibility to #include the header implementing +// tr1/tuple. +#if GTEST_HAS_TR1_TUPLE + +# if GTEST_USE_OWN_TR1_TUPLE +// This file was GENERATED by command: +// pump.py gtest-tuple.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2009 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 a subset of TR1 tuple needed by Google Test and Google Mock. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple +#define GTEST_2_TUPLE_(T) tuple +#define GTEST_3_TUPLE_(T) tuple +#define GTEST_4_TUPLE_(T) tuple +#define GTEST_5_TUPLE_(T) tuple +#define GTEST_6_TUPLE_(T) tuple +#define GTEST_7_TUPLE_(T) tuple +#define GTEST_8_TUPLE_(T) tuple +#define GTEST_9_TUPLE_(T) tuple +#define GTEST_10_TUPLE_(T) tuple + +// GTEST_n_TYPENAMES_(T) declares a list of n typenames. +#define GTEST_0_TYPENAMES_(T) +#define GTEST_1_TYPENAMES_(T) typename T##0 +#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 +#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 +#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3 +#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4 +#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5 +#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6 +#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 +#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8 +#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8, typename T##9 + +// In theory, defining stuff in the ::std namespace is undefined +// behavior. We can do this as we are playing the role of a standard +// library vendor. +namespace std { +namespace tr1 { + +template +class tuple; + +// Anything in namespace gtest_internal is Google Test's INTERNAL +// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. +namespace gtest_internal { + +// ByRef::type is T if T is a reference; otherwise it's const T&. +template +struct ByRef { typedef const T& type; }; // NOLINT +template +struct ByRef { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type + +// AddRef::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference::type. +template +struct AddRef { typedef T& type; }; // NOLINT +template +struct AddRef { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type + +// A helper for implementing get(). +template class Get; + +// A helper for implementing tuple_element. kIndexValid is true +// iff k < the number of fields in tuple type T. +template +struct TupleElement; + +template +struct TupleElement { + typedef T0 type; +}; + +template +struct TupleElement { + typedef T1 type; +}; + +template +struct TupleElement { + typedef T2 type; +}; + +template +struct TupleElement { + typedef T3 type; +}; + +template +struct TupleElement { + typedef T4 type; +}; + +template +struct TupleElement { + typedef T5 type; +}; + +template +struct TupleElement { + typedef T6 type; +}; + +template +struct TupleElement { + typedef T7 type; +}; + +template +struct TupleElement { + typedef T8 type; +}; + +template +struct TupleElement { + typedef T9 type; +}; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template +class GTEST_1_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template +class GTEST_2_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), + f1_(f1) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} + + template + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template + tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template + tuple& operator=(const ::std::pair& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template +class GTEST_3_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + template + tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; +}; + +template +class GTEST_4_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} + + template + tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; +}; + +template +class GTEST_5_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, + GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_) {} + + template + tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; +}; + +template +class GTEST_6_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_) {} + + template + tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; +}; + +template +class GTEST_7_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + template + tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; +}; + +template +class GTEST_8_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, + GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + template + tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; +}; + +template +class GTEST_9_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + template + tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; +}; + +template +class tuple { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} + + template + tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), + f9_(t.f9_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + f9_ = t.f9_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; + T9 f9_; +}; + +// 6.1.3.2 Tuple creation functions. + +// Known limitations: we don't support passing an +// std::tr1::reference_wrapper to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template +inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { + return GTEST_3_TUPLE_(T)(f0, f1, f2); +} + +template +inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3) { + return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); +} + +template +inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4) { + return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); +} + +template +inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5) { + return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); +} + +template +inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6) { + return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); +} + +template +inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { + return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); +} + +template +inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8) { + return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); +} + +template +inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8, const T9& f9) { + return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); +} + +// 6.1.3.3 Tuple helper classes. + +template struct tuple_size; + +template +struct tuple_size { + static const int value = 0; +}; + +template +struct tuple_size { + static const int value = 1; +}; + +template +struct tuple_size { + static const int value = 2; +}; + +template +struct tuple_size { + static const int value = 3; +}; + +template +struct tuple_size { + static const int value = 4; +}; + +template +struct tuple_size { + static const int value = 5; +}; + +template +struct tuple_size { + static const int value = 6; +}; + +template +struct tuple_size { + static const int value = 7; +}; + +template +struct tuple_size { + static const int value = 8; +}; + +template +struct tuple_size { + static const int value = 9; +}; + +template +struct tuple_size { + static const int value = 10; +}; + +template +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::Field(t); +} + +template +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::ConstField(t); +} + +// 6.1.3.5 Relational operators + +// We only implement == and !=, as we don't have a need for the rest yet. + +namespace gtest_internal { + +// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the +// first k fields of t1 equals the first k fields of t2. +// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if +// k1 != k2. +template +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template +struct SameSizeTuplePrefixComparator { + template + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator::Eq(t1, t2) && + ::std::tr1::get(t1) == ::std::tr1::get(t2); + } +}; + +} // namespace gtest_internal + +template +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size::value, + tuple_size::value>::Eq(t, u); +} + +template +inline bool operator!=(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { return !(t == u); } + +// 6.1.4 Pairs. +// Unimplemented. + +} // namespace tr1 +} // namespace std + +#undef GTEST_0_TUPLE_ +#undef GTEST_1_TUPLE_ +#undef GTEST_2_TUPLE_ +#undef GTEST_3_TUPLE_ +#undef GTEST_4_TUPLE_ +#undef GTEST_5_TUPLE_ +#undef GTEST_6_TUPLE_ +#undef GTEST_7_TUPLE_ +#undef GTEST_8_TUPLE_ +#undef GTEST_9_TUPLE_ +#undef GTEST_10_TUPLE_ + +#undef GTEST_0_TYPENAMES_ +#undef GTEST_1_TYPENAMES_ +#undef GTEST_2_TYPENAMES_ +#undef GTEST_3_TYPENAMES_ +#undef GTEST_4_TYPENAMES_ +#undef GTEST_5_TYPENAMES_ +#undef GTEST_6_TYPENAMES_ +#undef GTEST_7_TYPENAMES_ +#undef GTEST_8_TYPENAMES_ +#undef GTEST_9_TYPENAMES_ +#undef GTEST_10_TYPENAMES_ + +#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +# elif GTEST_ENV_HAS_STD_TUPLE_ +# include +// C++11 puts its tuple into the ::std namespace rather than +// ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there. +// This causes undefined behavior, but supported compilers react in +// the way we intend. +namespace std { +namespace tr1 { +using ::std::get; +using ::std::make_tuple; +using ::std::tuple; +using ::std::tuple_element; +using ::std::tuple_size; +} +} + +# elif GTEST_OS_SYMBIAN + +// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to +// use STLport's tuple implementation, which unfortunately doesn't +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +# ifdef BOOST_HAS_TR1_TUPLE +# undef BOOST_HAS_TR1_TUPLE +# endif // BOOST_HAS_TR1_TUPLE + +// This prevents , which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . +# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +# include + +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the header. This does +// not conform to the TR1 spec, which requires the header to be . + +# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes , +// which is #included by , to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// . Hence the following #define is a hack to prevent +// from being included. +# define _TR1_FUNCTIONAL 1 +# include +# undef _TR1_FUNCTIONAL // Allows the user to #include + // if he chooses to. +# else +# include // NOLINT +# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +# else +// If the compiler is not GCC 4.0+, we assume the user is using a +// spec-conforming TR1 implementation. +# include // NOLINT +# endif // GTEST_USE_OWN_TR1_TUPLE + +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether clone(2) is supported. +// Usually it will only be available on Linux, excluding +// Linux on the Itanium architecture. +// Also see http://linux.die.net/man/2/clone. +#ifndef GTEST_HAS_CLONE +// The user didn't tell us, so we need to figure it out. + +# if GTEST_OS_LINUX && !defined(__ia64__) +# if GTEST_OS_LINUX_ANDROID +// On Android, clone() is only available on ARM starting with Gingerbread. +# if defined(__arm__) && __ANDROID_API__ >= 9 +# define GTEST_HAS_CLONE 1 +# else +# define GTEST_HAS_CLONE 0 +# endif +# else +# define GTEST_HAS_CLONE 1 +# endif +# else +# define GTEST_HAS_CLONE 0 +# endif // GTEST_OS_LINUX && !defined(__ia64__) + +#endif // GTEST_HAS_CLONE + +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#ifndef GTEST_HAS_STREAM_REDIRECTION +// By default, we assume that stream redirection is supported on all +// platforms except known mobile ones. +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN +# define GTEST_HAS_STREAM_REDIRECTION 0 +# else +# define GTEST_HAS_STREAM_REDIRECTION 1 +# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ + GTEST_OS_OPENBSD || GTEST_OS_QNX) +# define GTEST_HAS_DEATH_TEST 1 +# include // NOLINT +#endif + +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 + +// Determines whether to support type-driven tests. + +// Typed tests need and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, IBM Visual Age, and HP aCC support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) || defined(__HP_aCC) +# define GTEST_HAS_TYPED_TEST 1 +# define GTEST_HAS_TYPED_TEST_P 1 +#endif + +// Determines whether to support Combine(). This only makes sense when +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +# define GTEST_HAS_COMBINE 1 +#endif + +// Determines whether the system compiler uses UTF-16 for encoding wide strings. +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + +// Determines whether test results can be streamed to a socket. +#if GTEST_OS_LINUX +# define GTEST_CAN_STREAM_RESULTS_ 1 +#endif + +// Defines some utility macros. + +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#ifdef __INTEL_COMPILER +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ +#else +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT +#endif + +// Use this annotation at the end of a struct/class definition to +// prevent the compiler from optimizing away instances that are never +// used. This is useful when all interesting logic happens inside the +// c'tor and / or d'tor. Example: +// +// struct Foo { +// Foo() { ... } +// } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. +#if defined(__GNUC__) && !defined(COMPILER_ICC) +# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) +#else +# define GTEST_ATTRIBUTE_UNUSED_ +#endif + +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; +#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) +#else +# define GTEST_MUST_USE_RESULT_ +#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC + +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +# if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +# define GTEST_HAS_SEH 1 +# else +// Assume no SEH. +# define GTEST_HAS_SEH 0 +# endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +# if GTEST_LINKED_AS_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllimport) +# elif GTEST_CREATE_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllexport) +# endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +# define GTEST_API_ +#endif + +#ifdef __GNUC__ +// Ask the compiler to never inline a given function. +# define GTEST_NO_INLINE_ __attribute__((noinline)) +#else +# define GTEST_NO_INLINE_ +#endif + +// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. +#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) +# define GTEST_HAS_CXXABI_H_ 1 +#else +# define GTEST_HAS_CXXABI_H_ 0 +#endif + +namespace testing { + +class Message; + +namespace internal { + +// A secret type that Google Test users don't know about. It has no +// definition on purpose. Therefore it's impossible to create a +// Secret object, which is what we want. +class Secret; + +// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template +struct CompileAssert { +}; + +#define GTEST_COMPILE_ASSERT_(expr, msg) \ + typedef ::testing::internal::CompileAssert<(static_cast(expr))> \ + msg[static_cast(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_ + +// Implementation details of GTEST_COMPILE_ASSERT_: +// +// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// GTEST_COMPILE_ASSERT_(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. +// +// This template is declared, but intentionally undefined. +template +struct StaticAssertTypeEqHelper; + +template +struct StaticAssertTypeEqHelper {}; + +#if GTEST_HAS_GLOBAL_STRING +typedef ::string string; +#else +typedef ::std::string string; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_GLOBAL_WSTRING +typedef ::wstring wstring; +#elif GTEST_HAS_STD_WSTRING +typedef ::std::wstring wstring; +#endif // GTEST_HAS_GLOBAL_WSTRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); + +// Defines scoped_ptr. + +// This implementation of scoped_ptr is PARTIAL - it only contains +// enough stuff to satisfy Google Test's need. +template +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} + ~scoped_ptr() { reset(); } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + T* get() const { return ptr_; } + + T* release() { + T* const ptr = ptr_; + ptr_ = NULL; + return ptr; + } + + void reset(T* p = NULL) { + if (p != ptr_) { + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. + delete ptr_; + } + ptr_ = p; + } + } + + private: + T* ptr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); +}; + +// Defines RE. + +// A simple C++ wrapper for . It uses the POSIX Extended +// Regular Expression syntax. +class GTEST_API_ RE { + public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + + // Constructs an RE from a string. + RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + + RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT + +#endif // GTEST_HAS_GLOBAL_STRING + + RE(const char* regex) { Init(regex); } // NOLINT + ~RE(); + + // Returns the string representation of the regex. + const char* pattern() const { return pattern_; } + + // FullMatch(str, re) returns true iff regular expression re matches + // the entire str. + // PartialMatch(str, re) returns true iff regular expression re + // matches a substring of str (including str itself). + // + // TODO(wan@google.com): make FullMatch() and PartialMatch() work + // when str contains NUL characters. + static bool FullMatch(const ::std::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::std::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#if GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const ::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#endif // GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const char* str, const RE& re); + static bool PartialMatch(const char* str, const RE& re); + + private: + void Init(const char* regex); + + // We use a const char* instead of an std::string, as Google Test used to be + // used where std::string is not available. TODO(wan@google.com): change to + // std::string. + const char* pattern_; + bool is_valid_; + +#if GTEST_USES_POSIX_RE + + regex_t full_regex_; // For FullMatch(). + regex_t partial_regex_; // For PartialMatch(). + +#else // GTEST_USES_SIMPLE_RE + + const char* full_pattern_; // For FullMatch(); + +#endif + + GTEST_DISALLOW_ASSIGN_(RE); +}; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, + int line); + +// Defines logging utilities: +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. + +enum GTestLogSeverity { + GTEST_INFO, + GTEST_WARNING, + GTEST_ERROR, + GTEST_FATAL +}; + +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); + + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() + +inline void LogToStderr() {} +inline void FlushInfoLog() { fflush(NULL); } + +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Use ImplicitCast_ as a safe version of static_cast for upcasting in +// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a +// const Foo*). When you use ImplicitCast_, the compiler checks that +// the cast is safe. Such explicit ImplicitCast_s are necessary in +// surprisingly many situations where C++ demands an exact type match +// instead of an argument type convertable to a target type. +// +// The syntax for using ImplicitCast_ is the same as for static_cast: +// +// ImplicitCast_(expr) +// +// ImplicitCast_ would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., implicit_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template +inline To ImplicitCast_(To x) { return x; } + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., down_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template // use like this: DownCast_(foo); +inline To DownCast_(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + const To to = NULL; + ::testing::internal::ImplicitCast_(to); + } + +#if GTEST_HAS_RTTI + // RTTI: debug mode only! + GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast(base); // NOLINT +#else + return static_cast(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION + +// Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. +// CaptureStderr - starts capturing stderr. +// GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ std::string GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ std::string GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION + + +#if GTEST_HAS_DEATH_TEST + +const ::std::vector& GetInjectableArgvs(); +void SetInjectableArgvs(const ::std::vector* + new_argvs); + +// A copy of all command line arguments. Set by InitGoogleTest(). +extern ::std::vector g_argvs; + +#endif // GTEST_HAS_DEATH_TEST + +// Defines synchronization primitives. + +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// 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 Notification { + public: + Notification() : notified_(false) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + } + ~Notification() { + pthread_mutex_destroy(&mutex_); + } + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { + pthread_mutex_lock(&mutex_); + notified_ = true; + pthread_mutex_unlock(&mutex_); + } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + for (;;) { + pthread_mutex_lock(&mutex_); + const bool notified = notified_; + pthread_mutex_unlock(&mutex_); + if (notified) + break; + SleepMilliseconds(10); + } + } + + private: + pthread_mutex_t mutex_; + bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // 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: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + has_owner_ = true; + } + + // Releases this mutex. + void Unlock() { + // Since the lock is being released the owner_ field should no longer be + // considered valid. We don't protect writing to has_owner_ here, as it's + // the caller's responsibility to ensure that the current thread holds the + // mutex when this is called. + has_owner_ = false; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self())) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + // has_owner_ indicates whether the owner_ field below contains a valid thread + // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All + // accesses to the owner_ field should be protected by a check of this field. + // An alternative might be to memset() owner_ to all zeros, but there's no + // guarantee that a zero'd pthread_t is necessarily invalid or even different + // from pthread_self(). + bool has_owner_; + pthread_t owner_; // The thread holding the mutex. +}; + +// Forward-declares a static mutex. +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +// The initialization list here does not explicitly initialize each field, +// instead relying on default initialization for the unspecified fields. In +// particular, the owner_ field (a pthread_t) is not explicitly initialized. +// 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. +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + has_owner_ = false; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal 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 +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + 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 type 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); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +# define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + +// A dummy implementation of synchronization primitives (mutex, lock, +// and thread-local variable). Necessary for compiling Google Test where +// mutex is not supported - using Google Test in multiple threads is not +// supported on such platforms. + +class Mutex { + public: + Mutex() {} + void Lock() {} + void Unlock() {} + void AssertHeld() const {} +}; + +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + +class GTestMutexLock { + public: + explicit GTestMutexLock(Mutex*) {} // NOLINT +}; + +typedef GTestMutexLock MutexLock; + +template +class ThreadLocal { + public: + ThreadLocal() : value_() {} + explicit ThreadLocal(const T& value) : value_(value) {} + T* pointer() { return &value_; } + const T* pointer() const { return &value_; } + const T& get() const { return value_; } + void set(const T& value) { value_ = value; } + private: + T value_; +}; + +// 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 +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); + +// Passing non-POD classes through ellipsis (...) crashes the ARM +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +# define GTEST_CAN_COMPARE_NULL 1 +#endif + +// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between +// const T& and const T* in a function template. These compilers +// _can_ decide between class template specializations for T and T*, +// so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +# define GTEST_NEEDS_IS_POINTER_ 1 +#endif + +template +struct bool_constant { + typedef bool_constant type; + static const bool value = bool_value; +}; +template const bool bool_constant::value; + +typedef bool_constant false_type; +typedef bool_constant true_type; + +template +struct is_pointer : public false_type {}; + +template +struct is_pointer : public true_type {}; + +template +struct IteratorTraits { + typedef typename Iterator::value_type value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_SEP_ "\\" +# define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. +typedef __int64 BiggestInt; +#else +# define GTEST_PATH_SEP_ "/" +# define GTEST_HAS_ALT_PATH_SEP_ 0 +typedef long long BiggestInt; // NOLINT +#endif // GTEST_OS_WINDOWS + +// Utilities for char. + +// isspace(int ch) and friends accept an unsigned char or EOF. char +// may be signed, depending on the compiler (or compiler flags). +// Therefore we need to cast a char to unsigned char before calling +// isspace(), etc. + +inline bool IsAlpha(char ch) { + return isalpha(static_cast(ch)) != 0; +} +inline bool IsAlNum(char ch) { + return isalnum(static_cast(ch)) != 0; +} +inline bool IsDigit(char ch) { + return isdigit(static_cast(ch)) != 0; +} +inline bool IsLower(char ch) { + return islower(static_cast(ch)) != 0; +} +inline bool IsSpace(char ch) { + return isspace(static_cast(ch)) != 0; +} +inline bool IsUpper(char ch) { + return isupper(static_cast(ch)) != 0; +} +inline bool IsXDigit(char ch) { + return isxdigit(static_cast(ch)) != 0; +} +inline bool IsXDigit(wchar_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} + +inline char ToLower(char ch) { + return static_cast(tolower(static_cast(ch))); +} +inline char ToUpper(char ch) { + return static_cast(toupper(static_cast(ch))); +} + +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +# ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +# else // !__BORLANDC__ +# if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +# else +inline int IsATTY(int fd) { return _isatty(fd); } +# endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +# endif // __BORLANDC__ + +# if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +# else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +# endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#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) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + +// MSVC "deprecates" snprintf and issues warnings wherever it is used. In +// order to avoid these warnings, we need to use _snprintf or _snprintf_s on +// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate +// function in order to achieve that. We use macro definition here because +// snprintf is a variadic function. +#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE +// MSVC 2005 and above support variadic macros. +# define GTEST_SNPRINTF_(buffer, size, format, ...) \ + _snprintf_s(buffer, size, size, format, __VA_ARGS__) +#elif defined(_MSC_VER) +// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't +// complain about _snprintf. +# define GTEST_SNPRINTF_ _snprintf +#else +# define GTEST_SNPRINTF_ snprintf +#endif + +// The maximum number a BiggestInt can represent. This definition +// works no matter BiggestInt is represented in one's complement or +// two's complement. +// +// We cannot rely on numeric_limits in STL, as __int64 and long long +// are not part of standard C++ and numeric_limits doesn't need to be +// defined for them. +const BiggestInt kMaxBiggestInt = + ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); + +// This template class serves as a compile-time function from size to +// type. It maps a size in bytes to a primitive type with that +// size. e.g. +// +// TypeWithSize<4>::UInt +// +// is typedef-ed to be unsigned int (unsigned integer made up of 4 +// bytes). +// +// Such functionality should belong to STL, but I cannot find it +// there. +// +// Google Test uses this class in the implementation of floating-point +// comparison. +// +// For now it only handles UInt (unsigned int) as that's all Google Test +// needs. Other types can be easily added in the future if need +// arises. +template +class TypeWithSize { + public: + // This prevents the user from using TypeWithSize with incorrect + // values of N. + typedef void UInt; +}; + +// The specialization for size 4. +template <> +class TypeWithSize<4> { + public: + // unsigned int has size 4 in both gcc and MSVC. + // + // As base/basictypes.h doesn't compile on Windows, we cannot use + // uint32, uint64, and etc here. + typedef int Int; + typedef unsigned int UInt; +}; + +// The specialization for size 8. +template <> +class TypeWithSize<8> { + public: +#if GTEST_OS_WINDOWS + typedef __int64 Int; + typedef unsigned __int64 UInt; +#else + typedef long long Int; // NOLINT + typedef unsigned long long UInt; // NOLINT +#endif // GTEST_OS_WINDOWS +}; + +// Integer types of known sizes. +typedef TypeWithSize<4>::Int Int32; +typedef TypeWithSize<4>::UInt UInt32; +typedef TypeWithSize<8>::Int Int64; +typedef TypeWithSize<8>::UInt UInt64; +typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. + +// Utilities for command line flags and environment variables. + +// Macro for referencing flags. +#define GTEST_FLAG(name) FLAGS_gtest_##name + +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_int32_(name) \ + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) +#define GTEST_DECLARE_string_(name) \ + GTEST_API_ extern ::std::string GTEST_FLAG(name) + +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + GTEST_API_ bool GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) + +// Thread annotations +#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) +#define GTEST_LOCK_EXCLUDED_(locks) + +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +// TODO(chandlerc): Find a better way to refactor flag and environment parsing +// out of both gtest-port.cc and gtest.cc to avoid exporting this utility +// function. +bool ParseInt32(const Message& src_text, const char* str, Int32* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromGTestEnv(const char* flag, bool default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +const char* StringFromGTestEnv(const char* flag, const char* default_val); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +#if GTEST_OS_LINUX +# include +# include +# include +# include +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#include +#include +#include +#include +#include +#include + +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the Message class. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ + +#include + + +// Ensures that there is at least one operator<< in the global namespace. +// See Message& operator<<(...) below for why. +void operator<<(const testing::internal::Secret&, int); + +namespace testing { + +// The Message class works like an ostream repeater. +// +// Typical usage: +// +// 1. You stream a bunch of values to a Message object. +// It will remember the text in a stringstream. +// 2. Then you stream the Message object to an ostream. +// This causes the text in the Message to be streamed +// to the ostream. +// +// For example; +// +// testing::Message foo; +// foo << 1 << " != " << 2; +// std::cout << foo; +// +// will print "1 != 2". +// +// Message is not intended to be inherited from. In particular, its +// destructor is not virtual. +// +// Note that stringstream behaves differently in gcc and in MSVC. You +// can stream a NULL char pointer to it in the former, but not in the +// latter (it causes an access violation if you do). The Message +// class hides this difference by treating a NULL char pointer as +// "(null)". +class GTEST_API_ Message { + private: + // The type of basic IO manipulators (endl, ends, and flush) for + // narrow streams. + typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); + + public: + // Constructs an empty Message. + Message(); + + // Copy constructor. + Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT + *ss_ << msg.GetString(); + } + + // Constructs a Message from a C-string. + explicit Message(const char* str) : ss_(new ::std::stringstream) { + *ss_ << str; + } + +#if GTEST_OS_SYMBIAN + // Streams a value (either a pointer or not) to this object. + template + inline Message& operator <<(const T& value) { + StreamHelper(typename internal::is_pointer::type(), value); + return *this; + } +#else + // Streams a non-pointer value to this object. + template + inline Message& operator <<(const T& val) { + // Some libraries overload << for STL containers. These + // overloads are defined in the global namespace instead of ::std. + // + // C++'s symbol lookup rule (i.e. Koenig lookup) says that these + // overloads are visible in either the std namespace or the global + // namespace, but not other namespaces, including the testing + // namespace which Google Test's Message class is in. + // + // To allow STL containers (and other types that has a << operator + // defined in the global namespace) to be used in Google Test + // assertions, testing::Message must access the custom << operator + // from the global namespace. With this using declaration, + // overloads of << defined in the global namespace and those + // visible via Koenig lookup are both exposed in this function. + using ::operator <<; + *ss_ << val; + return *this; + } + + // Streams a pointer value to this object. + // + // This function is an overload of the previous one. When you + // stream a pointer to a Message, this definition will be used as it + // is more specialized. (The C++ Standard, section + // [temp.func.order].) If you stream a non-pointer, then the + // previous definition will be used. + // + // The reason for this overload is that streaming a NULL pointer to + // ostream is undefined behavior. Depending on the compiler, you + // may get "0", "(nil)", "(null)", or an access violation. To + // ensure consistent result across compilers, we always treat NULL + // as "(null)". + template + inline Message& operator <<(T* const& pointer) { // NOLINT + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + return *this; + } +#endif // GTEST_OS_SYMBIAN + + // Since the basic IO manipulators are overloaded for both narrow + // and wide streams, we have to provide this specialized definition + // of operator <<, even though its body is the same as the + // templatized version above. Without this definition, streaming + // endl or other basic IO manipulators to Message will confuse the + // compiler. + Message& operator <<(BasicNarrowIoManip val) { + *ss_ << val; + return *this; + } + + // Instead of 1/0, we want to see true/false for bool values. + Message& operator <<(bool b) { + return *this << (b ? "true" : "false"); + } + + // These two overloads allow streaming a wide C string to a Message + // using the UTF-8 encoding. + Message& operator <<(const wchar_t* wide_c_str); + Message& operator <<(wchar_t* wide_c_str); + +#if GTEST_HAS_STD_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::std::wstring& wstr); +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::wstring& wstr); +#endif // GTEST_HAS_GLOBAL_WSTRING + + // Gets the text streamed to this object so far as an std::string. + // Each '\0' character in the buffer is replaced with "\\0". + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + std::string GetString() const; + + private: + +#if GTEST_OS_SYMBIAN + // These are needed as the Nokia Symbian Compiler cannot decide between + // const T& and const T* in a function template. The Nokia compiler _can_ + // decide between class template specializations for T and T*, so a + // tr1::type_traits-like is_pointer works, and we can overload on that. + template + inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + } + template + inline void StreamHelper(internal::false_type /*is_pointer*/, + const T& value) { + // See the comments in Message& operator <<(const T&) above for why + // we need this using statement. + using ::operator <<; + *ss_ << value; + } +#endif // GTEST_OS_SYMBIAN + + // We'll hold the text streamed to this object here. + const internal::scoped_ptr< ::std::stringstream> ss_; + + // We declare (but don't implement) this to prevent the compiler + // from implementing the assignment operator. + void operator=(const Message&); +}; + +// Streams a Message to an ostream. +inline std::ostream& operator <<(std::ostream& os, const Message& sb) { + return os << sb.GetString(); +} + +namespace internal { + +// Converts a streamable value to an std::string. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +template +std::string StreamableToString(const T& streamable) { + return (Message() << streamable).GetString(); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares the String class and functions used internally by +// Google Test. They are subject to change without notice. They should not used +// by code external to Google Test. +// +// This header file is #included by . +// It should not be #included by other files. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ + +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +# include +#endif + +#include +#include + + +namespace testing { +namespace internal { + +// String - an abstract class holding static string utilities. +class GTEST_API_ String { + public: + // Static utility methods + + // Clones a 0-terminated C string, allocating memory using new. The + // caller is responsible for deleting the return value using + // delete[]. Returns the cloned string, or NULL if the input is + // NULL. + // + // This is different from strdup() in string.h, which allocates + // memory using malloc(). + static const char* CloneCString(const char* c_str); + +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be + // able to pass strings to Win32 APIs on CE we need to convert them + // to 'Unicode', UTF-16. + + // Creates a UTF-16 wide string from the given ANSI string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the wide string, or NULL if the + // input is NULL. + // + // The wide string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static LPCWSTR AnsiToUtf16(const char* c_str); + + // Creates an ANSI string from the given wide string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the ANSI string, or NULL if the + // input is NULL. + // + // The returned string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static const char* Utf16ToAnsi(LPCWSTR utf16_str); +#endif + + // Compares two C strings. Returns true iff they have the same content. + // + // Unlike strcmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CStringEquals(const char* lhs, const char* rhs); + + // Converts a wide C string to a String using the UTF-8 encoding. + // NULL will be converted to "(null)". If an error occurred during + // the conversion, "(failed to convert from wide string)" is + // returned. + static std::string ShowWideCString(const wchar_t* wide_c_str); + + // Compares two wide C strings. Returns true iff they have the same + // content. + // + // Unlike wcscmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); + + // Compares two C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike strcasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CaseInsensitiveCStringEquals(const char* lhs, + const char* rhs); + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. + static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs); + + // Returns true iff the given string ends with the given suffix, ignoring + // case. Any string is considered to end with an empty suffix. + static bool EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix); + + // Formats an int value as "%02d". + static std::string FormatIntWidth2(int value); // "%02d" for width == 2 + + // Formats an int value as "%X". + static std::string FormatHexInt(int value); + + // Formats a byte as "%02X". + static std::string FormatByte(unsigned char value); + + private: + String(); // Not meant to be instantiated. +}; // class String + +// Gets the content of the stringstream's buffer as an std::string. Each '\0' +// character in the buffer is replaced with "\\0". +GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +// 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: keith.ray@gmail.com (Keith Ray) +// +// Google Test filepath utilities +// +// This header file declares classes and functions used internally by +// Google Test. They are subject to change without notice. +// +// This file is #included in . +// Do not include this header file separately! + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ + + +namespace testing { +namespace internal { + +// FilePath - a class for file and directory pathname manipulation which +// handles platform-specific conventions (like the pathname separator). +// Used for helper functions for naming files in a directory for xml output. +// Except for Set methods, all methods are const or static, which provides an +// "immutable value object" -- useful for peace of mind. +// A FilePath with a value ending in a path separator ("like/this/") represents +// a directory, otherwise it is assumed to represent a file. In either case, +// it may or may not represent an actual file or directory in the file system. +// Names are NOT checked for syntax correctness -- no checking for illegal +// characters, malformed paths, etc. + +class GTEST_API_ FilePath { + public: + FilePath() : pathname_("") { } + FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } + + explicit FilePath(const std::string& pathname) : pathname_(pathname) { + Normalize(); + } + + FilePath& operator=(const FilePath& rhs) { + Set(rhs); + return *this; + } + + void Set(const FilePath& rhs) { + pathname_ = rhs.pathname_; + } + + const std::string& string() const { return pathname_; } + const char* c_str() const { return pathname_.c_str(); } + + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + + // Given directory = "dir", base_name = "test", number = 0, + // extension = "xml", returns "dir/test.xml". If number is greater + // than zero (e.g., 12), returns "dir/test_12.xml". + // On Windows platform, uses \ as the separator rather than /. + static FilePath MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension); + + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + + // Returns a pathname for a file that does not currently exist. The pathname + // will be directory/base_name.extension or + // directory/base_name_.extension if directory/base_name.extension + // already exists. The number will be incremented until a pathname is found + // that does not already exist. + // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. + // There could be a race condition if two or more processes are calling this + // function at the same time -- they could both pick the same filename. + static FilePath GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension); + + // Returns true iff the path is "". + bool IsEmpty() const { return pathname_.empty(); } + + // If input name has a trailing separator character, removes it and returns + // the name, otherwise return the name string unmodified. + // On Windows platform, uses \ as the separator, other platforms use /. + FilePath RemoveTrailingPathSeparator() const; + + // Returns a copy of the FilePath with the directory part removed. + // Example: FilePath("path/to/file").RemoveDirectoryName() returns + // FilePath("file"). If there is no directory part ("just_a_file"), it returns + // the FilePath unmodified. If there is no file part ("just_a_dir/") it + // returns an empty FilePath (""). + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveDirectoryName() const; + + // RemoveFileName returns the directory path with the filename removed. + // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". + // If the FilePath is "a_file" or "/a_file", RemoveFileName returns + // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does + // not have a file, like "just/a/dir/", it returns the FilePath unmodified. + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveFileName() const; + + // Returns a copy of the FilePath with the case-insensitive extension removed. + // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns + // FilePath("dir/file"). If a case-insensitive extension is not + // found, returns a copy of the original FilePath. + FilePath RemoveExtension(const char* extension) const; + + // Creates directories so that path exists. Returns true if successful or if + // the directories already exist; returns false if unable to create + // directories for any reason. Will also return false if the FilePath does + // not represent a directory (that is, it doesn't end with a path separator). + bool CreateDirectoriesRecursively() const; + + // Create the directory so that path exists. Returns true if successful or + // if the directory already exists; returns false if unable to create the + // directory for any reason, including if the parent directory does not + // exist. Not named "CreateDirectory" because that's a macro on Windows. + bool CreateFolder() const; + + // Returns true if FilePath describes something in the file-system, + // either a file, directory, or whatever, and that something exists. + bool FileOrDirectoryExists() const; + + // Returns true if pathname describes a directory in the file-system + // that exists. + bool DirectoryExists() const; + + // Returns true if FilePath ends with a path separator, which indicates that + // it is intended to represent a directory. Returns false otherwise. + // This does NOT check that a directory (or file) actually exists. + bool IsDirectory() const; + + // Returns true if pathname describes a root directory. (Windows has one + // root directory per disk drive.) + bool IsRootDirectory() const; + + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + + private: + // Replaces multiple consecutive separators with a single separator. + // For example, "bar///foo" becomes "bar/foo". Does not eliminate other + // redundancies that might be in a pathname involving "." or "..". + // + // A pathname with multiple consecutive separators may occur either through + // user error or as a result of some scripts or APIs that generate a pathname + // with a trailing separator. On other platforms the same API or script + // may NOT generate a pathname with a trailing "/". Then elsewhere that + // pathname may have another "/" and pathname components added to it, + // without checking for the separator already being there. + // The script language and operating system may allow paths like "foo//bar" + // but some of the functions in FilePath will not handle that correctly. In + // particular, RemoveTrailingPathSeparator() only removes one separator, and + // it is called in CreateDirectoriesRecursively() assuming that it will change + // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". + + void Normalize(); + + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + + std::string pathname_; +}; // class FilePath + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +// This file was GENERATED by command: +// pump.py gtest-type-util.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) + +// Type utilities needed for implementing typed and type-parameterized +// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently we support at most 50 types in a list, and at most 50 +// type-parameterized tests in one type-parameterized test case. +// Please contact googletestframework@googlegroups.com if you need +// more. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + + +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +# if GTEST_HAS_CXXABI_H_ +# include +# elif defined(__HP_aCC) +# include +# endif // GTEST_HASH_CXXABI_H_ + +namespace testing { +namespace internal { + +// GetTypeName() returns a human-readable name of type T. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +std::string GetTypeName() { +# if GTEST_HAS_RTTI + + const char* const name = typeid(T).name(); +# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) + int status = 0; + // gcc's implementation of typeid(T).name() mangles the type name, + // so we have to demangle it. +# if GTEST_HAS_CXXABI_H_ + using abi::__cxa_demangle; +# endif // GTEST_HAS_CXXABI_H_ + char* const readable_name = __cxa_demangle(name, 0, 0, &status); + const std::string name_str(status == 0 ? readable_name : name); + free(readable_name); + return name_str; +# else + return name; +# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC + +# else + + return ""; + +# endif // GTEST_HAS_RTTI +} + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// AssertyTypeEq::type is defined iff T1 and T2 are the same +// type. This can be used as a compile-time assertion to ensure that +// two types are equal. + +template +struct AssertTypeEq; + +template +struct AssertTypeEq { + typedef bool type; +}; + +// A unique type used as the default value for the arguments of class +// template Types. This allows us to simulate variadic templates +// (e.g. Types, Type, and etc), which C++ doesn't +// support directly. +struct None {}; + +// The following family of struct and struct templates are used to +// represent type lists. In particular, TypesN +// represents a type list with N types (T1, T2, ..., and TN) in it. +// Except for Types0, every struct in the family has two member types: +// Head for the first type in the list, and Tail for the rest of the +// list. + +// The empty type list. +struct Types0 {}; + +// Type lists of length 1, 2, 3, and so on. + +template +struct Types1 { + typedef T1 Head; + typedef Types0 Tail; +}; +template +struct Types2 { + typedef T1 Head; + typedef Types1 Tail; +}; + +template +struct Types3 { + typedef T1 Head; + typedef Types2 Tail; +}; + +template +struct Types4 { + typedef T1 Head; + typedef Types3 Tail; +}; + +template +struct Types5 { + typedef T1 Head; + typedef Types4 Tail; +}; + +template +struct Types6 { + typedef T1 Head; + typedef Types5 Tail; +}; + +template +struct Types7 { + typedef T1 Head; + typedef Types6 Tail; +}; + +template +struct Types8 { + typedef T1 Head; + typedef Types7 Tail; +}; + +template +struct Types9 { + typedef T1 Head; + typedef Types8 Tail; +}; + +template +struct Types10 { + typedef T1 Head; + typedef Types9 Tail; +}; + +template +struct Types11 { + typedef T1 Head; + typedef Types10 Tail; +}; + +template +struct Types12 { + typedef T1 Head; + typedef Types11 Tail; +}; + +template +struct Types13 { + typedef T1 Head; + typedef Types12 Tail; +}; + +template +struct Types14 { + typedef T1 Head; + typedef Types13 Tail; +}; + +template +struct Types15 { + typedef T1 Head; + typedef Types14 Tail; +}; + +template +struct Types16 { + typedef T1 Head; + typedef Types15 Tail; +}; + +template +struct Types17 { + typedef T1 Head; + typedef Types16 Tail; +}; + +template +struct Types18 { + typedef T1 Head; + typedef Types17 Tail; +}; + +template +struct Types19 { + typedef T1 Head; + typedef Types18 Tail; +}; + +template +struct Types20 { + typedef T1 Head; + typedef Types19 Tail; +}; + +template +struct Types21 { + typedef T1 Head; + typedef Types20 Tail; +}; + +template +struct Types22 { + typedef T1 Head; + typedef Types21 Tail; +}; + +template +struct Types23 { + typedef T1 Head; + typedef Types22 Tail; +}; + +template +struct Types24 { + typedef T1 Head; + typedef Types23 Tail; +}; + +template +struct Types25 { + typedef T1 Head; + typedef Types24 Tail; +}; + +template +struct Types26 { + typedef T1 Head; + typedef Types25 Tail; +}; + +template +struct Types27 { + typedef T1 Head; + typedef Types26 Tail; +}; + +template +struct Types28 { + typedef T1 Head; + typedef Types27 Tail; +}; + +template +struct Types29 { + typedef T1 Head; + typedef Types28 Tail; +}; + +template +struct Types30 { + typedef T1 Head; + typedef Types29 Tail; +}; + +template +struct Types31 { + typedef T1 Head; + typedef Types30 Tail; +}; + +template +struct Types32 { + typedef T1 Head; + typedef Types31 Tail; +}; + +template +struct Types33 { + typedef T1 Head; + typedef Types32 Tail; +}; + +template +struct Types34 { + typedef T1 Head; + typedef Types33 Tail; +}; + +template +struct Types35 { + typedef T1 Head; + typedef Types34 Tail; +}; + +template +struct Types36 { + typedef T1 Head; + typedef Types35 Tail; +}; + +template +struct Types37 { + typedef T1 Head; + typedef Types36 Tail; +}; + +template +struct Types38 { + typedef T1 Head; + typedef Types37 Tail; +}; + +template +struct Types39 { + typedef T1 Head; + typedef Types38 Tail; +}; + +template +struct Types40 { + typedef T1 Head; + typedef Types39 Tail; +}; + +template +struct Types41 { + typedef T1 Head; + typedef Types40 Tail; +}; + +template +struct Types42 { + typedef T1 Head; + typedef Types41 Tail; +}; + +template +struct Types43 { + typedef T1 Head; + typedef Types42 Tail; +}; + +template +struct Types44 { + typedef T1 Head; + typedef Types43 Tail; +}; + +template +struct Types45 { + typedef T1 Head; + typedef Types44 Tail; +}; + +template +struct Types46 { + typedef T1 Head; + typedef Types45 Tail; +}; + +template +struct Types47 { + typedef T1 Head; + typedef Types46 Tail; +}; + +template +struct Types48 { + typedef T1 Head; + typedef Types47 Tail; +}; + +template +struct Types49 { + typedef T1 Head; + typedef Types48 Tail; +}; + +template +struct Types50 { + typedef T1 Head; + typedef Types49 Tail; +}; + + +} // namespace internal + +// We don't want to require the users to write TypesN<...> directly, +// as that would require them to count the length. Types<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Types +// will appear as Types in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Types, and Google Test will translate +// that to TypesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Types template. +template +struct Types { + typedef internal::Types50 type; +}; + +template <> +struct Types { + typedef internal::Types0 type; +}; +template +struct Types { + typedef internal::Types1 type; +}; +template +struct Types { + typedef internal::Types2 type; +}; +template +struct Types { + typedef internal::Types3 type; +}; +template +struct Types { + typedef internal::Types4 type; +}; +template +struct Types { + typedef internal::Types5 type; +}; +template +struct Types { + typedef internal::Types6 type; +}; +template +struct Types { + typedef internal::Types7 type; +}; +template +struct Types { + typedef internal::Types8 type; +}; +template +struct Types { + typedef internal::Types9 type; +}; +template +struct Types { + typedef internal::Types10 type; +}; +template +struct Types { + typedef internal::Types11 type; +}; +template +struct Types { + typedef internal::Types12 type; +}; +template +struct Types { + typedef internal::Types13 type; +}; +template +struct Types { + typedef internal::Types14 type; +}; +template +struct Types { + typedef internal::Types15 type; +}; +template +struct Types { + typedef internal::Types16 type; +}; +template +struct Types { + typedef internal::Types17 type; +}; +template +struct Types { + typedef internal::Types18 type; +}; +template +struct Types { + typedef internal::Types19 type; +}; +template +struct Types { + typedef internal::Types20 type; +}; +template +struct Types { + typedef internal::Types21 type; +}; +template +struct Types { + typedef internal::Types22 type; +}; +template +struct Types { + typedef internal::Types23 type; +}; +template +struct Types { + typedef internal::Types24 type; +}; +template +struct Types { + typedef internal::Types25 type; +}; +template +struct Types { + typedef internal::Types26 type; +}; +template +struct Types { + typedef internal::Types27 type; +}; +template +struct Types { + typedef internal::Types28 type; +}; +template +struct Types { + typedef internal::Types29 type; +}; +template +struct Types { + typedef internal::Types30 type; +}; +template +struct Types { + typedef internal::Types31 type; +}; +template +struct Types { + typedef internal::Types32 type; +}; +template +struct Types { + typedef internal::Types33 type; +}; +template +struct Types { + typedef internal::Types34 type; +}; +template +struct Types { + typedef internal::Types35 type; +}; +template +struct Types { + typedef internal::Types36 type; +}; +template +struct Types { + typedef internal::Types37 type; +}; +template +struct Types { + typedef internal::Types38 type; +}; +template +struct Types { + typedef internal::Types39 type; +}; +template +struct Types { + typedef internal::Types40 type; +}; +template +struct Types { + typedef internal::Types41 type; +}; +template +struct Types { + typedef internal::Types42 type; +}; +template +struct Types { + typedef internal::Types43 type; +}; +template +struct Types { + typedef internal::Types44 type; +}; +template +struct Types { + typedef internal::Types45 type; +}; +template +struct Types { + typedef internal::Types46 type; +}; +template +struct Types { + typedef internal::Types47 type; +}; +template +struct Types { + typedef internal::Types48 type; +}; +template +struct Types { + typedef internal::Types49 type; +}; + +namespace internal { + +# define GTEST_TEMPLATE_ template class + +// The template "selector" struct TemplateSel is used to +// represent Tmpl, which must be a class template with one type +// parameter, as a type. TemplateSel::Bind::type is defined +// as the type Tmpl. This allows us to actually instantiate the +// template "selected" by TemplateSel. +// +// This trick is necessary for simulating typedef for class templates, +// which C++ doesn't support directly. +template +struct TemplateSel { + template + struct Bind { + typedef Tmpl type; + }; +}; + +# define GTEST_BIND_(TmplSel, T) \ + TmplSel::template Bind::type + +// A unique struct template used as the default value for the +// arguments of class template Templates. This allows us to simulate +// variadic templates (e.g. Templates, Templates, +// and etc), which C++ doesn't support directly. +template +struct NoneT {}; + +// The following family of struct and struct templates are used to +// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except +// for Templates0, every struct in the family has two member types: +// Head for the selector of the first template in the list, and Tail +// for the rest of the list. + +// The empty template list. +struct Templates0 {}; + +// Template lists of length 1, 2, 3, and so on. + +template +struct Templates1 { + typedef TemplateSel Head; + typedef Templates0 Tail; +}; +template +struct Templates2 { + typedef TemplateSel Head; + typedef Templates1 Tail; +}; + +template +struct Templates3 { + typedef TemplateSel Head; + typedef Templates2 Tail; +}; + +template +struct Templates4 { + typedef TemplateSel Head; + typedef Templates3 Tail; +}; + +template +struct Templates5 { + typedef TemplateSel Head; + typedef Templates4 Tail; +}; + +template +struct Templates6 { + typedef TemplateSel Head; + typedef Templates5 Tail; +}; + +template +struct Templates7 { + typedef TemplateSel Head; + typedef Templates6 Tail; +}; + +template +struct Templates8 { + typedef TemplateSel Head; + typedef Templates7 Tail; +}; + +template +struct Templates9 { + typedef TemplateSel Head; + typedef Templates8 Tail; +}; + +template +struct Templates10 { + typedef TemplateSel Head; + typedef Templates9 Tail; +}; + +template +struct Templates11 { + typedef TemplateSel Head; + typedef Templates10 Tail; +}; + +template +struct Templates12 { + typedef TemplateSel Head; + typedef Templates11 Tail; +}; + +template +struct Templates13 { + typedef TemplateSel Head; + typedef Templates12 Tail; +}; + +template +struct Templates14 { + typedef TemplateSel Head; + typedef Templates13 Tail; +}; + +template +struct Templates15 { + typedef TemplateSel Head; + typedef Templates14 Tail; +}; + +template +struct Templates16 { + typedef TemplateSel Head; + typedef Templates15 Tail; +}; + +template +struct Templates17 { + typedef TemplateSel Head; + typedef Templates16 Tail; +}; + +template +struct Templates18 { + typedef TemplateSel Head; + typedef Templates17 Tail; +}; + +template +struct Templates19 { + typedef TemplateSel Head; + typedef Templates18 Tail; +}; + +template +struct Templates20 { + typedef TemplateSel Head; + typedef Templates19 Tail; +}; + +template +struct Templates21 { + typedef TemplateSel Head; + typedef Templates20 Tail; +}; + +template +struct Templates22 { + typedef TemplateSel Head; + typedef Templates21 Tail; +}; + +template +struct Templates23 { + typedef TemplateSel Head; + typedef Templates22 Tail; +}; + +template +struct Templates24 { + typedef TemplateSel Head; + typedef Templates23 Tail; +}; + +template +struct Templates25 { + typedef TemplateSel Head; + typedef Templates24 Tail; +}; + +template +struct Templates26 { + typedef TemplateSel Head; + typedef Templates25 Tail; +}; + +template +struct Templates27 { + typedef TemplateSel Head; + typedef Templates26 Tail; +}; + +template +struct Templates28 { + typedef TemplateSel Head; + typedef Templates27 Tail; +}; + +template +struct Templates29 { + typedef TemplateSel Head; + typedef Templates28 Tail; +}; + +template +struct Templates30 { + typedef TemplateSel Head; + typedef Templates29 Tail; +}; + +template +struct Templates31 { + typedef TemplateSel Head; + typedef Templates30 Tail; +}; + +template +struct Templates32 { + typedef TemplateSel Head; + typedef Templates31 Tail; +}; + +template +struct Templates33 { + typedef TemplateSel Head; + typedef Templates32 Tail; +}; + +template +struct Templates34 { + typedef TemplateSel Head; + typedef Templates33 Tail; +}; + +template +struct Templates35 { + typedef TemplateSel Head; + typedef Templates34 Tail; +}; + +template +struct Templates36 { + typedef TemplateSel Head; + typedef Templates35 Tail; +}; + +template +struct Templates37 { + typedef TemplateSel Head; + typedef Templates36 Tail; +}; + +template +struct Templates38 { + typedef TemplateSel Head; + typedef Templates37 Tail; +}; + +template +struct Templates39 { + typedef TemplateSel Head; + typedef Templates38 Tail; +}; + +template +struct Templates40 { + typedef TemplateSel Head; + typedef Templates39 Tail; +}; + +template +struct Templates41 { + typedef TemplateSel Head; + typedef Templates40 Tail; +}; + +template +struct Templates42 { + typedef TemplateSel Head; + typedef Templates41 Tail; +}; + +template +struct Templates43 { + typedef TemplateSel Head; + typedef Templates42 Tail; +}; + +template +struct Templates44 { + typedef TemplateSel Head; + typedef Templates43 Tail; +}; + +template +struct Templates45 { + typedef TemplateSel Head; + typedef Templates44 Tail; +}; + +template +struct Templates46 { + typedef TemplateSel Head; + typedef Templates45 Tail; +}; + +template +struct Templates47 { + typedef TemplateSel Head; + typedef Templates46 Tail; +}; + +template +struct Templates48 { + typedef TemplateSel Head; + typedef Templates47 Tail; +}; + +template +struct Templates49 { + typedef TemplateSel Head; + typedef Templates48 Tail; +}; + +template +struct Templates50 { + typedef TemplateSel Head; + typedef Templates49 Tail; +}; + + +// We don't want to require the users to write TemplatesN<...> directly, +// as that would require them to count the length. Templates<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Templates +// will appear as Templates in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Templates, and Google Test will translate +// that to TemplatesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Templates template. +template +struct Templates { + typedef Templates50 type; +}; + +template <> +struct Templates { + typedef Templates0 type; +}; +template +struct Templates { + typedef Templates1 type; +}; +template +struct Templates { + typedef Templates2 type; +}; +template +struct Templates { + typedef Templates3 type; +}; +template +struct Templates { + typedef Templates4 type; +}; +template +struct Templates { + typedef Templates5 type; +}; +template +struct Templates { + typedef Templates6 type; +}; +template +struct Templates { + typedef Templates7 type; +}; +template +struct Templates { + typedef Templates8 type; +}; +template +struct Templates { + typedef Templates9 type; +}; +template +struct Templates { + typedef Templates10 type; +}; +template +struct Templates { + typedef Templates11 type; +}; +template +struct Templates { + typedef Templates12 type; +}; +template +struct Templates { + typedef Templates13 type; +}; +template +struct Templates { + typedef Templates14 type; +}; +template +struct Templates { + typedef Templates15 type; +}; +template +struct Templates { + typedef Templates16 type; +}; +template +struct Templates { + typedef Templates17 type; +}; +template +struct Templates { + typedef Templates18 type; +}; +template +struct Templates { + typedef Templates19 type; +}; +template +struct Templates { + typedef Templates20 type; +}; +template +struct Templates { + typedef Templates21 type; +}; +template +struct Templates { + typedef Templates22 type; +}; +template +struct Templates { + typedef Templates23 type; +}; +template +struct Templates { + typedef Templates24 type; +}; +template +struct Templates { + typedef Templates25 type; +}; +template +struct Templates { + typedef Templates26 type; +}; +template +struct Templates { + typedef Templates27 type; +}; +template +struct Templates { + typedef Templates28 type; +}; +template +struct Templates { + typedef Templates29 type; +}; +template +struct Templates { + typedef Templates30 type; +}; +template +struct Templates { + typedef Templates31 type; +}; +template +struct Templates { + typedef Templates32 type; +}; +template +struct Templates { + typedef Templates33 type; +}; +template +struct Templates { + typedef Templates34 type; +}; +template +struct Templates { + typedef Templates35 type; +}; +template +struct Templates { + typedef Templates36 type; +}; +template +struct Templates { + typedef Templates37 type; +}; +template +struct Templates { + typedef Templates38 type; +}; +template +struct Templates { + typedef Templates39 type; +}; +template +struct Templates { + typedef Templates40 type; +}; +template +struct Templates { + typedef Templates41 type; +}; +template +struct Templates { + typedef Templates42 type; +}; +template +struct Templates { + typedef Templates43 type; +}; +template +struct Templates { + typedef Templates44 type; +}; +template +struct Templates { + typedef Templates45 type; +}; +template +struct Templates { + typedef Templates46 type; +}; +template +struct Templates { + typedef Templates47 type; +}; +template +struct Templates { + typedef Templates48 type; +}; +template +struct Templates { + typedef Templates49 type; +}; + +// The TypeList template makes it possible to use either a single type +// or a Types<...> list in TYPED_TEST_CASE() and +// INSTANTIATE_TYPED_TEST_CASE_P(). + +template +struct TypeList { + typedef Types1 type; +}; + +template +struct TypeList > { + typedef typename Types::type type; +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + +// Due to C++ preprocessor weirdness, we need double indirection to +// concatenate two tokens when one of them is __LINE__. Writing +// +// foo ## __LINE__ +// +// will result in the token foo__LINE__, instead of foo followed by +// the current line number. For more details, see +// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 +#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) +#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar + +class ProtocolMessage; +namespace proto2 { class Message; } + +namespace testing { + +// Forward declarations. + +class AssertionResult; // Result of an assertion. +class Message; // Represents a failure message. +class Test; // Represents a test. +class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. +class UnitTest; // A collection of test cases. + +template +::std::string PrintToString(const T& value); + +namespace internal { + +struct TraceInfo; // Information about a trace point. +class ScopedTrace; // Implements scoped trace. +class TestInfoImpl; // Opaque implementation of TestInfo +class UnitTestImpl; // Opaque implementation of UnitTest + +// How many times InitGoogleTest() has been called. +GTEST_API_ extern int g_init_gtest_count; + +// The text used in failure messages to indicate the start of the +// stack trace. +GTEST_API_ extern const char kStackTraceMarker[]; + +// Two overloaded helpers for checking at compile time whether an +// expression is a null pointer literal (i.e. NULL or any 0-valued +// compile-time integral constant). Their return values have +// different sizes, so we can use sizeof() to test which version is +// picked by the compiler. These helpers have no implementations, as +// we only need their signatures. +// +// Given IsNullLiteralHelper(x), the compiler will pick the first +// version if x can be implicitly converted to Secret*, and pick the +// second version otherwise. Since Secret is a secret and incomplete +// type, the only expression a user can write that has type Secret* is +// a null pointer literal. Therefore, we know that x is a null +// pointer literal if and only if the first version is picked by the +// compiler. +char IsNullLiteralHelper(Secret* p); +char (&IsNullLiteralHelper(...))[2]; // NOLINT + +// A compile-time bool constant that is true if and only if x is a +// null pointer literal (i.e. NULL or any 0-valued compile-time +// integral constant). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_IS_NULL_LITERAL_(x) false +#else +# define GTEST_IS_NULL_LITERAL_(x) \ + (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) +#endif // GTEST_ELLIPSIS_NEEDS_POD_ + +// Appends the user-supplied message to the Google-Test-generated message. +GTEST_API_ std::string AppendUserMessage( + const std::string& gtest_msg, const Message& user_msg); + +#if GTEST_HAS_EXCEPTIONS + +// This exception is thrown by (and only by) a failed Google Test +// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions +// are enabled). We derive it from std::runtime_error, which is for +// errors presumably detectable only at run time. Since +// std::runtime_error inherits from std::exception, many testing +// frameworks know how to extract and print the message inside it. +class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure); +}; + +#endif // GTEST_HAS_EXCEPTIONS + +// A helper class for creating scoped traces in user programs. +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + ScopedTrace(const char* file, int line, const Message& message); + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +// This template class represents an IEEE floating-point number +// (either single-precision or double-precision, depending on the +// template parameters). +// +// The purpose of this class is to do more sophisticated number +// comparison. (Due to round-off error, etc, it's very unlikely that +// two floating-points will be equal exactly. Hence a naive +// comparison by the == operation often doesn't work.) +// +// Format of IEEE floating-point: +// +// The most-significant bit being the leftmost, an IEEE +// floating-point looks like +// +// sign_bit exponent_bits fraction_bits +// +// Here, sign_bit is a single bit that designates the sign of the +// number. +// +// For float, there are 8 exponent bits and 23 fraction bits. +// +// For double, there are 11 exponent bits and 52 fraction bits. +// +// More details can be found at +// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +template +class FloatingPoint { + public: + // Defines the unsigned integer type that has the same size as the + // floating point number. + typedef typename TypeWithSize::UInt Bits; + + // Constants. + + // # of bits in a number. + static const size_t kBitCount = 8*sizeof(RawType); + + // # of fraction bits in a number. + static const size_t kFractionBitCount = + std::numeric_limits::digits - 1; + + // # of exponent bits in a number. + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; + + // The mask for the sign bit. + static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); + + // The mask for the fraction bits. + static const Bits kFractionBitMask = + ~static_cast(0) >> (kExponentBitCount + 1); + + // The mask for the exponent bits. + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); + + // How many ULP's (Units in the Last Place) we want to tolerate when + // comparing two numbers. The larger the value, the more error we + // allow. A 0 value means that two numbers must be exactly the same + // to be considered equal. + // + // The maximum error of a single floating-point operation is 0.5 + // units in the last place. On Intel CPU's, all floating-point + // calculations are done with 80-bit precision, while double has 64 + // bits. Therefore, 4 should be enough for ordinary use. + // + // See the following article for more details on ULP: + // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + static const size_t kMaxUlps = 4; + + // Constructs a FloatingPoint from a raw floating-point number. + // + // On an Intel CPU, passing a non-normalized NAN (Not a Number) + // around may change its bits, although the new value is guaranteed + // to be also a NAN. Therefore, don't expect this constructor to + // preserve the bits in x when x is a NAN. + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } + + // Static methods + + // Reinterprets a bit pattern as a floating-point number. + // + // This function is needed to test the AlmostEquals() method. + static RawType ReinterpretBits(const Bits bits) { + FloatingPoint fp(0); + fp.u_.bits_ = bits; + return fp.u_.value_; + } + + // Returns the floating-point number that represent positive infinity. + static RawType Infinity() { + return ReinterpretBits(kExponentBitMask); + } + + // Returns the maximum representable finite floating-point number. + static RawType Max(); + + // Non-static methods + + // Returns the bits that represents this number. + const Bits &bits() const { return u_.bits_; } + + // Returns the exponent bits of this number. + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } + + // Returns the fraction bits of this number. + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } + + // Returns the sign bit of this number. + Bits sign_bit() const { return kSignBitMask & u_.bits_; } + + // Returns true iff this is NAN (not a number). + bool is_nan() const { + // It's a NAN if the exponent bits are all ones and the fraction + // bits are not entirely zeros. + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); + } + + // Returns true iff this number is at most kMaxUlps ULP's away from + // rhs. In particular, this function: + // + // - returns false if either number is (or both are) NAN. + // - treats really large numbers as almost equal to infinity. + // - thinks +0.0 and -0.0 are 0 DLP's apart. + bool AlmostEquals(const FloatingPoint& rhs) const { + // The IEEE standard says that any comparison operation involving + // a NAN must return false. + if (is_nan() || rhs.is_nan()) return false; + + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; + } + + private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + + // Converts an integer from the sign-and-magnitude representation to + // the biased representation. More precisely, let N be 2 to the + // power of (kBitCount - 1), an integer x is represented by the + // unsigned number x + N. + // + // For instance, + // + // -N + 1 (the most negative number representable using + // sign-and-magnitude) is represented by 1; + // 0 is represented by N; and + // N - 1 (the biggest number representable using + // sign-and-magnitude) is represented by 2N - 1. + // + // Read http://en.wikipedia.org/wiki/Signed_number_representations + // for more details on signed number representations. + static Bits SignAndMagnitudeToBiased(const Bits &sam) { + if (kSignBitMask & sam) { + // sam represents a negative number. + return ~sam + 1; + } else { + // sam represents a positive number. + return kSignBitMask | sam; + } + } + + // Given two numbers in the sign-and-magnitude representation, + // returns the distance between them as an unsigned number. + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, + const Bits &sam2) { + const Bits biased1 = SignAndMagnitudeToBiased(sam1); + const Bits biased2 = SignAndMagnitudeToBiased(sam2); + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); + } + + FloatingPointUnion u_; +}; + +// We cannot use std::numeric_limits::max() as it clashes with the max() +// macro defined by . +template <> +inline float FloatingPoint::Max() { return FLT_MAX; } +template <> +inline double FloatingPoint::Max() { return DBL_MAX; } + +// Typedefs the instances of the FloatingPoint template class that we +// care to use. +typedef FloatingPoint Float; +typedef FloatingPoint Double; + +// In order to catch the mistake of putting tests that use different +// test fixture classes in the same test case, we need to assign +// unique IDs to fixture classes and compare them. The TypeId type is +// used to hold such IDs. The user should treat TypeId as an opaque +// type: the only operation allowed on TypeId values is to compare +// them for equality using the == operator. +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; + +// GetTypeId() returns the ID of type T. Different values will be +// returned for different types. Calling the function twice with the +// same type argument is guaranteed to return the same ID. +template +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); +} + +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +GTEST_API_ TypeId GetTestTypeId(); + +// Defines the abstract factory interface that creates instances +// of a Test object. +class TestFactoryBase { + public: + virtual ~TestFactoryBase() {} + + // Creates a test instance to run. The instance is both created and destroyed + // within TestInfoImpl::Run() + virtual Test* CreateTest() = 0; + + protected: + TestFactoryBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); +}; + +// This class provides implementation of TeastFactoryBase interface. +// It is used in TEST and TEST_F macros. +template +class TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + +#if GTEST_OS_WINDOWS + +// Predicate-formatters for implementing the HRESULT checking macros +// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} +// We pass a long instead of HRESULT to avoid causing an +// include dependency for the HRESULT type. +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT + +#endif // GTEST_OS_WINDOWS + +// Types of SetUpTestCase() and TearDownTestCase() functions. +typedef void (*SetUpTestCaseFunc)(); +typedef void (*TearDownTestCaseFunc)(); + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param text representation of the test's value parameter, +// or NULL if this is not a type-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory); + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// State of the definition of a type-parameterized test case. +class GTEST_API_ TypedTestCasePState { + public: + TypedTestCasePState() : registered_(false) {} + + // Adds the given test name to defined_test_names_ and return true + // if the test case hasn't been registered; otherwise aborts the + // program. + bool AddTestName(const char* file, int line, const char* case_name, + const char* test_name) { + if (registered_) { + fprintf(stderr, "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + FormatFileLocation(file, line).c_str(), test_name, case_name); + fflush(stderr); + posix::Abort(); + } + defined_test_names_.insert(test_name); + return true; + } + + // Verifies that registered_tests match the test names in + // defined_test_names_; returns registered_tests if successful, or + // aborts the program otherwise. + const char* VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests); + + private: + bool registered_; + ::std::set defined_test_names_; +}; + +// Skips to the first non-space char after the first comma in 'str'; +// returns NULL if no comma is found in 'str'. +inline const char* SkipComma(const char* str) { + const char* comma = strchr(str, ','); + if (comma == NULL) { + return NULL; + } + while (IsSpace(*(++comma))) {} + return comma; +} + +// Returns the prefix of 'str' before the first comma in it; returns +// the entire string if it contains no comma. +inline std::string GetPrefixUntilComma(const char* str) { + const char* comma = strchr(str, ','); + return comma == NULL ? str : std::string(str, comma); +} + +// TypeParameterizedTest::Register() +// registers a list of type-parameterized tests with Google Test. The +// return value is insignificant - we just need to return something +// such that we can call this function in a namespace scope. +// +// Implementation note: The GTEST_TEMPLATE_ macro declares a template +// template parameter. It's defined in gtest-type-util.h. +template +class TypeParameterizedTest { + public: + // 'index' is the index of the test in the type list 'Types' + // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // Types). Valid values for 'index' are [0, N - 1] where N is the + // length of Types. + static bool Register(const char* prefix, const char* case_name, + const char* test_names, int index) { + typedef typename Types::Head Type; + typedef Fixture FixtureClass; + typedef typename GTEST_BIND_(TestSel, Type) TestClass; + + // First, registers the first type-parameterized test in the type + // list. + MakeAndRegisterTestInfo( + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" + + StreamableToString(index)).c_str(), + GetPrefixUntilComma(test_names).c_str(), + GetTypeName().c_str(), + NULL, // No value parameter. + GetTypeId(), + TestClass::SetUpTestCase, + TestClass::TearDownTestCase, + new TestFactoryImpl); + + // Next, recurses (at compile time) with the tail of the type list. + return TypeParameterizedTest + ::Register(prefix, case_name, test_names, index + 1); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTest { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/, int /*index*/) { + return true; + } +}; + +// TypeParameterizedTestCase::Register() +// registers *all combinations* of 'Tests' and 'Types' with Google +// Test. The return value is insignificant - we just need to return +// something such that we can call this function in a namespace scope. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* prefix, const char* case_name, + const char* test_names) { + typedef typename Tests::Head Head; + + // First, register the first test in 'Test' for each type in 'Types'. + TypeParameterizedTest::Register( + prefix, case_name, test_names, 0); + + // Next, recurses (at compile time) with the tail of the test list. + return TypeParameterizedTestCase + ::Register(prefix, case_name, SkipComma(test_names)); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { + return true; + } +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +GTEST_API_ std::string GetCurrentOsStackTraceExceptTop( + UnitTest* unit_test, int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// Helper for suppressing false warning from Clang on a const char* +// variable declared in a conditional expression always being NULL in +// the else branch. +struct GTEST_API_ ConstCharPtr { + ConstCharPtr(const char* str) : value(str) {} + operator bool() const { return true; } + const char* value; +}; + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} + + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; + +// Defining a variable of type CompileAssertTypesEqual will cause a +// compiler error iff T1 and T2 are different types. +template +struct CompileAssertTypesEqual; + +template +struct CompileAssertTypesEqual { +}; + +// Removes the reference from a type if it is a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::remove_reference, which is not widely available yet. +template +struct RemoveReference { typedef T type; }; // NOLINT +template +struct RemoveReference { typedef T type; }; // NOLINT + +// A handy wrapper around RemoveReference that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_REFERENCE_(T) \ + typename ::testing::internal::RemoveReference::type + +// Removes const from a type if it is a const type, otherwise leaves +// it unchanged. This is the same as tr1::remove_const, which is not +// widely available yet. +template +struct RemoveConst { typedef T type; }; // NOLINT +template +struct RemoveConst { typedef T type; }; // NOLINT + +// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above +// definition to fail to remove the const in 'const int[3]' and 'const +// char[3][4]'. The following specialization works around the bug. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; + +#if defined(_MSC_VER) && _MSC_VER < 1400 +// This is the only specialization that allows VC++ 7.1 to remove const in +// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC +// and thus needs to be conditionally compiled. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; +#endif + +// A handy wrapper around RemoveConst that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_CONST_(T) \ + typename ::testing::internal::RemoveConst::type + +// Turns const U&, U&, const U, and U all into U. +#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ + GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) + +// Adds reference to a type if it is not a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::add_reference, which is not widely available yet. +template +struct AddReference { typedef T& type; }; // NOLINT +template +struct AddReference { typedef T& type; }; // NOLINT + +// A handy wrapper around AddReference that works when the argument T +// depends on template parameters. +#define GTEST_ADD_REFERENCE_(T) \ + typename ::testing::internal::AddReference::type + +// Adds a reference to const on top of T as necessary. For example, +// it transforms +// +// char ==> const char& +// const char ==> const char& +// char& ==> const char& +// const char& ==> const char& +// +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) + +// ImplicitlyConvertible::value is a compile-time bool +// constant that's true iff type From can be implicitly converted to +// type To. +template +class ImplicitlyConvertible { + private: + // We need the following helper functions only for their types. + // They have no implementations. + + // MakeFrom() is an expression whose type is From. We cannot simply + // use From(), as the type From may not have a public default + // constructor. + static From MakeFrom(); + + // These two functions are overloaded. Given an expression + // Helper(x), the compiler will pick the first version if x can be + // implicitly converted to type To; otherwise it will pick the + // second version. + // + // The first version returns a value of size 1, and the second + // version returns a value of size 2. Therefore, by checking the + // size of Helper(x), which can be done at compile time, we can tell + // which version of Helper() is used, and hence whether x can be + // implicitly converted to type To. + static char Helper(To); + static char (&Helper(...))[2]; // NOLINT + + // We have to put the 'public' section after the 'private' section, + // or MSVC refuses to compile the code. + public: + // 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 + // instantiation. The simplest workaround is to use its C++0x type traits + // functions (C++Builder 2009 and above only). + static const bool value = __is_convertible(From, To); +#else + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +#endif // _MSV_VER +}; +template +const bool ImplicitlyConvertible::value; + +// IsAProtocolMessage::value is a compile-time bool constant that's +// true iff T is type ProtocolMessage, proto2::Message, or a subclass +// of those. +template +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible::value || + ImplicitlyConvertible::value> { +}; + +// When the compiler sees expression IsContainerTest(0), if C is an +// STL-style container class, the first overload of IsContainerTest +// will be viable (since both C::iterator* and C::const_iterator* are +// valid types and NULL can be implicitly converted to them). It will +// be picked over the second overload as 'int' is a perfect match for +// the type of argument 0. If C::iterator or C::const_iterator is not +// a valid type, the first overload is not viable, and the second +// overload will be picked. Therefore, we can determine whether C is +// a container class by checking the type of IsContainerTest(0). +// The value of the expression is insignificant. +// +// Note that we look for both C::iterator and C::const_iterator. The +// reason is that C++ injects the name of a class as a member of the +// class itself (e.g. you can refer to class iterator as either +// 'iterator' or 'iterator::iterator'). If we look for C::iterator +// only, for example, we would mistakenly think that a class named +// iterator is an STL container. +// +// Also note that the simpler approach of overloading +// IsContainerTest(typename C::const_iterator*) and +// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. +typedef int IsContainer; +template +IsContainer IsContainerTest(int /* dummy */, + typename C::iterator* /* it */ = NULL, + typename C::const_iterator* /* const_it */ = NULL) { + return 0; +} + +typedef char IsNotContainer; +template +IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } + +// EnableIf::type is void when 'Cond' is true, and +// undefined when 'Cond' is false. To use SFINAE to make a function +// overload only apply when a particular expression is true, add +// "typename EnableIf::type* = 0" as the last parameter. +template struct EnableIf; +template<> struct EnableIf { typedef void type; }; // NOLINT + +// Utilities for native arrays. + +// ArrayEq() compares two k-dimensional native arrays using the +// elements' operator==, where k can be any integer >= 0. When k is +// 0, ArrayEq() degenerates into comparing a single pair of values. + +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs); + +// This generic version is used when k is 0. +template +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } + +// This overload is used when k >= 1. +template +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { + return internal::ArrayEq(lhs, N, rhs); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous ArrayEq() function, arrays with different sizes would +// lead to different copies of the template code. +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs) { + for (size_t i = 0; i != size; i++) { + if (!internal::ArrayEq(lhs[i], rhs[i])) + return false; + } + return true; +} + +// Finds the first element in the iterator range [begin, end) that +// equals elem. Element may be a native array type itself. +template +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { + for (Iter it = begin; it != end; ++it) { + if (internal::ArrayEq(*it, elem)) + return it; + } + return end; +} + +// CopyArray() copies a k-dimensional native array using the elements' +// operator=, where k can be any integer >= 0. When k is 0, +// CopyArray() degenerates into copying a single value. + +template +void CopyArray(const T* from, size_t size, U* to); + +// This generic version is used when k is 0. +template +inline void CopyArray(const T& from, U* to) { *to = from; } + +// This overload is used when k >= 1. +template +inline void CopyArray(const T(&from)[N], U(*to)[N]) { + internal::CopyArray(from, N, *to); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous CopyArray() function, arrays with different sizes +// would lead to different copies of the template code. +template +void CopyArray(const T* from, size_t size, U* to) { + for (size_t i = 0; i != size; i++) { + internal::CopyArray(from[i], to + i); + } +} + +// The relation between an NativeArray object (see below) and the +// native array it represents. +enum RelationToSource { + kReference, // The NativeArray references the native array. + kCopy // The NativeArray makes a copy of the native array and + // owns the copy. +}; + +// Adapts a native array to a read-only STL-style container. Instead +// of the complete STL container concept, this adaptor only implements +// members useful for Google Mock's container matchers. New members +// should be added as needed. To simplify the implementation, we only +// support Element being a raw type (i.e. having no top-level const or +// reference modifier). It's the client's responsibility to satisfy +// this requirement. Element can be an array type itself (hence +// multi-dimensional arrays are supported). +template +class NativeArray { + public: + // STL-style container typedefs. + typedef Element value_type; + typedef Element* iterator; + typedef const Element* const_iterator; + + // Constructs from a native array. + NativeArray(const Element* array, size_t count, RelationToSource relation) { + Init(array, count, relation); + } + + // Copy constructor. + NativeArray(const NativeArray& rhs) { + Init(rhs.array_, rhs.size_, rhs.relation_to_source_); + } + + ~NativeArray() { + // Ensures that the user doesn't instantiate NativeArray with a + // const or reference type. + static_cast(StaticAssertTypeEqHelper()); + if (relation_to_source_ == kCopy) + delete[] array_; + } + + // STL-style container methods. + size_t size() const { return size_; } + const_iterator begin() const { return array_; } + const_iterator end() const { return array_ + size_; } + bool operator==(const NativeArray& rhs) const { + return size() == rhs.size() && + ArrayEq(begin(), size(), rhs.begin()); + } + + private: + // Initializes this object; makes a copy of the input array if + // 'relation' is kCopy. + void Init(const Element* array, size_t a_size, RelationToSource relation) { + if (relation == kReference) { + array_ = array; + } else { + Element* const copy = new Element[a_size]; + CopyArray(array, a_size, copy); + array_ = copy; + } + size_ = a_size; + relation_to_source_ = relation; + } + + const Element* array_; + size_t size_; + RelationToSource relation_to_source_; + + GTEST_DISALLOW_ASSIGN_(NativeArray); +}; + +} // namespace internal +} // namespace testing + +#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ + ::testing::internal::AssertHelper(result_type, file, line, message) \ + = ::testing::Message() + +#define GTEST_MESSAGE_(message, result_type) \ + GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) + +#define GTEST_FATAL_FAILURE_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) + +#define GTEST_NONFATAL_FAILURE_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) + +#define GTEST_SUCCESS_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::ConstCharPtr gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ + fail(gtest_msg.value) + +#define GTEST_TEST_NO_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ + fail("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws.") + +#define GTEST_TEST_ANY_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + bool gtest_caught_any = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ + fail("Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't.") + + +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ + ; \ + else \ + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) + +#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ + fail("Expected: " #statement " doesn't generate new fatal " \ + "failures in the current thread.\n" \ + " Actual: it does.") + +// Expands to the name of the class that implements the given test. +#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + test_case_name##_##test_name##_Test + +// Helper macro for defining tests. +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ +class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ + public:\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ + private:\ + virtual void TestBody();\ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ +};\ +\ +::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ + ::test_info_ =\ + ::testing::internal::MakeAndRegisterTestInfo(\ + #test_case_name, #test_name, NULL, NULL, \ + (parent_id), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ +void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for death tests. It is +// #included by gtest.h so a user doesn't need to include this +// directly. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ + +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines internal utilities needed for implementing +// death tests. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + + +#include + +namespace testing { +namespace internal { + +GTEST_DECLARE_string_(internal_run_death_test); + +// Names of the flags (needed for parsing Google Test flags). +const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; +const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; + +#if GTEST_HAS_DEATH_TEST + +// DeathTest is a class that hides much of the complexity of the +// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method +// returns a concrete class that depends on the prevailing death test +// style, as defined by the --gtest_death_test_style and/or +// --gtest_internal_run_death_test flags. + +// In describing the results of death tests, these terms are used with +// the corresponding definitions: +// +// exit status: The integer exit information in the format specified +// by wait(2) +// exit code: The integer code passed to exit(3), _exit(2), or +// returned from main() +class GTEST_API_ DeathTest { + public: + // Create returns false if there was an error determining the + // appropriate action to take for the current death test; for example, + // if the gtest_death_test_style flag is set to an invalid value. + // The LastMessage method will return a more detailed message in that + // case. Otherwise, the DeathTest pointer pointed to by the "test" + // argument is set. If the death test should be skipped, the pointer + // is set to NULL; otherwise, it is set to the address of a new concrete + // DeathTest object that controls the execution of the current test. + static bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); + DeathTest(); + virtual ~DeathTest() { } + + // A helper class that aborts a death test when it's deleted. + class ReturnSentinel { + public: + explicit ReturnSentinel(DeathTest* test) : test_(test) { } + ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } + private: + DeathTest* const test_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); + } GTEST_ATTRIBUTE_UNUSED_; + + // An enumeration of possible roles that may be taken when a death + // test is encountered. EXECUTE means that the death test logic should + // be executed immediately. OVERSEE means that the program should prepare + // the appropriate environment for a child process to execute the death + // test, then wait for it to complete. + enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; + + // An enumeration of the three reasons that a test might be aborted. + enum AbortReason { + TEST_ENCOUNTERED_RETURN_STATEMENT, + TEST_THREW_EXCEPTION, + TEST_DID_NOT_DIE + }; + + // Assumes one of the above roles. + virtual TestRole AssumeRole() = 0; + + // Waits for the death test to finish and returns its status. + virtual int Wait() = 0; + + // Returns true if the death test passed; that is, the test process + // exited during the test, its exit status matches a user-supplied + // predicate, and its stderr output matches a user-supplied regular + // expression. + // The user-supplied predicate may be a macro expression rather + // than a function pointer or functor, or else Wait and Passed could + // be combined. + virtual bool Passed(bool exit_status_ok) = 0; + + // Signals that the death test did not die as expected. + virtual void Abort(AbortReason reason) = 0; + + // Returns a human-readable outcome message regarding the outcome of + // the last death test. + static const char* LastMessage(); + + static void set_last_death_test_message(const std::string& message); + + private: + // A string containing a description of the outcome of the last death test. + static std::string last_death_test_message_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); +}; + +// Factory interface for death tests. May be mocked out for testing. +class DeathTestFactory { + public: + virtual ~DeathTestFactory() { } + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) = 0; +}; + +// A concrete DeathTestFactory implementation for normal use. +class DefaultDeathTestFactory : public DeathTestFactory { + public: + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); +}; + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); + +// Traps C++ exceptions escaping statement and reports them as test +// failures. Note that trapping SEH exceptions is not implemented here. +# if GTEST_HAS_EXCEPTIONS +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (const ::std::exception& gtest_exception) { \ + fprintf(\ + stderr, \ + "\n%s: Caught std::exception-derived exception escaping the " \ + "death test statement. Exception message: %s\n", \ + ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ + gtest_exception.what()); \ + fflush(stderr); \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } catch (...) { \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } + +# else +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) + +# endif + +// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, +// ASSERT_EXIT*, and EXPECT_EXIT*. +# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const ::testing::internal::RE& gtest_regex = (regex); \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != NULL) { \ + ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ + gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel \ + gtest_sentinel(gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ + fail(::testing::internal::DeathTest::LastMessage()) +// The symbol "fail" here expands to something into which a message +// can be streamed. + +// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in +// NDEBUG mode. In this case we need the statements to be executed, the regex is +// ignored, and the macro must accept a streamed message even though the message +// is never printed. +# define GTEST_EXECUTE_STATEMENT_(statement, regex) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } else \ + ::testing::Message() + +// A class representing the parsed contents of the +// --gtest_internal_run_death_test flag, as it existed when +// RUN_ALL_TESTS was called. +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const std::string& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + const std::string& file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + std::string file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); +}; + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); + +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + +namespace testing { + +// This flag controls the style of death tests. Valid values are "threadsafe", +// meaning that the death test child process will re-execute the test binary +// from the start, running only a single death test, or "fast", +// meaning that the child process will execute the test logic immediately +// after forking. +GTEST_DECLARE_string_(death_test_style); + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +GTEST_API_ bool InDeathTestChild(); + +} // namespace internal + +// The following macros are useful for writing death tests. + +// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is +// executed: +// +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. +// +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. +// +// 3. The parent process waits for the sub-process to terminate. +// +// 4. The parent process checks the exit code and error message of +// the sub-process. +// +// Examples: +// +// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); +// for (int i = 0; i < 5; i++) { +// EXPECT_DEATH(server.ProcessRequest(i), +// "Invalid request .* in ProcessRequest()") +// << "Failed to die on request " << i; +// } +// +// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); +// +// bool KilledBySIGHUP(int exit_code) { +// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; +// } +// +// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. + +// Asserts that a given statement causes the program to exit, with an +// integer exit status that satisfies predicate, and emitting error output +// that matches regex. +# define ASSERT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) + +// Like ASSERT_EXIT, but continues on to successive tests in the +// test case, if any: +# define EXPECT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) + +// Asserts that a given statement causes the program to exit, either by +// explicitly exiting with a nonzero exit code or being killed by a +// signal, and emitting error output that matches regex. +# define ASSERT_DEATH(statement, regex) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Like ASSERT_DEATH, but continues on to successive tests in the +// test case, if any: +# define EXPECT_DEATH(statement, regex) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: + +// Tests that an exit code describes a normal exit with a given exit code. +class GTEST_API_ ExitedWithCode { + public: + explicit ExitedWithCode(int exit_code); + bool operator()(int exit_status) const; + private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + + const int exit_code_; +}; + +# if !GTEST_OS_WINDOWS +// Tests that an exit code describes an exit due to termination by a +// given signal. +class GTEST_API_ KilledBySignal { + public: + explicit KilledBySignal(int signum); + bool operator()(int exit_status) const; + private: + const int signum_; +}; +# endif // !GTEST_OS_WINDOWS + +// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. +// The death testing framework causes this to have interesting semantics, +// since the sideeffects of the call are only visible in opt mode, and not +// in debug mode. +// +// In practice, this can be used to test functions that utilize the +// LOG(DFATAL) macro using the following style: +// +// int DieInDebugOr12(int* sideeffect) { +// if (sideeffect) { +// *sideeffect = 12; +// } +// LOG(DFATAL) << "death"; +// return 12; +// } +// +// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// int sideeffect = 0; +// // Only asserts in dbg. +// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); +// +// #ifdef NDEBUG +// // opt-mode has sideeffect visible. +// EXPECT_EQ(12, sideeffect); +// #else +// // dbg-mode no visible sideeffect. +// EXPECT_EQ(0, sideeffect); +// #endif +// } +// +// This will assert that DieInDebugReturn12InOpt() crashes in debug +// mode, usually due to a DCHECK or LOG(DFATAL), but returns the +// appropriate fallback value (12 in this case) in opt mode. If you +// need to test that a function has appropriate side-effects in opt +// mode, include assertions against the side-effects. A general +// pattern for this is: +// +// EXPECT_DEBUG_DEATH({ +// // Side-effects here will have an effect after this statement in +// // opt mode, but none in debug mode. +// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); +// }, "death"); +// +# ifdef NDEBUG + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# else + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + EXPECT_DEATH(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + ASSERT_DEATH(statement, regex) + +# endif // NDEBUG for EXPECT_DEBUG_DEATH +#endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +// This file was GENERATED by command: +// pump.py gtest-param-test.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. +// +// Authors: vladl@google.com (Vlad Losev) +// +// Macros and functions for implementing parameterized tests +// in Google C++ Testing Framework (Google Test) +// +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ + + +// Value-parameterized tests allow you to test your code with different +// parameters without writing multiple copies of the same test. +// +// Here is how you use value-parameterized tests: + +#if 0 + +// To write value-parameterized tests, first you should define a fixture +// class. It is usually derived from testing::TestWithParam (see below for +// another inheritance scheme that's sometimes useful in more complicated +// class hierarchies), where the type of your parameter values. +// TestWithParam is itself derived from testing::Test. T can be any +// copyable type. If it's a raw pointer, you are responsible for managing the +// lifespan of the pointed values. + +class FooTest : public ::testing::TestWithParam { + // You can implement all the usual class fixture members here. +}; + +// Then, use the TEST_P macro to define as many parameterized tests +// for this fixture as you want. The _P suffix is for "parameterized" +// or "pattern", whichever you prefer to think. + +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} + +// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// case with any set of parameters you want. Google Test defines a number +// of functions for generating test parameters. They return what we call +// (surprise!) parameter generators. Here is a summary of them, which +// are all in the testing namespace: +// +// +// Range(begin, end [, step]) - Yields values {begin, begin+step, +// begin+step+step, ...}. The values do not +// include end. step defaults to 1. +// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. +// ValuesIn(container) - Yields values from a C-style array, an STL +// ValuesIn(begin,end) container, or an iterator range [begin, end). +// Bool() - Yields sequence {false, true}. +// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product +// for the math savvy) of the values generated +// by the N generators. +// +// For more details, see comments at the definitions of these functions below +// in this file. +// +// The following statement will instantiate tests from the FooTest test case +// each with parameter values "meeny", "miny", and "moe". + +INSTANTIATE_TEST_CASE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); + +// To distinguish different instances of the pattern, (yes, you +// can instantiate it more then once) the first argument to the +// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the +// actual test case name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: +// +// * InstantiationName/FooTest.DoesBlah/0 for "meeny" +// * InstantiationName/FooTest.DoesBlah/1 for "miny" +// * InstantiationName/FooTest.DoesBlah/2 for "moe" +// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" +// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" +// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" +// +// You can use these names in --gtest_filter. +// +// This statement will instantiate all tests from FooTest again, each +// with parameter values "cat" and "dog": + +const char* pets[] = {"cat", "dog"}; +INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); + +// The tests from the instantiation above will have these names: +// +// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" +// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" +// +// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests +// in the given test case, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_CASE_P statement. +// +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. +// +// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc +// for more examples. +// +// In the future, we plan to publish the API for defining new parameter +// generators. But for now this interface remains part of the internal +// implementation and is subject to change. +// +// +// A parameterized test fixture must be derived from testing::Test and from +// testing::WithParamInterface, where T is the type of the parameter +// values. Inheriting from TestWithParam satisfies that requirement because +// TestWithParam inherits from both Test and WithParamInterface. In more +// complicated hierarchies, however, it is occasionally useful to inherit +// separately from Test and WithParamInterface. For example: + +class BaseTest : public ::testing::Test { + // You can inherit all the usual members for a non-parameterized test + // fixture here. +}; + +class DerivedTest : public BaseTest, public ::testing::WithParamInterface { + // The usual test fixture members go here too. +}; + +TEST_F(BaseTest, HasFoo) { + // This is an ordinary non-parameterized test. +} + +TEST_P(DerivedTest, DoesBlah) { + // GetParam works just the same here as if you inherit from TestWithParam. + EXPECT_TRUE(foo.Blah(GetParam())); +} + +#endif // 0 + + +#if !GTEST_OS_SYMBIAN +# include +#endif + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// 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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ + +#include +#include +#include + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2003 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. +// +// Authors: Dan Egnor (egnor@google.com) +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// TODO(wan@google.com): rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include +#include + + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr, linked_ptr, and + // linked_ptr). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +// 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 Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// A user can teach this function how to print a class type T by +// defining either operator<<() or PrintTo() in the namespace that +// defines T. More specifically, the FIRST defined function in the +// following list will be used (assuming T is defined in namespace +// foo): +// +// 1. foo::PrintTo(const T&, ostream*) +// 2. operator<<(ostream&, const T&) defined in either foo or the +// global namespace. +// +// If none of the above is defined, it will print the debug string of +// the value if it is a protocol buffer, or print the raw bytes in the +// value otherwise. +// +// To aid debugging: when T is a reference type, the address of the +// value is also printed; when T is a (const) char pointer, both the +// pointer value and the NUL-terminated string it points to are +// printed. +// +// We also provide some convenient wrappers: +// +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); +// +// // Prints a value tersely: for a reference type, the referenced +// // value (but not the address) is printed; for a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); +// +// // Prints value using the type inferred by the compiler. The difference +// // from UniversalTersePrint() is that this function prints both the +// // pointer and the NUL-terminated string for a (const or not) char pointer. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); +// +// // Prints the fields of a tuple tersely to a string vector, one +// // element for each field. Tuple support must be enabled in +// // gtest-port.h. +// std::vector UniversalTersePrintTupleFieldsToStrings( +// const Tuple& value); +// +// Known limitation: +// +// The print primitives print the elements of an STL-style container +// using the compiler-inferred type of *iter where iter is a +// const_iterator of the container. When const_iterator is an input +// iterator but not a forward iterator, this inferred type may not +// match value_type, and the print output may be incorrect. In +// practice, this is rarely a problem as for most containers +// const_iterator is a forward iterator. We'll fix this if there's an +// actual need for it. Note that this fix cannot rely on value_type +// being defined as many user-defined container types don't have +// value_type. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +// Definitions in the 'internal' and 'internal2' name spaces are +// subject to change without notice. DO NOT USE THEM IN USER CODE! +namespace internal2 { + +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); + +// For selecting which printer to use when a given type has neither << +// nor PrintTo(). +enum TypeKind { + kProtobuf, // a protobuf type + kConvertibleToInteger, // a type implicitly convertible to BiggestInt + // (e.g. a named or unnamed enum type) + kOtherType // anything else +}; + +// TypeWithoutFormatter::PrintValue(value, os) is called +// by the universal printer to print a value of type T when neither +// operator<< nor PrintTo() is defined for T, where kTypeKind is the +// "kind" of T as defined by enum TypeKind. +template +class TypeWithoutFormatter { + public: + // This default version is called when kTypeKind is kOtherType. + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo(reinterpret_cast(&value), + sizeof(value), os); + } +}; + +// We print a protobuf using its ShortDebugString() when the string +// doesn't exceed this many characters; otherwise we print it using +// DebugString() for better readability. +const size_t kProtobufOneLinerMaxLength = 50; + +template +class TypeWithoutFormatter { + public: + static void PrintValue(const T& value, ::std::ostream* os) { + const ::testing::internal::string short_str = value.ShortDebugString(); + const ::testing::internal::string pretty_str = + short_str.length() <= kProtobufOneLinerMaxLength ? + short_str : ("\n" + value.DebugString()); + *os << ("<" + pretty_str + ">"); + } +}; + +template +class TypeWithoutFormatter { + public: + // Since T has no << operator or PrintTo() but can be implicitly + // converted to BiggestInt, we print it as a BiggestInt. + // + // Most likely T is an enum type (either named or unnamed), in which + // case printing it as an integer is the desired behavior. In case + // T is not an enum, printing it as an integer is the best we can do + // given that it has no user-defined printer. + static void PrintValue(const T& value, ::std::ostream* os) { + const internal::BiggestInt kBigInt = value; + *os << kBigInt; + } +}; + +// Prints the given value to the given ostream. If the value is a +// protocol message, its debug string is printed; if it's an enum or +// of a type implicitly convertible to BiggestInt, it's printed as an +// integer; otherwise the bytes in the value are printed. This is +// what UniversalPrinter::Print() does when it knows nothing about +// type T and T has neither << operator nor PrintTo(). +// +// A user can override this behavior for a class type Foo by defining +// a << operator in the namespace where Foo is defined. +// +// We put this operator in namespace 'internal2' instead of 'internal' +// to simplify the implementation, as much code in 'internal' needs to +// use << in STL, which would conflict with our own << were it defined +// in 'internal'. +// +// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If +// we define it to take an std::ostream instead, we'll get an +// "ambiguous overloads" compiler error when trying to print a type +// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether +// operator<<(std::ostream&, const T&) or +// operator<<(std::basic_stream, const Foo&) is more +// specific. +template +::std::basic_ostream& operator<<( + ::std::basic_ostream& os, const T& x) { + TypeWithoutFormatter::value ? kProtobuf : + internal::ImplicitlyConvertible::value ? + kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + return os; +} + +} // namespace internal2 +} // namespace testing + +// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up +// magic needed for implementing UniversalPrinter won't work. +namespace testing_internal { + +// Used to print a value that is not an STL-style container when the +// user doesn't define PrintTo() for it. +template +void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { + // With the following statement, during unqualified name lookup, + // testing::internal2::operator<< appears as if it was declared in + // the nearest enclosing namespace that contains both + // ::testing_internal and ::testing::internal2, i.e. the global + // namespace. For more details, refer to the C++ Standard section + // 7.3.4-1 [namespace.udir]. This allows us to fall back onto + // testing::internal2::operator<< in case T doesn't come with a << + // operator. + // + // We cannot write 'using ::testing::internal2::operator<<;', which + // gcc 3.3 fails to compile due to a compiler bug. + using namespace ::testing::internal2; // NOLINT + + // Assuming T is defined in namespace foo, in the next statement, + // the compiler will consider all of: + // + // 1. foo::operator<< (thanks to Koenig look-up), + // 2. ::operator<< (as the current namespace is enclosed in ::), + // 3. testing::internal2::operator<< (thanks to the using statement above). + // + // The operator<< whose type matches T best will be picked. + // + // We deliberately allow #2 to be a candidate, as sometimes it's + // impossible to define #1 (e.g. when foo is ::std, defining + // anything in it is undefined behavior unless you are a compiler + // vendor.). + *os << value; +} + +} // namespace testing_internal + +namespace testing { +namespace internal { + +// UniversalPrinter::Print(value, ostream_ptr) prints the given +// value to the given ostream. The caller must ensure that +// 'ostream_ptr' is not NULL, or the behavior is undefined. +// +// We define UniversalPrinter as a class template (as opposed to a +// function template), as we need to partially specialize it for +// reference types, which cannot be done with function templates. +template +class UniversalPrinter; + +template +void UniversalPrint(const T& value, ::std::ostream* os); + +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +template +void DefaultPrintTo(IsContainer /* dummy */, + false_type /* is not a pointer */, + const C& container, ::std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (typename C::const_iterator it = container.begin(); + it != container.end(); ++it, ++count) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(*it, os) here as PrintTo() doesn't + // handle *it being a native array. + internal::UniversalPrint(*it, os); + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; +} + +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +template +void DefaultPrintTo(IsNotContainer /* dummy */, + true_type /* is a pointer */, + T* p, ::std::ostream* os) { + if (p == NULL) { + *os << "NULL"; + } else { + // C++ doesn't allow casting from a function pointer to any object + // pointer. + // + // IsTrue() silences warnings: "Condition is always true", + // "unreachable code". + if (IsTrue(ImplicitlyConvertible::value)) { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. However, we cannot cast it to const void* directly, + // even using reinterpret_cast, as earlier versions of gcc + // (e.g. 3.4.5) cannot compile the cast when p is a function + // pointer. Casting to UInt64 first solves the problem. + *os << reinterpret_cast( + reinterpret_cast(p)); + } + } +} + +// Used to print a non-container, non-pointer value when the user +// doesn't define PrintTo() for it. +template +void DefaultPrintTo(IsNotContainer /* dummy */, + false_type /* is not a pointer */, + const T& value, ::std::ostream* os) { + ::testing_internal::DefaultPrintNonContainerTo(value, os); +} + +// Prints the given value using the << operator if it has one; +// otherwise prints the bytes in it. This is what +// UniversalPrinter::Print() does when PrintTo() is not specialized +// or overloaded for type T. +// +// A user can override this behavior for a class type Foo by defining +// an overload of PrintTo() in the namespace where Foo is defined. We +// give the user this option as sometimes defining a << operator for +// Foo is not desirable (e.g. the coding style may prevent doing it, +// or there is already a << operator but it doesn't do what the user +// wants). +template +void PrintTo(const T& value, ::std::ostream* os) { + // DefaultPrintTo() is overloaded. The type of its first two + // arguments determine which version will be picked. If T is an + // STL-style container, the version for container will be called; if + // T is a pointer, the pointer version will be called; otherwise the + // generic version will be called. + // + // Note that we check for container types here, prior to we check + // for protocol message types in our operator<<. The rationale is: + // + // For protocol messages, we want to give people a chance to + // override Google Mock's format by defining a PrintTo() or + // operator<<. For STL containers, other formats can be + // incompatible with Google Mock's format for the container + // elements; therefore we check for container types here to ensure + // that our format is used. + // + // The second argument of DefaultPrintTo() is needed to bypass a bug + // in Symbian's C++ compiler that prevents it from picking the right + // overload between: + // + // PrintTo(const T& x, ...); + // PrintTo(T* x, ...); + DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); +} + +// The following list of PrintTo() overloads tells +// UniversalPrinter::Print() how to print standard types (built-in +// types, strings, plain arrays, and pointers). + +// Overloads for various char types. +GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); +GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); +inline void PrintTo(char c, ::std::ostream* os) { + // When printing a plain char, we always treat it as unsigned. This + // way, the output won't be affected by whether the compiler thinks + // char is signed or not. + PrintTo(static_cast(c), os); +} + +// Overloads for other simple built-in types. +inline void PrintTo(bool x, ::std::ostream* os) { + *os << (x ? "true" : "false"); +} + +// Overload for wchar_t type. +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); + +// Overloads for C strings. +GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); +inline void PrintTo(char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// signed/unsigned char is often used for representing binary data, so +// we print pointers to it as void* to be safe. +inline void PrintTo(const signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(const unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Overloads for wide C strings +GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); +inline void PrintTo(wchar_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif + +// Overload for C arrays. Multi-dimensional arrays are printed +// properly. + +// Prints the given number of elements in an array, without printing +// the curly braces. +template +void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { + UniversalPrint(a[0], os); + for (size_t i = 1; i != count; i++) { + *os << ", "; + UniversalPrint(a[i], os); + } +} + +// Overloads for ::string and ::std::string. +#if GTEST_HAS_GLOBAL_STRING +GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); +inline void PrintTo(const ::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +inline void PrintTo(const ::std::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} + +// Overloads for ::wstring and ::std::wstring. +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_STD_WSTRING + +#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 +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os); + +// Overloaded PrintTo() for tuples of various arities. We support +// tuples of up-to 10 fields. The following implementation works +// regardless of whether tr1::tuple is implemented using the +// non-standard variadic template feature or not. + +inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo( + const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} +#endif // GTEST_HAS_TR1_TUPLE + +// Overload for std::pair. +template +void PrintTo(const ::std::pair& value, ::std::ostream* os) { + *os << '('; + // We cannot use UniversalPrint(value.first, os) here, as T1 may be + // a reference type. The same for printing value.second. + UniversalPrinter::Print(value.first, os); + *os << ", "; + UniversalPrinter::Print(value.second, os); + *os << ')'; +} + +// Implements printing a non-reference type T by letting the compiler +// pick the right overload of PrintTo() for T. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#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 + // conflicts with ::testing::internal::PrintTo in the body of the + // function. + static void Print(const T& value, ::std::ostream* os) { + // By default, ::testing::internal::PrintTo() is used for printing + // the value. + // + // Thanks to Koenig look-up, if T is a class and has its own + // PrintTo() function defined in its namespace, that function will + // be visible here. Since it is more specific than the generic ones + // in ::testing::internal, it will be picked by the compiler in the + // following statement - exactly what we want. + PrintTo(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// UniversalPrintArray(begin, len, os) prints an array of 'len' +// elements, starting at address 'begin'. +template +void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { + if (len == 0) { + *os << "{}"; + } else { + *os << "{ "; + const size_t kThreshold = 18; + const size_t kChunkSize = 8; + // If the array has more than kThreshold elements, we'll have to + // omit some details by printing only the first and the last + // kChunkSize elements. + // TODO(wan@google.com): let the user control the threshold using a flag. + if (len <= kThreshold) { + PrintRawArrayTo(begin, len, os); + } else { + PrintRawArrayTo(begin, kChunkSize, os); + *os << ", ..., "; + PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); + } + *os << " }"; + } +} +// This overload prints a (const) char array compactly. +GTEST_API_ void UniversalPrintArray( + const char* begin, size_t len, ::std::ostream* os); + +// This overload prints a (const) wchar_t array compactly. +GTEST_API_ void UniversalPrintArray( + const wchar_t* begin, size_t len, ::std::ostream* os); + +// Implements printing an array type T[N]. +template +class UniversalPrinter { + public: + // Prints the given array, omitting some elements when there are too + // many. + static void Print(const T (&a)[N], ::std::ostream* os) { + UniversalPrintArray(a, N, os); + } +}; + +// Implements printing a reference type T&. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#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) { + // Prints the address of the value. We use reinterpret_cast here + // as static_cast doesn't compile when T is a function type. + *os << "@" << reinterpret_cast(&value) << " "; + + // Then prints the value itself. + UniversalPrint(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// Prints a value tersely: for a reference type, the referenced value +// (but not the address) is printed; for a (const) char pointer, the +// NUL-terminated string (but not the pointer) is printed. + +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T (&value)[N], ::std::ostream* os) { + UniversalPrinter::Print(value, os); + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(const char* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(string(str), os); + } + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(char* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +#if GTEST_HAS_STD_WSTRING +template <> +class UniversalTersePrinter { + public: + static void Print(const wchar_t* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(::std::wstring(str), os); + } + } +}; +#endif + +template <> +class UniversalTersePrinter { + public: + static void Print(wchar_t* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +template +void UniversalTersePrint(const T& value, ::std::ostream* os) { + UniversalTersePrinter::Print(value, os); +} + +// Prints a value using the type inferred by the compiler. The +// difference between this and UniversalTersePrint() is that for a +// (const) char pointer, this prints both the pointer and the +// NUL-terminated string. +template +void UniversalPrint(const T& value, ::std::ostream* os) { + // A workarond for the bug in VC++ 7.1 that prevents us from instantiating + // UniversalPrinter with T directly. + typedef T T1; + UniversalPrinter::Print(value, os); +} + +#if GTEST_HAS_TR1_TUPLE +typedef ::std::vector Strings; + +// This helper template allows PrintTo() for tuples and +// UniversalTersePrintTupleFieldsToStrings() to be defined by +// induction on the number of tuple fields. The idea is that +// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N +// fields in tuple t, and can be defined in terms of +// TuplePrefixPrinter. + +// The inductive case. +template +struct TuplePrefixPrinter { + // Prints the first N fields of a tuple. + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + TuplePrefixPrinter::PrintPrefixTo(t, os); + *os << ", "; + UniversalPrinter::type> + ::Print(::std::tr1::get(t), os); + } + + // Tersely prints the first N fields of a tuple to a string vector, + // one element for each field. + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Base cases. +template <> +struct TuplePrefixPrinter<0> { + template + static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} + + template + 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 + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + UniversalPrinter::type>:: + Print(::std::tr1::get<0>(t), os); + } + + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + ::std::stringstream ss; + 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 +void PrintTupleTo(const T& t, ::std::ostream* os) { + *os << "("; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + PrintPrefixTo(t, os); + *os << ")"; +} + +// Prints the fields of a tuple tersely to a string vector, one +// element for each field. See the comment before +// UniversalTersePrint() for how we define "tersely". +template +Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { + Strings result; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + TersePrintPrefixToStrings(value, &result); + return result; +} +#endif // GTEST_HAS_TR1_TUPLE + +} // namespace internal + +template +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrinter::Print(value, &ss); + return ss.str(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { +namespace internal { + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Outputs a message explaining invalid registration of different +// fixture class for the same test case. This may happen when +// TEST_P macro is used to define two tests with the same name +// but in different namespaces. +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); + +template class ParamGeneratorInterface; +template class ParamGenerator; + +// Interface for iterating over elements provided by an implementation +// of ParamGeneratorInterface. +template +class ParamIteratorInterface { + public: + virtual ~ParamIteratorInterface() {} + // A pointer to the base generator instance. + // Used only for the purposes of iterator comparison + // to make sure that two iterators belong to the same generator. + virtual const ParamGeneratorInterface* BaseGenerator() const = 0; + // Advances iterator to point to the next element + // provided by the generator. The caller is responsible + // for not calling Advance() on an iterator equal to + // BaseGenerator()->End(). + virtual void Advance() = 0; + // Clones the iterator object. Used for implementing copy semantics + // of ParamIterator. + virtual ParamIteratorInterface* Clone() const = 0; + // Dereferences the current iterator and provides (read-only) access + // to the pointed value. It is the caller's responsibility not to call + // Current() on an iterator equal to BaseGenerator()->End(). + // Used for implementing ParamGenerator::operator*(). + virtual const T* Current() const = 0; + // Determines whether the given iterator and other point to the same + // element in the sequence generated by the generator. + // Used for implementing ParamGenerator::operator==(). + virtual bool Equals(const ParamIteratorInterface& other) const = 0; +}; + +// Class iterating over elements provided by an implementation of +// ParamGeneratorInterface. It wraps ParamIteratorInterface +// and implements the const forward iterator concept. +template +class ParamIterator { + public: + typedef T value_type; + typedef const T& reference; + typedef ptrdiff_t difference_type; + + // ParamIterator assumes ownership of the impl_ pointer. + ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} + ParamIterator& operator=(const ParamIterator& other) { + if (this != &other) + impl_.reset(other.impl_->Clone()); + return *this; + } + + const T& operator*() const { return *impl_->Current(); } + const T* operator->() const { return impl_->Current(); } + // Prefix version of operator++. + ParamIterator& operator++() { + impl_->Advance(); + return *this; + } + // Postfix version of operator++. + ParamIterator operator++(int /*unused*/) { + ParamIteratorInterface* clone = impl_->Clone(); + impl_->Advance(); + return ParamIterator(clone); + } + bool operator==(const ParamIterator& other) const { + return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); + } + bool operator!=(const ParamIterator& other) const { + return !(*this == other); + } + + private: + friend class ParamGenerator; + explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} + scoped_ptr > impl_; +}; + +// ParamGeneratorInterface is the binary interface to access generators +// defined in other translation units. +template +class ParamGeneratorInterface { + public: + typedef T ParamType; + + virtual ~ParamGeneratorInterface() {} + + // Generator interface definition + virtual ParamIteratorInterface* Begin() const = 0; + virtual ParamIteratorInterface* End() const = 0; +}; + +// Wraps ParamGeneratorInterface and provides general generator syntax +// compatible with the STL Container concept. +// This class implements copy initialization semantics and the contained +// ParamGeneratorInterface instance is shared among all copies +// of the original object. This is possible because that instance is immutable. +template +class ParamGenerator { + public: + typedef ParamIterator iterator; + + explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} + ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} + + ParamGenerator& operator=(const ParamGenerator& other) { + impl_ = other.impl_; + return *this; + } + + iterator begin() const { return iterator(impl_->Begin()); } + iterator end() const { return iterator(impl_->End()); } + + private: + linked_ptr > impl_; +}; + +// Generates values from a range of two comparable values. Can be used to +// generate sequences of user-defined types that implement operator+() and +// operator<(). +// This class is used in the Range() function. +template +class RangeGenerator : public ParamGeneratorInterface { + public: + RangeGenerator(T begin, T end, IncrementT step) + : begin_(begin), end_(end), + step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} + virtual ~RangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, begin_, 0, step_); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, end_, end_index_, step_); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, T value, int index, + IncrementT step) + : base_(base), value_(value), index_(index), step_(step) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + value_ = value_ + step_; + index_++; + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const T* Current() const { return &value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const int other_index = + CheckedDowncastToActualType(&other)->index_; + return index_ == other_index; + } + + private: + Iterator(const Iterator& other) + : ParamIteratorInterface(), + base_(other.base_), value_(other.value_), index_(other.index_), + step_(other.step_) {} + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + T value_; + int index_; + const IncrementT step_; + }; // class RangeGenerator::Iterator + + static int CalculateEndIndex(const T& begin, + const T& end, + const IncrementT& step) { + int end_index = 0; + for (T i = begin; i < end; i = i + step) + end_index++; + return end_index; + } + + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + + const T begin_; + const T end_; + const IncrementT step_; + // The index for the end() iterator. All the elements in the generated + // sequence are indexed (0-based) to aid iterator comparison. + const int end_index_; +}; // class RangeGenerator + + +// Generates values from a pair of STL-style iterators. Used in the +// ValuesIn() function. The elements are copied from the source range +// since the source can be located on the stack, and the generator +// is likely to persist beyond that stack frame. +template +class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { + public: + template + ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) + : container_(begin, end) {} + virtual ~ValuesInIteratorRangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, container_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, container_.end()); + } + + private: + typedef typename ::std::vector ContainerType; + + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + typename ContainerType::const_iterator iterator) + : base_(base), iterator_(iterator) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + ++iterator_; + value_.reset(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + // We need to use cached value referenced by iterator_ because *iterator_ + // can return a temporary object (and of type other then T), so just + // having "return &*iterator_;" doesn't work. + // value_ is updated here and not in Advance() because Advance() + // can advance iterator_ beyond the end of the range, and we cannot + // detect that fact. The client code, on the other hand, is + // responsible for not calling Current() on an out-of-range iterator. + virtual const T* Current() const { + if (value_.get() == NULL) + value_.reset(new T(*iterator_)); + return value_.get(); + } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + return iterator_ == + CheckedDowncastToActualType(&other)->iterator_; + } + + private: + Iterator(const Iterator& other) + // The explicit constructor call suppresses a false warning + // emitted by gcc when supplied with the -Wextra option. + : ParamIteratorInterface(), + base_(other.base_), + iterator_(other.iterator_) {} + + const ParamGeneratorInterface* const base_; + typename ContainerType::const_iterator iterator_; + // A cached value of *iterator_. We keep it here to allow access by + // pointer in the wrapping iterator's operator->(). + // value_ needs to be mutable to be accessed in Current(). + // Use of scoped_ptr helps manage cached value's lifetime, + // which is bound by the lifespan of the iterator itself. + mutable scoped_ptr value_; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); + + const ContainerType container_; +}; // class ValuesInIteratorRangeGenerator + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Stores a parameter value and later creates tests parameterized with that +// value. +template +class ParameterizedTestFactory : public TestFactoryBase { + public: + typedef typename TestClass::ParamType ParamType; + explicit ParameterizedTestFactory(ParamType parameter) : + parameter_(parameter) {} + virtual Test* CreateTest() { + TestClass::SetParam(¶meter_); + return new TestClass(); + } + + private: + const ParamType parameter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactoryBase is a base class for meta-factories that create +// test factories for passing into MakeAndRegisterTestInfo function. +template +class TestMetaFactoryBase { + public: + virtual ~TestMetaFactoryBase() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactory creates test factories for passing into +// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives +// ownership of test factory pointer, same factory object cannot be passed +// into that method twice. But ParameterizedTestCaseInfo is going to call +// it for each Test/Parameter value combination. Thus it needs meta factory +// creator class. +template +class TestMetaFactory + : public TestMetaFactoryBase { + public: + typedef typename TestCase::ParamType ParamType; + + TestMetaFactory() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { + return new ParameterizedTestFactory(parameter); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfoBase is a generic interface +// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// accumulates test information provided by TEST_P macro invocations +// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and uses that information to register all resulting test instances +// in RegisterTests method. The ParameterizeTestCaseRegistry class holds +// a collection of pointers to the ParameterizedTestCaseInfo objects +// and calls RegisterTests() on each of them when asked. +class ParameterizedTestCaseInfoBase { + public: + virtual ~ParameterizedTestCaseInfoBase() {} + + // Base part of test case name for display purposes. + virtual const string& GetTestCaseName() const = 0; + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const = 0; + // UnitTest class invokes this method to register tests in this + // test case right before running them in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + virtual void RegisterTests() = 0; + + protected: + ParameterizedTestCaseInfoBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test case and generators +// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that +// test case. It registers tests with all values generated by all +// generators when asked. +template +class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { + public: + // ParamType and GeneratorCreationFunc are private types but are required + // for declarations of public methods AddTestPattern() and + // AddTestCaseInstantiation(). + typedef typename TestCase::ParamType ParamType; + // A function that returns an instance of appropriate generator type. + typedef ParamGenerator(GeneratorCreationFunc)(); + + explicit ParameterizedTestCaseInfo(const char* name) + : test_case_name_(name) {} + + // Test case base name for display purposes. + virtual const string& GetTestCaseName() const { return test_case_name_; } + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + // TEST_P macro uses AddTestPattern() to record information + // about a single test in a LocalTestInfo structure. + // test_case_name is the base name of the test case (without invocation + // prefix). test_base_name is the name of an individual test without + // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is + // test case base name and DoBar is test base name. + void AddTestPattern(const char* test_case_name, + const char* test_base_name, + TestMetaFactoryBase* meta_factory) { + tests_.push_back(linked_ptr(new TestInfo(test_case_name, + test_base_name, + meta_factory))); + } + // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // about a generator. + int AddTestCaseInstantiation(const string& instantiation_name, + GeneratorCreationFunc* func, + const char* /* file */, + int /* line */) { + instantiations_.push_back(::std::make_pair(instantiation_name, func)); + return 0; // Return value used only to run this method in namespace scope. + } + // UnitTest class invokes this method to register tests in this test case + // test cases right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more then once. + virtual void RegisterTests() { + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + linked_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); gen_it != instantiations_.end(); + ++gen_it) { + const string& instantiation_name = gen_it->first; + ParamGenerator generator((*gen_it->second)()); + + string test_case_name; + if ( !instantiation_name.empty() ) + test_case_name = instantiation_name + "/"; + test_case_name += test_info->test_case_base_name; + + int i = 0; + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { + Message test_name_stream; + test_name_stream << test_info->test_base_name << "/" << i; + MakeAndRegisterTestInfo( + test_case_name.c_str(), + test_name_stream.GetString().c_str(), + NULL, // No type parameter. + PrintToString(*param_it).c_str(), + GetTestCaseTypeId(), + TestCase::SetUpTestCase, + TestCase::TearDownTestCase, + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it + } // RegisterTests + + private: + // LocalTestInfo structure keeps information about a single test registered + // with TEST_P macro. + struct TestInfo { + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const string test_case_base_name; + const string test_base_name; + const scoped_ptr > test_meta_factory; + }; + typedef ::std::vector > TestInfoContainer; + // Keeps pairs of + // received from INSTANTIATE_TEST_CASE_P macros. + typedef ::std::vector > + InstantiationContainer; + + const string test_case_name_; + TestInfoContainer tests_; + InstantiationContainer instantiations_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); +}; // class ParameterizedTestCaseInfo + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase +// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P +// macros use it to locate their corresponding ParameterizedTestCaseInfo +// descriptors. +class ParameterizedTestCaseRegistry { + public: + ParameterizedTestCaseRegistry() {} + ~ParameterizedTestCaseRegistry() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + delete *it; + } + } + + // Looks up or creates and returns a structure containing information about + // tests and instantiations of a particular test case. + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, + const char* file, + int line) { + ParameterizedTestCaseInfo* typed_test_info = NULL; + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + if ((*it)->GetTestCaseName() == test_case_name) { + if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test case setup and tear-down in this case. + ReportInvalidTestCaseType(test_case_name, file, line); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestCaseInfo >(*it); + } + break; + } + } + if (typed_test_info == NULL) { + typed_test_info = new ParameterizedTestCaseInfo(test_case_name); + test_case_infos_.push_back(typed_test_info); + } + return typed_test_info; + } + void RegisterTests() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + (*it)->RegisterTests(); + } + } + + private: + typedef ::std::vector TestCaseInfoContainer; + + TestCaseInfoContainer test_case_infos_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +// This file was GENERATED by command: +// pump.py gtest-param-util-generated.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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently Google Test supports at most 50 arguments in Values, +// and at most 10 arguments in Combine. Please contact +// googletestframework@googlegroups.com if you need more. +// Please note that the number of arguments to Combine is limited +// by the maximum arity of the implementation of tr1::tuple which is +// currently set at 10. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end); + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]); + +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { + +// Used in the Values() function to provide polymorphic capabilities. +template +class ValueArray1 { + public: + explicit ValueArray1(T1 v1) : v1_(v1) {} + + template + operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + + const T1 v1_; +}; + +template +class ValueArray2 { + public: + ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + + const T1 v1_; + const T2 v2_; +}; + +template +class ValueArray3 { + public: + ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; +}; + +template +class ValueArray4 { + public: + ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; +}; + +template +class ValueArray5 { + public: + ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; +}; + +template +class ValueArray6 { + public: + ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; +}; + +template +class ValueArray7 { + public: + ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; +}; + +template +class ValueArray8 { + public: + ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; +}; + +template +class ValueArray9 { + public: + ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; +}; + +template +class ValueArray10 { + public: + ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; +}; + +template +class ValueArray11 { + public: + ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; +}; + +template +class ValueArray12 { + public: + ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; +}; + +template +class ValueArray13 { + public: + ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; +}; + +template +class ValueArray14 { + public: + ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; +}; + +template +class ValueArray15 { + public: + ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; +}; + +template +class ValueArray16 { + public: + ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; +}; + +template +class ValueArray17 { + public: + ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; +}; + +template +class ValueArray18 { + public: + ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; +}; + +template +class ValueArray19 { + public: + ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; +}; + +template +class ValueArray20 { + public: + ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; +}; + +template +class ValueArray21 { + public: + ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; +}; + +template +class ValueArray22 { + public: + ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; +}; + +template +class ValueArray23 { + public: + ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; +}; + +template +class ValueArray24 { + public: + ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; +}; + +template +class ValueArray25 { + public: + ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; +}; + +template +class ValueArray26 { + public: + ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; +}; + +template +class ValueArray27 { + public: + ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; +}; + +template +class ValueArray28 { + public: + ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; +}; + +template +class ValueArray29 { + public: + ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; +}; + +template +class ValueArray30 { + public: + ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; +}; + +template +class ValueArray31 { + public: + ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; +}; + +template +class ValueArray32 { + public: + ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; +}; + +template +class ValueArray33 { + public: + ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; +}; + +template +class ValueArray34 { + public: + ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; +}; + +template +class ValueArray35 { + public: + ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; +}; + +template +class ValueArray36 { + public: + ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; +}; + +template +class ValueArray37 { + public: + ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; +}; + +template +class ValueArray38 { + public: + ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; +}; + +template +class ValueArray39 { + public: + ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; +}; + +template +class ValueArray40 { + public: + ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; +}; + +template +class ValueArray41 { + public: + ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; +}; + +template +class ValueArray42 { + public: + ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; +}; + +template +class ValueArray43 { + public: + ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), + v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; +}; + +template +class ValueArray44 { + public: + ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), + v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), + v43_(v43), v44_(v44) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; +}; + +template +class ValueArray45 { + public: + ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), + v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; +}; + +template +class ValueArray46 { + public: + ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; +}; + +template +class ValueArray47 { + public: + ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), + v47_(v47) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; +}; + +template +class ValueArray48 { + public: + ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), + v46_(v46), v47_(v47), v48_(v48) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; +}; + +template +class ValueArray49 { + public: + ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, + T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; +}; + +template +class ValueArray50 { + public: + ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, + T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_), static_cast(v50_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; + const T50 v50_; +}; + +# if GTEST_HAS_COMBINE +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Generates values from the Cartesian product of values produced +// by the argument generators. +// +template +class CartesianProductGenerator2 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator2(const ParamGenerator& g1, + const ParamGenerator& g2) + : g1_(g1), g2_(g2) {} + virtual ~CartesianProductGenerator2() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current2_; + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + ParamType current_value_; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; +}; // class CartesianProductGenerator2 + + +template +class CartesianProductGenerator3 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator3(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + virtual ~CartesianProductGenerator3() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current3_; + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + ParamType current_value_; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; +}; // class CartesianProductGenerator3 + + +template +class CartesianProductGenerator4 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator4(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + virtual ~CartesianProductGenerator4() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current4_; + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + ParamType current_value_; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; +}; // class CartesianProductGenerator4 + + +template +class CartesianProductGenerator5 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator5(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + virtual ~CartesianProductGenerator5() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current5_; + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + ParamType current_value_; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; +}; // class CartesianProductGenerator5 + + +template +class CartesianProductGenerator6 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator6(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + virtual ~CartesianProductGenerator6() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current6_; + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + ParamType current_value_; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; +}; // class CartesianProductGenerator6 + + +template +class CartesianProductGenerator7 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator7(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + virtual ~CartesianProductGenerator7() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current7_; + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + ParamType current_value_; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; +}; // class CartesianProductGenerator7 + + +template +class CartesianProductGenerator8 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator8(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + virtual ~CartesianProductGenerator8() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current8_; + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + ParamType current_value_; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; +}; // class CartesianProductGenerator8 + + +template +class CartesianProductGenerator9 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator9(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + virtual ~CartesianProductGenerator9() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current9_; + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + ParamType current_value_; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; +}; // class CartesianProductGenerator9 + + +template +class CartesianProductGenerator10 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator10(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9, + const ParamGenerator& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + virtual ~CartesianProductGenerator10() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end(), g10_, g10_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9, + const ParamGenerator& g10, + const typename ParamGenerator::iterator& current10) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9), + begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current10_; + if (current10_ == end10_) { + current10_ = begin10_; + ++current9_; + } + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_ && + current10_ == typed_other->current10_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_), + begin10_(other.begin10_), + end10_(other.end10_), + current10_(other.current10_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_, *current10_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_ || + current10_ == end10_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + const typename ParamGenerator::iterator begin10_; + const typename ParamGenerator::iterator end10_; + typename ParamGenerator::iterator current10_; + ParamType current_value_; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; + const ParamGenerator g10_; +}; // class CartesianProductGenerator10 + + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Helper classes providing Combine() with polymorphic features. They allow +// casting CartesianProductGeneratorN to ParamGenerator if T is +// convertible to U. +// +template +class CartesianProductHolder2 { + public: +CartesianProductHolder2(const Generator1& g1, const Generator2& g2) + : g1_(g1), g2_(g2) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator2( + static_cast >(g1_), + static_cast >(g2_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + + const Generator1 g1_; + const Generator2 g2_; +}; // class CartesianProductHolder2 + +template +class CartesianProductHolder3 { + public: +CartesianProductHolder3(const Generator1& g1, const Generator2& g2, + const Generator3& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator3( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; +}; // class CartesianProductHolder3 + +template +class CartesianProductHolder4 { + public: +CartesianProductHolder4(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator4( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; +}; // class CartesianProductHolder4 + +template +class CartesianProductHolder5 { + public: +CartesianProductHolder5(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator5( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; +}; // class CartesianProductHolder5 + +template +class CartesianProductHolder6 { + public: +CartesianProductHolder6(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator6( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; +}; // class CartesianProductHolder6 + +template +class CartesianProductHolder7 { + public: +CartesianProductHolder7(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator7( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; +}; // class CartesianProductHolder7 + +template +class CartesianProductHolder8 { + public: +CartesianProductHolder8(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator8( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; +}; // class CartesianProductHolder8 + +template +class CartesianProductHolder9 { + public: +CartesianProductHolder9(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator9( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; +}; // class CartesianProductHolder9 + +template +class CartesianProductHolder10 { + public: +CartesianProductHolder10(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9, const Generator10& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator10( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_), + static_cast >(g10_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; + const Generator10 g10_; +}; // class CartesianProductHolder10 + +# endif // GTEST_HAS_COMBINE + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Functions producing parameter generators. +// +// Google Test uses these generators to produce parameters for value- +// parameterized tests. When a parameterized test case is instantiated +// with a particular generator, Google Test creates and runs tests +// for each element in the sequence produced by the generator. +// +// In the following sample, tests from test case FooTest are instantiated +// each three times with parameter values 3, 5, and 8: +// +// class FooTest : public TestWithParam { ... }; +// +// TEST_P(FooTest, TestThis) { +// } +// TEST_P(FooTest, TestThat) { +// } +// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// + +// Range() returns generators providing sequences of values in a range. +// +// Synopsis: +// Range(start, end) +// - returns a generator producing a sequence of values {start, start+1, +// start+2, ..., }. +// Range(start, end, step) +// - returns a generator producing a sequence of values {start, start+step, +// start+step+step, ..., }. +// Notes: +// * The generated sequences never include end. For example, Range(1, 5) +// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) +// returns a generator producing {1, 3, 5, 7}. +// * start and end must have the same type. That type may be any integral or +// floating-point type or a user defined type satisfying these conditions: +// * It must be assignable (have operator=() defined). +// * It must have operator+() (operator+(int-compatible type) for +// two-operand version). +// * It must have operator<() defined. +// Elements in the resulting sequences will also have that type. +// * Condition start < end must be satisfied in order for resulting sequences +// to contain any elements. +// +template +internal::ParamGenerator Range(T start, T end, IncrementT step) { + return internal::ParamGenerator( + new internal::RangeGenerator(start, end, step)); +} + +template +internal::ParamGenerator Range(T start, T end) { + return Range(start, end, 1); +} + +// ValuesIn() function allows generation of tests with parameters coming from +// a container. +// +// Synopsis: +// ValuesIn(const T (&array)[N]) +// - returns a generator producing sequences with elements from +// a C-style array. +// ValuesIn(const Container& container) +// - returns a generator producing sequences with elements from +// an STL-style container. +// ValuesIn(Iterator begin, Iterator end) +// - returns a generator producing sequences with elements from +// a range [begin, end) defined by a pair of STL-style iterators. These +// iterators can also be plain C pointers. +// +// Please note that ValuesIn copies the values from the containers +// passed in and keeps them to generate tests in RUN_ALL_TESTS(). +// +// Examples: +// +// This instantiates tests from test case StringTest +// each with C-string values of "foo", "bar", and "baz": +// +// const char* strings[] = {"foo", "bar", "baz"}; +// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// +// This instantiates tests from test case StlStringTest +// each with STL strings with values "a" and "b": +// +// ::std::vector< ::std::string> GetParameterStrings() { +// ::std::vector< ::std::string> v; +// v.push_back("a"); +// v.push_back("b"); +// return v; +// } +// +// INSTANTIATE_TEST_CASE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); +// +// +// This will also instantiate tests from CharTest +// each with parameter values 'a' and 'b': +// +// ::std::list GetParameterChars() { +// ::std::list list; +// list.push_back('a'); +// list.push_back('b'); +// return list; +// } +// ::std::list l = GetParameterChars(); +// INSTANTIATE_TEST_CASE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); +// +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end) { + typedef typename ::testing::internal::IteratorTraits + ::value_type ParamType; + return internal::ParamGenerator( + new internal::ValuesInIteratorRangeGenerator(begin, end)); +} + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]) { + return ValuesIn(array, array + N); +} + +template +internal::ParamGenerator ValuesIn( + const Container& container) { + return ValuesIn(container.begin(), container.end()); +} + +// Values() allows generating tests from explicitly specified list of +// parameters. +// +// Synopsis: +// Values(T v1, T v2, ..., T vN) +// - returns a generator producing sequences with elements v1, v2, ..., vN. +// +// For example, this instantiates tests from test case BarTest each +// with values "one", "two", and "three": +// +// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// +// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// The exact type of values will depend on the type of parameter in BazTest. +// +// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// +// Currently, Values() supports from 1 to 50 parameters. +// +template +internal::ValueArray1 Values(T1 v1) { + return internal::ValueArray1(v1); +} + +template +internal::ValueArray2 Values(T1 v1, T2 v2) { + return internal::ValueArray2(v1, v2); +} + +template +internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { + return internal::ValueArray3(v1, v2, v3); +} + +template +internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { + return internal::ValueArray4(v1, v2, v3, v4); +} + +template +internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5) { + return internal::ValueArray5(v1, v2, v3, v4, v5); +} + +template +internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6) { + return internal::ValueArray6(v1, v2, v3, v4, v5, v6); +} + +template +internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7) { + return internal::ValueArray7(v1, v2, v3, v4, v5, + v6, v7); +} + +template +internal::ValueArray8 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { + return internal::ValueArray8(v1, v2, v3, v4, + v5, v6, v7, v8); +} + +template +internal::ValueArray9 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { + return internal::ValueArray9(v1, v2, v3, + v4, v5, v6, v7, v8, v9); +} + +template +internal::ValueArray10 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { + return internal::ValueArray10(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10); +} + +template +internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) { + return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); +} + +template +internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) { + return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); +} + +template +internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) { + return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); +} + +template +internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { + return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14); +} + +template +internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { + return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15); +} + +template +internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16) { + return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16); +} + +template +internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17) { + return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17); +} + +template +internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18) { + return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18); +} + +template +internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { + return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); +} + +template +internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { + return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); +} + +template +internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { + return internal::ValueArray21(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); +} + +template +internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22) { + return internal::ValueArray22(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22); +} + +template +internal::ValueArray23 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23) { + return internal::ValueArray23(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23); +} + +template +internal::ValueArray24 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24) { + return internal::ValueArray24(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24); +} + +template +internal::ValueArray25 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { + return internal::ValueArray25(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25); +} + +template +internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) { + return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); +} + +template +internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) { + return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); +} + +template +internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) { + return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28); +} + +template +internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) { + return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29); +} + +template +internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { + return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30); +} + +template +internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { + return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31); +} + +template +internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32) { + return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32); +} + +template +internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33) { + return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); +} + +template +internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34) { + return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); +} + +template +internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { + return internal::ValueArray35(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); +} + +template +internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { + return internal::ValueArray36(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36); +} + +template +internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37) { + return internal::ValueArray37(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37); +} + +template +internal::ValueArray38 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38) { + return internal::ValueArray38(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, + v33, v34, v35, v36, v37, v38); +} + +template +internal::ValueArray39 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38, T39 v39) { + return internal::ValueArray39(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + v32, v33, v34, v35, v36, v37, v38, v39); +} + +template +internal::ValueArray40 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, + T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, + T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { + return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, + v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); +} + +template +internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { + return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); +} + +template +internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) { + return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, + v42); +} + +template +internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) { + return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, + v41, v42, v43); +} + +template +internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) { + return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, + v40, v41, v42, v43, v44); +} + +template +internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { + return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, + v39, v40, v41, v42, v43, v44, v45); +} + +template +internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { + return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46); +} + +template +internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { + return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); +} + +template +internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, + T48 v48) { + return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, + v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); +} + +template +internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, + T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, + T47 v47, T48 v48, T49 v49) { + return internal::ValueArray49(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, + v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); +} + +template +internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, + T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, + T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { + return internal::ValueArray50(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, + v48, v49, v50); +} + +// Bool() allows generating tests with parameters in a set of (false, true). +// +// Synopsis: +// Bool() +// - returns a generator producing sequences with elements {false, true}. +// +// It is useful when testing code that depends on Boolean flags. Combinations +// of multiple flags can be tested when several Bool()'s are combined using +// Combine() function. +// +// In the following example all tests in the test case FlagDependentTest +// will be instantiated twice with parameters false and true. +// +// class FlagDependentTest : public testing::TestWithParam { +// virtual void SetUp() { +// external_flag = GetParam(); +// } +// } +// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); +// +inline internal::ParamGenerator Bool() { + return Values(false, true); +} + +# if GTEST_HAS_COMBINE +// Combine() allows the user to combine two or more sequences to produce +// values of a Cartesian product of those sequences' elements. +// +// Synopsis: +// Combine(gen1, gen2, ..., genN) +// - returns a generator producing sequences with elements coming from +// the Cartesian product of elements from the sequences generated by +// gen1, gen2, ..., genN. The sequence elements will have a type of +// tuple where T1, T2, ..., TN are the types +// of elements from sequences produces by gen1, gen2, ..., genN. +// +// Combine can have up to 10 arguments. This number is currently limited +// by the maximum number of elements in the tuple implementation used by Google +// Test. +// +// Example: +// +// This will instantiate tests in test case AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// class AnimalTest +// : public testing::TestWithParam > {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); +// +// This will instantiate tests in FlagDependentTest with all variations of two +// Boolean flags: +// +// class FlagDependentTest +// : public testing::TestWithParam > { +// virtual void SetUp() { +// // Assigns external_flag_1 and external_flag_2 values from the tuple. +// tie(external_flag_1, external_flag_2) = GetParam(); +// } +// }; +// +// TEST_P(FlagDependentTest, TestFeature1) { +// // Test your code using external_flag_1 and external_flag_2 here. +// } +// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder2 Combine( + const Generator1& g1, const Generator2& g2) { + return internal::CartesianProductHolder2( + g1, g2); +} + +template +internal::CartesianProductHolder3 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3) { + return internal::CartesianProductHolder3( + g1, g2, g3); +} + +template +internal::CartesianProductHolder4 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4) { + return internal::CartesianProductHolder4( + g1, g2, g3, g4); +} + +template +internal::CartesianProductHolder5 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5) { + return internal::CartesianProductHolder5( + g1, g2, g3, g4, g5); +} + +template +internal::CartesianProductHolder6 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6) { + return internal::CartesianProductHolder6( + g1, g2, g3, g4, g5, g6); +} + +template +internal::CartesianProductHolder7 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7) { + return internal::CartesianProductHolder7( + g1, g2, g3, g4, g5, g6, g7); +} + +template +internal::CartesianProductHolder8 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8) { + return internal::CartesianProductHolder8( + g1, g2, g3, g4, g5, g6, g7, g8); +} + +template +internal::CartesianProductHolder9 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9) { + return internal::CartesianProductHolder9( + g1, g2, g3, g4, g5, g6, g7, g8, g9); +} + +template +internal::CartesianProductHolder10 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9, + const Generator10& g10) { + return internal::CartesianProductHolder10( + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); +} +# endif // GTEST_HAS_COMBINE + + + +# define TEST_P(test_case_name, test_name) \ + class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + : public test_case_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ + virtual void TestBody(); \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ + #test_case_name, \ + #test_name, \ + new ::testing::internal::TestMetaFactory< \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ + return 0; \ + } \ + static int gtest_registering_dummy_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_case_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + ::testing::internal::ParamGenerator \ + gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ + int gtest_##prefix##test_case_name##_dummy_ = \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ + #prefix, \ + >est_##prefix##test_case_name##_EvalGenerator_, \ + __FILE__, __LINE__) + +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +// Copyright 2006, 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++ Testing Framework definitions useful in production code. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// When you need to test the private or protected members of a class, +// use the FRIEND_TEST macro to declare your tests as friends of the +// class. For example: +// +// class MyClass { +// private: +// void MyMethod(); +// FRIEND_TEST(MyClassTest, MyMethod); +// }; +// +// class MyClassTest : public testing::Test { +// // ... +// }; +// +// TEST_F(MyClassTest, MyMethod) { +// // Can call MyClass::MyMethod() here. +// } + +#define FRIEND_TEST(test_case_name, test_name)\ +friend class test_case_name##_##test_name##_Test + +#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +// 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: mheule@google.com (Markus Heule) +// + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ + +#include +#include + +namespace testing { + +// A copyable object representing the result of a test part (i.e. an +// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). +// +// Don't inherit from TestPartResult as its destructor is not virtual. +class GTEST_API_ TestPartResult { + public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + + // C'tor. TestPartResult does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestPartResult object. + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name == NULL ? "" : a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { + } + + // Gets the outcome of the test part. + Type type() const { return type_; } + + // Gets the name of the source file where the test part took place, or + // NULL if it's unknown. + const char* file_name() const { + return file_name_.empty() ? NULL : file_name_.c_str(); + } + + // Gets the line in the source file where the test part took place, + // or -1 if it's unknown. + int line_number() const { return line_number_; } + + // Gets the summary of the failure message. + const char* summary() const { return summary_.c_str(); } + + // Gets the message associated with the test part. + const char* message() const { return message_.c_str(); } + + // Returns true iff the test part passed. + bool passed() const { return type_ == kSuccess; } + + // Returns true iff the test part failed. + bool failed() const { return type_ != kSuccess; } + + // Returns true iff the test part non-fatally failed. + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } + + // Returns true iff the test part fatally failed. + bool fatally_failed() const { return type_ == kFatalFailure; } + + private: + Type type_; + + // Gets the summary of the failure message by omitting the stack + // trace in it. + static std::string ExtractSummary(const char* message); + + // The name of the source file where the test part took place, or + // "" if the source file is unknown. + std::string file_name_; + // The line in the source file where the test part took place, or -1 + // if the line number is unknown. + int line_number_; + std::string summary_; // The test failure summary. + std::string message_; // The test failure message. +}; + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result); + +// An array of TestPartResult objects. +// +// Don't inherit from TestPartResultArray as its destructor is not +// virtual. +class GTEST_API_ TestPartResultArray { + public: + TestPartResultArray() {} + + // Appends the given TestPartResult to the array. + void Append(const TestPartResult& result); + + // Returns the TestPartResult at the given index (0-based). + const TestPartResult& GetTestPartResult(int index) const; + + // Returns the number of TestPartResult objects in the array. + int size() const; + + private: + std::vector array_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); +}; + +// This interface knows how to report a test part result. +class TestPartResultReporterInterface { + public: + virtual ~TestPartResultReporterInterface() {} + + virtual void ReportTestPartResult(const TestPartResult& result) = 0; +}; + +namespace internal { + +// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a +// statement generates new fatal failures. To do so it registers itself as the +// current test part result reporter. Besides checking if fatal failures were +// reported, it only delegates the reporting to the former result reporter. +// The original result reporter is restored in the destructor. +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { + public: + HasNewFatalFailureHelper(); + virtual ~HasNewFatalFailureHelper(); + virtual void ReportTestPartResult(const TestPartResult& result); + bool has_new_fatal_failure() const { return has_new_fatal_failure_; } + private: + bool has_new_fatal_failure_; + TestPartResultReporterInterface* original_reporter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); +}; + +} // namespace internal + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +// 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) + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// This header implements typed tests and type-parameterized tests. + +// Typed (aka type-driven) tests repeat the same test for types in a +// list. You must know which types you want to test with when writing +// typed tests. Here's how you do it: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + public: + ... + typedef std::list List; + static T shared_; + T value_; +}; + +// Next, associate a list of types with the test case, which will be +// repeated for each type in the list. The typedef is necessary for +// the macro to parse correctly. +typedef testing::Types MyTypes; +TYPED_TEST_CASE(FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// TYPED_TEST_CASE(FooTest, int); + +// Then, use TYPED_TEST() instead of TEST_F() to define as many typed +// tests for this test case as you want. +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + // Since we are inside a derived class template, C++ requires use to + // visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the TestFixture:: + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the "typename + // TestFixture::" prefix. + typename TestFixture::List values; + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } + +#endif // 0 + +// Type-parameterized tests are abstract test patterns parameterized +// by a type. Compared with typed tests, type-parameterized tests +// allow you to define the test pattern without knowing what the type +// parameters are. The defined pattern can be instantiated with +// different types any number of times, in any number of translation +// units. +// +// If you are designing an interface or concept, you can define a +// suite of type-parameterized tests to verify properties that any +// valid implementation of the interface/concept should have. Then, +// each implementation can easily instantiate the test suite to verify +// that it conforms to the requirements, without having to write +// similar tests repeatedly. Here's an example: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + ... +}; + +// Next, declare that you will define a type-parameterized test case +// (the _P suffix is for "parameterized" or "pattern", whichever you +// prefer): +TYPED_TEST_CASE_P(FooTest); + +// Then, use TYPED_TEST_P() to define as many type-parameterized tests +// for this type-parameterized test case as you want. +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } + +// Now the tricky part: you need to register all test patterns before +// you can instantiate them. The first argument of the macro is the +// test case name; the rest are the names of the tests in this test +// case. +REGISTER_TYPED_TEST_CASE_P(FooTest, + DoesBlah, HasPropertyA); + +// Finally, you are free to instantiate the pattern with the types you +// want. If you put the above code in a header file, you can #include +// it in multiple C++ source files and instantiate it multiple times. +// +// To distinguish different instances of the pattern, the first +// argument to the INSTANTIATE_* macro is a prefix that will be added +// to the actual test case name. Remember to pick unique prefixes for +// different instances. +typedef testing::Types MyTypes; +INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); + +#endif // 0 + + +// Implements typed tests. + +#if GTEST_HAS_TYPED_TEST + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the typedef for the type parameters of the +// given test case. +# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define TYPED_TEST_CASE(CaseName, Types) \ + typedef ::testing::internal::TypeList< Types >::type \ + GTEST_TYPE_PARAMS_(CaseName) + +# define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel< \ + GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ + GTEST_TYPE_PARAMS_(CaseName)>::Register(\ + "", #CaseName, #TestName, 0); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() + +#endif // GTEST_HAS_TYPED_TEST + +// Implements type-parameterized tests. + +#if GTEST_HAS_TYPED_TEST_P + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the namespace name that the type-parameterized tests for +// the given type-parameterized test case are defined in. The exact +// name of the namespace is subject to change without notice. +# define GTEST_CASE_NAMESPACE_(TestCaseName) \ + gtest_case_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the variable used to remember the names of +// the defined tests in the given test case. +# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ + gtest_typed_test_case_p_state_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. +// +// Expands to the name of the variable used to remember the names of +// the registered tests in the given test case. +# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ + gtest_registered_test_names_##TestCaseName##_ + +// The variables defined in the type-parameterized test macros are +// static as typically these macros are used in a .h file that can be +// #included in multiple translation units linked together. +# define TYPED_TEST_CASE_P(CaseName) \ + static ::testing::internal::TypedTestCasePState \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) + +# define TYPED_TEST_P(CaseName, TestName) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + template \ + class TestName : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ + __FILE__, __LINE__, #CaseName, #TestName); \ + } \ + template \ + void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() + +# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ + __FILE__, __LINE__, #__VA_ARGS__) + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ + bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestCase::type>::Register(\ + #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) + +#endif // GTEST_HAS_TYPED_TEST_P + +#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// Depending on the platform, different string classes are available. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. +// +// If the user's ::std::string and ::string are the same class due to +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. +// +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. + +namespace testing { + +// Declares the flags. + +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); + +// This flag controls whether Google Test includes Google Test internal +// stack frames in failure stack traces. +GTEST_DECLARE_bool_(show_internal_stack_frames); + +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// When this flag is set with a "host:port" string, on supported +// platforms test results are streamed to the specified port on +// the specified host machine. +GTEST_DECLARE_string_(stream_result_to); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + +namespace internal { + +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; +class GTestFlagSaver; +class StreamingListenerTest; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class UnitTestRecordPropertyTestHelper; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message); + +} // namespace internal + +// The friend relationship of some of these classes is cyclic. +// If we don't forward declare them the compiler might confuse the classes +// in friendship clauses with same named classes on the scope. +class Test; +class TestCase; +class TestInfo; +class UnitTest; + +// A class for indicating whether an assertion was successful. When +// the assertion wasn't successful, the AssertionResult object +// remembers a non-empty message that describes how it failed. +// +// To create an instance of this class, use one of the factory functions +// (AssertionSuccess() and AssertionFailure()). +// +// This class is useful for two purposes: +// 1. Defining predicate functions to be used with Boolean test assertions +// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts +// 2. Defining predicate-format functions to be +// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). +// +// For example, if you define IsEven predicate: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) +// will print the message +// +// Value of: IsEven(Fib(5)) +// Actual: false (5 is odd) +// Expected: true +// +// instead of a more opaque +// +// Value of: IsEven(Fib(5)) +// Actual: false +// Expected: true +// +// in case IsEven is a simple Boolean predicate. +// +// If you expect your predicate to be reused and want to support informative +// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up +// about half as often as positive ones in our tests), supply messages for +// both success and failure cases: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess() << n << " is even"; +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print +// +// Value of: IsEven(Fib(6)) +// Actual: true (8 is even) +// Expected: false +// +// NB: Predicates that support negative Boolean assertions have reduced +// performance in positive ones so be careful not to use them in tests +// that have lots (tens of thousands) of positive Boolean assertions. +// +// To use this class with EXPECT_PRED_FORMAT assertions such as: +// +// // Verifies that Foo() returns an even number. +// EXPECT_PRED_FORMAT1(IsEven, Foo()); +// +// you need to define: +// +// testing::AssertionResult IsEven(const char* expr, int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() +// << "Expected: " << expr << " is even\n Actual: it's " << n; +// } +// +// If Foo() returns 5, you will see the following message: +// +// Expected: Foo() is even +// Actual: it's 5 +// +class GTEST_API_ AssertionResult { + public: + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} + + // Returns true iff the assertion succeeded. + operator bool() const { return success_; } // NOLINT + + // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. + AssertionResult operator!() const; + + // Returns the text streamed into this AssertionResult. Test assertions + // use it when they fail (i.e., the predicate's outcome doesn't match the + // assertion's expectation). When nothing has been streamed into the + // object, returns an empty string. + const char* message() const { + return message_.get() != NULL ? message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } + + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value) { + AppendMessage(Message() << value); + return *this; + } + + // Allows streaming basic output manipulators such as endl or flush into + // this object. + AssertionResult& operator<<( + ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { + AppendMessage(Message() << basic_manipulator); + return *this; + } + + private: + // Appends the contents of message to message_. + void AppendMessage(const Message& a_message) { + if (message_.get() == NULL) + message_.reset(new ::std::string); + message_->append(a_message.GetString().c_str()); + } + + // Stores result of the assertion predicate. + bool success_; + // Stores the message describing the condition in case the expectation + // construct is not satisfied with the predicate's outcome. + // Referenced via a pointer to avoid taking too much stack frame space + // with test assertions. + internal::scoped_ptr< ::std::string> message_; + + GTEST_DISALLOW_ASSIGN_(AssertionResult); +}; + +// Makes a successful assertion result. +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); + +// The abstract class that all tests inherit from. +// +// In Google Test, a unit test program contains one or many TestCases, and +// each TestCase contains one or many Tests. +// +// When you define a test using the TEST macro, you don't need to +// explicitly derive from Test - the TEST macro automatically does +// this for you. +// +// The only time you derive from Test is when defining a test fixture +// to be used a TEST_F. For example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { ... } +// virtual void TearDown() { ... } +// ... +// }; +// +// TEST_F(FooTest, Bar) { ... } +// TEST_F(FooTest, Baz) { ... } +// +// Test is not copyable. +class GTEST_API_ Test { + public: + friend class TestInfo; + + // Defines types for pointers to functions that set up and tear down + // a test case. + typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; + typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; + + // The d'tor is virtual as we intend to inherit from Test. + virtual ~Test(); + + // Sets up the stuff shared by all tests in this test case. + // + // Google Test will call Foo::SetUpTestCase() before running the first + // test in test case Foo. Hence a sub-class can define its own + // SetUpTestCase() method to shadow the one defined in the super + // class. + static void SetUpTestCase() {} + + // Tears down the stuff shared by all tests in this test case. + // + // Google Test will call Foo::TearDownTestCase() after running the last + // test in test case Foo. Hence a sub-class can define its own + // TearDownTestCase() method to shadow the one defined in the super + // class. + static void TearDownTestCase() {} + + // Returns true iff the current test has a fatal failure. + static bool HasFatalFailure(); + + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + + // Logs a property for the current test, test case, or for the entire + // invocation of the test program when used outside of the context of a + // test case. Only the last value for a given key is remembered. These + // are public static so they can be called from utility functions that are + // not members of the test fixture. Calls to RecordProperty made during + // lifespan of the test (from the moment its constructor starts to the + // moment its destructor finishes) will be output in XML as attributes of + // the element. Properties recorded from fixture's + // SetUpTestCase or TearDownTestCase are logged as attributes of the + // corresponding element. Calls to RecordProperty made in the + // global context (before or after invocation of RUN_ALL_TESTS and from + // SetUp/TearDown method of Environment objects registered with Google + // Test) will be output as attributes of the element. + static void RecordProperty(const std::string& key, const std::string& value); + static void RecordProperty(const std::string& key, int value); + + protected: + // Creates a Test object. + Test(); + + // Sets up the test fixture. + virtual void SetUp(); + + // Tears down the test fixture. + virtual void TearDown(); + + private: + // Returns true iff the current test has the same fixture class as + // the first test in the current test case. + static bool HasSameFixtureClass(); + + // Runs the test after the test fixture has been set up. + // + // A sub-class must implement this to define the test logic. + // + // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. + // Instead, use the TEST or TEST_F macro. + virtual void TestBody() = 0; + + // Sets up, executes, and tears down the test. + void Run(); + + // Deletes self. We deliberately pick an unusual name for this + // internal method to avoid clashing with names used in user TESTs. + void DeleteSelf_() { delete this; } + + // Uses a GTestFlagSaver to save and restore all Google Test flags. + const internal::GTestFlagSaver* const gtest_flag_saver_; + + // Often a user mis-spells SetUp() as Setup() and spends a long time + // wondering why it is never called by Google Test. The declaration of + // the following method is solely for catching such an error at + // compile time: + // + // - The return type is deliberately chosen to be not void, so it + // will be a conflict if a user declares void Setup() in his test + // fixture. + // + // - This method is private, so it will be another compiler error + // if a user calls it from his test fixture. + // + // DO NOT OVERRIDE THIS FUNCTION. + // + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + + // We disallow copying Tests. + GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); +}; + +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const std::string& a_key, const std::string& a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const std::string& new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + std::string key_; + // The value supplied by the user. + std::string value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class TestCase; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. xml_element specifies the element for which the property is being + // recorded and is used for validation. + void RecordProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector test_part_results_; + // The vector of TestProperties + std::vector test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult + +// A TestInfo object stores the following information about a test: +// +// Test case name +// Test name +// Whether the test should be run +// A function pointer that creates the test object when invoked +// Test result +// +// The constructor of TestInfo registers itself with the UnitTest +// singleton such that the RUN_ALL_TESTS() macro knows which tests to +// run. +class GTEST_API_ TestInfo { + public: + // Destructs a TestInfo object. This function is not virtual, so + // don't inherit from TestInfo. + ~TestInfo(); + + // Returns the test case name. + const char* test_case_name() const { return test_case_name_.c_str(); } + + // Returns the test name. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a typed + // or a type-parameterized test. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns the text representation of the value parameter, or NULL if this + // is not a value-parameterized test. + const char* value_param() const { + if (value_param_.get() != NULL) + return value_param_->c_str(); + return NULL; + } + + // Returns true if this test should run, that is if the test is not + // disabled (or it is disabled but the also_run_disabled_tests flag has + // been specified) and its full name matches the user-specified filter. + // + // Google Test allows the user to filter the tests by their full names. + // The full name of a test Bar in test case Foo is defined as + // "Foo.Bar". Only the tests that match the filter will run. + // + // A filter is a colon-separated list of glob (not regex) patterns, + // optionally followed by a '-' and a colon-separated list of + // negative patterns (tests to exclude). A test is run if it + // matches one of the positive patterns and does not match any of + // the negative patterns. + // + // For example, *A*:Foo.* is a filter that matches any string that + // contains the character 'A' or starts with "Foo.". + bool should_run() const { return should_run_; } + + // Returns true iff this test will appear in the XML report. + bool is_reportable() const { + // For now, the XML report includes all tests matching the filter. + // In the future, we may trim tests that are excluded because of + // sharding. + return matches_filter_; + } + + // Returns the result of the test. + const TestResult* result() const { return &result_; } + + private: +#if GTEST_HAS_DEATH_TEST + friend class internal::DefaultDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + friend class Test; + friend class TestCase; + friend class internal::UnitTestImpl; + friend class internal::StreamingListenerTest; + friend TestInfo* internal::MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + internal::TypeId fixture_class_id, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + internal::TestFactoryBase* factory); + + // Constructs a TestInfo object. The newly constructed instance assumes + // ownership of the factory object. + TestInfo(const std::string& test_case_name, + const std::string& name, + const char* a_type_param, // NULL if not a type-parameterized test + const char* a_value_param, // NULL if not a value-parameterized test + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); + + // Increments the number of death tests encountered in this test so + // far. + int increment_death_test_count() { + return result_.increment_death_test_count(); + } + + // Creates the test object, runs it, records its result, and then + // deletes it. + void Run(); + + static void ClearTestResult(TestInfo* test_info) { + test_info->result_.Clear(); + } + + // These fields are immutable properties of the test. + const std::string test_case_name_; // Test case name + const std::string name_; // Test name + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // Text representation of the value parameter, or NULL if this is not a + // value-parameterized test. + const internal::scoped_ptr value_param_; + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True iff this test should run + bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + internal::TestFactoryBase* const factory_; // The factory that creates + // the test object + + // This field is mutable and needs to be reset before running the + // test for the second time. + TestResult result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); +}; + +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // a_type_param: the name of the test's type parameter, or NULL if + // this is not a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a + // type-parameterized test case. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + // Returns the TestResult that holds test properties recorded during + // execution of SetUpTestCase and TearDownTestCase. + const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Runs SetUpTestCase() for this TestCase. This wrapper is needed + // for catching exceptions thrown from SetUpTestCase(). + void RunSetUpTestCase() { (*set_up_tc_)(); } + + // Runs TearDownTestCase() for this TestCase. This wrapper is + // needed for catching exceptions thrown from TearDownTestCase(). + void RunTearDownTestCase() { (*tear_down_tc_)(); } + + // Returns true iff test passed. + static bool TestPassed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Passed(); + } + + // Returns true iff test failed. + static bool TestFailed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Failed(); + } + + // Returns true iff the test is disabled and will be reported in the XML + // report. + static bool TestReportableDisabled(const TestInfo* test_info) { + return test_info->is_reportable() && test_info->is_disabled_; + } + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo* test_info) { + return test_info->is_disabled_; + } + + // Returns true iff this test will appear in the XML report. + static bool TestReportable(const TestInfo* test_info) { + return test_info->is_reportable(); + } + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo* test_info) { + return test_info->should_run(); + } + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + std::string name_; + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + // Holds test properties recorded during execution of SetUpTestCase and + // TearDownTestCase. + TestResult ad_hoc_test_result_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + +// An Environment object is capable of setting up and tearing down an +// environment. The user should subclass this to define his own +// environment(s). +// +// An Environment object does the set-up and tear-down in virtual +// methods SetUp() and TearDown() instead of the constructor and the +// destructor, as: +// +// 1. You cannot safely throw from a destructor. This is a problem +// as in some cases Google Test is used where exceptions are enabled, and +// we may want to implement ASSERT_* using exceptions where they are +// available. +// 2. You cannot use ASSERT_* directly in a constructor or +// destructor. +class Environment { + public: + // The d'tor is virtual as we need to subclass Environment. + virtual ~Environment() {} + + // Override this to define how to set up the environment. + virtual void SetUp() {} + + // Override this to define how to tear down the environment. + virtual void TearDown() {} + private: + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } +}; + +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class TestInfo; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. +// +// This is a singleton class. The only instance of UnitTest is +// created when UnitTest::GetInstance() is first called. This +// instance is never deleted. +// +// UnitTest is not copyable. +// +// This class is thread-safe as long as the methods are called +// according to their specification. +class GTEST_API_ UnitTest { + public: + // Gets the singleton UnitTest object. The first time this method + // is called, a UnitTest object is constructed and returned. + // Consecutive calls will return the same object. + static UnitTest* GetInstance(); + + // Runs all tests in this UnitTest object and prints the result. + // Returns 0 if successful, or 1 otherwise. + // + // This method can only be called from the main thread. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + int Run() GTEST_MUST_USE_RESULT_; + + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + + // Returns the TestCase object for the test that's currently running, + // or NULL if no test is running. + const TestCase* current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the TestInfo object for the test that's currently running, + // or NULL if no test is running. + const TestInfo* current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST + // Returns the ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_); +#endif // GTEST_HAS_PARAM_TEST + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the TestResult containing information on test failures and + // properties logged outside of individual test cases. + const TestResult& ad_hoc_test_result() const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Adds a TestProperty to the current TestResult object when invoked from + // inside a test, to current TestCase's ad_hoc_test_result_ when invoked + // from SetUpTestCase or TearDownTestCase, or to the global property set + // when invoked elsewhere. If the result already contains a property with + // the same key, the value will be updated. + void RecordProperty(const std::string& key, const std::string& value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + + // Accessors for the implementation object. + internal::UnitTestImpl* impl() { return impl_; } + const internal::UnitTestImpl* impl() const { return impl_; } + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; + friend class internal::ScopedTrace; + friend class internal::StreamingListenerTest; + friend class internal::UnitTestRecordPropertyTestHelper; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const std::string& message); + + // Creates an empty UnitTest. + UnitTest(); + + // D'tor + virtual ~UnitTest(); + + // Pushes a trace defined by SCOPED_TRACE() on to the per-thread + // Google Test trace stack. + void PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Pops a trace from the per-thread Google Test trace stack. + void PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_); + + // Protects mutable state in *impl_. This is mutable as some const + // methods need to lock it too. + mutable internal::Mutex mutex_; + + // Opaque implementation object. This field is never changed once + // the object is constructed. We don't mark it as const here, as + // doing so will cause a warning in the constructor of UnitTest. + // Mutable state in *impl_ is protected by mutex_. + internal::UnitTestImpl* impl_; + + // We disallow copying UnitTest. + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); +}; + +// A convenient wrapper for adding an environment for the test +// program. +// +// You should call this before RUN_ALL_TESTS() is called, probably in +// main(). If you use gtest_main, you need to call this before main() +// starts for it to take effect. For example, you can define a global +// variable like this: +// +// testing::Environment* const foo_env = +// testing::AddGlobalTestEnvironment(new FooEnvironment); +// +// However, we strongly recommend you to write your own main() and +// call AddGlobalTestEnvironment() there, as relying on initialization +// of global variables makes the code harder to read and may cause +// problems when you register multiple environments from different +// translation units and the environments have dependencies among them +// (remember that the compiler doesn't guarantee the order in which +// global variables from different translation units are initialized). +inline Environment* AddGlobalTestEnvironment(Environment* env) { + return UnitTest::GetInstance()->AddEnvironment(env); +} + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +GTEST_API_ void InitGoogleTest(int* argc, char** argv); + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); + +namespace internal { + +// FormatForComparison::Format(value) formats a +// value of type ToPrint that is an operand of a comparison assertion +// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in +// the comparison, and is used to help determine the best way to +// format the value. In particular, when the value is a C string +// (char pointer) and the other operand is an STL string object, we +// want to format the C string as a string, since we know it is +// compared by value with the string object. If the value is a char +// pointer but the other operand is not an STL string object, we don't +// know whether the pointer is supposed to point to a NUL-terminated +// string, and thus want to print it as a pointer to be safe. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// The default case. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint& value) { + return ::testing::PrintToString(value); + } +}; + +// Array. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint* value) { + return FormatForComparison::Format(value); + } +}; + +// By default, print C string as pointers to be safe, as we don't know +// whether they actually point to a NUL-terminated string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \ + template \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(static_cast(value)); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ + +// If a C string is compared with an STL string object, we know it's meant +// to point to a NUL-terminated string, and thus can print it as a string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ + template <> \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(value); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); + +#if GTEST_HAS_GLOBAL_STRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string); +#endif + +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring); +#endif + +#if GTEST_HAS_STD_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); +#endif + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ + +// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) +// operand to be used in a failure message. The type (but not value) +// of the other operand may affect the format. This allows us to +// print a char* as a raw pointer when it is compared against another +// char* or void*, and print it as a C string when it is compared +// against an std::string object, for example. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +std::string FormatForComparisonFailureMessage( + const T1& value, const T2& /* other_operand */) { + return FormatForComparison::Format(value); +} + +// The helper function for {ASSERT|EXPECT}_EQ. +template +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { +#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) { + return AssertionSuccess(); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// With this overloaded version, we allow anonymous enums to be used +// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums +// can be implicitly cast to BiggestInt. +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); + +// The helper class for {ASSERT|EXPECT}_EQ. The template argument +// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() +// is a null pointer literal. The following default implementation is +// for lhs_is_null_literal being false. +template +class EqHelper { + public: + // This templatized version is for the general case. + template + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // With this overloaded version, we allow anonymous enums to be used + // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous + // enums can be implicitly cast to BiggestInt. + // + // Even though its body looks the same as the above version, we + // cannot merge the two, as it will make anonymous enums unhappy. + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } +}; + +// This specialization is used when the first argument to ASSERT_EQ() +// is a null pointer literal, like NULL, false, or 0. +template <> +class EqHelper { + public: + // We define two overloaded versions of Compare(). The first + // version will be picked when the second argument to ASSERT_EQ() is + // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or + // EXPECT_EQ(false, a_bool). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual, + // The following line prevents this overload from being considered if T2 + // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) + // expands to Compare("", "", NULL, my_ptr), which requires a conversion + // to match the Secret* in the other overload, which would otherwise make + // this template match better. + typename EnableIf::value>::type* = 0) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // This version will be picked when the second argument to ASSERT_EQ() is a + // pointer, e.g. ASSERT_EQ(NULL, a_pointer). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + // We used to have a second template parameter instead of Secret*. That + // template parameter would deduce to 'long', making this a better match + // than the first overload even without the first overload's EnableIf. + // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to + // non-pointer argument" (even a deduced integral argument), so the old + // implementation caused warnings in user code. + Secret* /* expected (NULL) */, + T* actual) { + // We already know that 'expected' is a null pointer. + return CmpHelperEQ(expected_expression, actual_expression, + static_cast(NULL), actual); + } +}; + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste +// of similar code. +// +// For each templatized helper function, we also define an overloaded +// version for BiggestInt in order to reduce code bloat and allow +// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled +// with gcc 4. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +template \ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + const T1& val1, const T2& val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +}\ +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) + +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// Implements the helper function for {ASSERT|EXPECT}_NE +GTEST_IMPL_CMP_HELPER_(NE, !=); +// Implements the helper function for {ASSERT|EXPECT}_LE +GTEST_IMPL_CMP_HELPER_(LE, <=); +// Implements the helper function for {ASSERT|EXPECT}_LT +GTEST_IMPL_CMP_HELPER_(LT, <); +// Implements the helper function for {ASSERT|EXPECT}_GE +GTEST_IMPL_CMP_HELPER_(GE, >=); +// Implements the helper function for {ASSERT|EXPECT}_GT +GTEST_IMPL_CMP_HELPER_(GT, >); + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRNE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + + +// Helper function for *_STREQ on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); + +// Helper function for *_STRNE on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); + +} // namespace internal + +// IsSubstring() and IsNotSubstring() are intended to be used as the +// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by +// themselves. They check whether needle is a substring of haystack +// (NULL is considered a substring of itself only), and return an +// appropriate error message when they fail. +// +// The {needle,haystack}_expr arguments are the stringified +// expressions that generated the two real arguments. +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +// Helper template function for comparing floating-points. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, + const char* actual_expression, + RawType expected, + RawType actual) { + const FloatingPoint lhs(expected), rhs(actual); + + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + ::std::stringstream expected_ss; + expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << expected; + + ::std::stringstream actual_ss; + actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << actual; + + return EqFailure(expected_expression, + actual_expression, + StringStreamToString(&expected_ss), + StringStreamToString(&actual_ss), + false); +} + +// Helper function for implementing ASSERT_NEAR. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// A class that enables one to stream messages to assertion macros +class GTEST_API_ AssertHelper { + public: + // Constructor. + AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message); + ~AssertHelper(); + + // Message assignment is a semantic trick to enable assertion + // streaming; see the GTEST_MESSAGE_ macro below. + void operator=(const Message& message) const; + + private: + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + std::string const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); +}; + +} // namespace internal + +#if GTEST_HAS_PARAM_TEST +// The pure interface class that all value-parameterized tests inherit from. +// A value-parameterized class must inherit from both ::testing::Test and +// ::testing::WithParamInterface. In most cases that just means inheriting +// from ::testing::TestWithParam, but more complicated test hierarchies +// may need to inherit from Test and WithParamInterface at different levels. +// +// This interface has support for accessing the test parameter value via +// the GetParam() method. +// +// Use it with one of the parameter generator defining functions, like Range(), +// Values(), ValuesIn(), Bool(), and Combine(). +// +// class FooTest : public ::testing::TestWithParam { +// protected: +// FooTest() { +// // Can use GetParam() here. +// } +// virtual ~FooTest() { +// // Can use GetParam() here. +// } +// virtual void SetUp() { +// // Can use GetParam() here. +// } +// virtual void TearDown { +// // Can use GetParam() here. +// } +// }; +// TEST_P(FooTest, DoesBar) { +// // Can use GetParam() method here. +// Foo foo; +// ASSERT_TRUE(foo.DoesBar(GetParam())); +// } +// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); + +template +class WithParamInterface { + public: + typedef T ParamType; + virtual ~WithParamInterface() {} + + // The current parameter value. Is also available in the test fixture's + // constructor. This member function is non-static, even though it only + // references static data, to reduce the opportunity for incorrect uses + // like writing 'WithParamInterface::GetParam()' for a test that + // uses a fixture whose parameter type is int. + const ParamType& GetParam() const { + GTEST_CHECK_(parameter_ != NULL) + << "GetParam() can only be called inside a value-parameterized test " + << "-- did you intend to write TEST_P instead of TEST_F?"; + return *parameter_; + } + + private: + // Sets parameter value. The caller is responsible for making sure the value + // remains alive and unchanged throughout the current test. + static void SetParam(const ParamType* parameter) { + parameter_ = parameter; + } + + // Static value used for accessing parameter during a test lifetime. + static const ParamType* parameter_; + + // TestClass must be a subclass of WithParamInterface and Test. + template friend class internal::ParameterizedTestFactory; +}; + +template +const T* WithParamInterface::parameter_ = NULL; + +// Most value-parameterized classes can ignore the existence of +// WithParamInterface, and can just inherit from ::testing::TestWithParam. + +template +class TestWithParam : public Test, public WithParamInterface { +}; + +#endif // GTEST_HAS_PARAM_TEST + +// Macros for indicating success/failure in test code. + +// ADD_FAILURE unconditionally adds a failure to the current test. +// SUCCEED generates a success - it doesn't automatically make the +// current test successful, as a test is only successful when it has +// no failure. +// +// EXPECT_* verifies that a certain condition is satisfied. If not, +// it behaves like ADD_FAILURE. In particular: +// +// EXPECT_TRUE verifies that a Boolean condition is true. +// EXPECT_FALSE verifies that a Boolean condition is false. +// +// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except +// that they will also abort the current function on failure. People +// usually want the fail-fast behavior of FAIL and ASSERT_*, but those +// writing data-driven tests often find themselves using ADD_FAILURE +// and EXPECT_* more. + +// Generates a nonfatal failure with a generic message. +#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") + +// Generates a nonfatal failure at the given source file location with +// a generic message. +#define ADD_FAILURE_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kNonFatalFailure) + +// Generates a fatal failure with a generic message. +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +# define FAIL() GTEST_FAIL() +#endif + +// Generates a success with a generic message. +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +# define SUCCEED() GTEST_SUCCEED() +#endif + +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) + +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. +#define EXPECT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_NONFATAL_FAILURE_) +#define EXPECT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_NONFATAL_FAILURE_) +#define ASSERT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_FATAL_FAILURE_) +#define ASSERT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_FATAL_FAILURE_) + +// Includes the auto-generated header that implements a family of +// generic predicate assertion macros. +// Copyright 2006, 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. + +// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command +// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! +// +// Implements a family of generic predicate assertion macros. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Makes sure this header is not included before gtest.h. +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ + +// This header implements a family of generic predicate assertion +// macros: +// +// ASSERT_PRED_FORMAT1(pred_format, v1) +// ASSERT_PRED_FORMAT2(pred_format, v1, v2) +// ... +// +// where pred_format is a function or functor that takes n (in the +// case of ASSERT_PRED_FORMATn) values and their source expression +// text, and returns a testing::AssertionResult. See the definition +// of ASSERT_EQ in gtest.h for an example. +// +// If you don't care about formatting, you can use the more +// restrictive version: +// +// ASSERT_PRED1(pred, v1) +// ASSERT_PRED2(pred, v1, v2) +// ... +// +// where pred is an n-ary function or functor that returns bool, +// and the values v1, v2, ..., must support the << operator for +// streaming to std::ostream. +// +// We also define the EXPECT_* variations. +// +// For now we only support predicates whose arity is at most 5. +// Please email googletestframework@googlegroups.com if you need +// support for higher arities. + +// GTEST_ASSERT_ is the basic statement to which all of the assertions +// in this file reduce. Don't use this in your code. + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar.failure_message()) + + +// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +template +AssertionResult AssertPred1Helper(const char* pred_text, + const char* e1, + Pred pred, + const T1& v1) { + if (pred(v1)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. +// Don't use this in your code. +#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, v1), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +#define GTEST_PRED1_(pred, v1, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ + #v1, \ + pred, \ + v1), on_failure) + +// Unary predicate assertion macros. +#define EXPECT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +template +AssertionResult AssertPred2Helper(const char* pred_text, + const char* e1, + const char* e2, + Pred pred, + const T1& v1, + const T2& v2) { + if (pred(v1, v2)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. +// Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +#define GTEST_PRED2_(pred, v1, v2, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ + #v1, \ + #v2, \ + pred, \ + v1, \ + v2), on_failure) + +// Binary predicate assertion macros. +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +template +AssertionResult AssertPred3Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3) { + if (pred(v1, v2, v3)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. +// Don't use this in your code. +#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + pred, \ + v1, \ + v2, \ + v3), on_failure) + +// Ternary predicate assertion macros. +#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +template +AssertionResult AssertPred4Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4) { + if (pred(v1, v2, v3, v4)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. +// Don't use this in your code. +#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4), on_failure) + +// 4-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +template +AssertionResult AssertPred5Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + const char* e5, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4, + const T5& v5) { + if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ", " + << e5 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4 + << "\n" << e5 << " evaluates to " << v5; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. +// Don't use this in your code. +#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + #v5, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4, \ + v5), on_failure) + +// 5-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) + + + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Macros for testing equalities and inequalities. +// +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// +// When they are not, Google Test prints both the tested expressions and +// their actual values. The values must be compatible built-in types, +// or you will get a compiler error. By "compatible" we mean that the +// values can be compared by the respective operator. +// +// Note: +// +// 1. It is possible to make a user-defined type work with +// {ASSERT|EXPECT}_??(), but that requires overloading the +// comparison operators and is thus discouraged by the Google C++ +// Usage Guide. Therefore, you are advised to use the +// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are +// equal. +// +// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on +// pointers (in particular, C strings). Therefore, if you use it +// with two C strings, you are testing how their locations in memory +// are related, not how their content is related. To compare two C +// strings by content, use {ASSERT|EXPECT}_STR*(). +// +// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to +// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you +// what the actual value is when it fails, and similarly for the +// other comparisons. +// +// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() +// evaluate their arguments, which is undefined. +// +// 5. These macros evaluate their arguments exactly once. +// +// Examples: +// +// EXPECT_NE(5, Foo()); +// EXPECT_EQ(NULL, a_pointer); +// ASSERT_LT(i, array_size); +// ASSERT_GT(records.size(), 0) << "There is no record left."; + +#define EXPECT_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define EXPECT_NE(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +#define GTEST_ASSERT_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define GTEST_ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define GTEST_ASSERT_LE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define GTEST_ASSERT_LT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define GTEST_ASSERT_GE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define GTEST_ASSERT_GT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of +// ASSERT_XY(), which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_ASSERT_EQ +# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_NE +# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LE +# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LT +# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GE +# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GT +# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) +#endif + +// C-string Comparisons. All tests treat NULL and any non-NULL string +// as different. Two NULLs are equal. +// +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// +// For wide or narrow string objects, you can use the +// {ASSERT|EXPECT}_??() macros. +// +// Don't depend on the order in which the arguments are evaluated, +// which is undefined. +// +// These macros evaluate their arguments exactly once. + +#define EXPECT_STREQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define EXPECT_STRNE(s1, s2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define EXPECT_STRCASEEQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define EXPECT_STRCASENE(s1, s2)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +#define ASSERT_STREQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define ASSERT_STRNE(s1, s2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define ASSERT_STRCASEEQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define ASSERT_STRCASENE(s1, s2)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +// Macros for comparing floating-point numbers. +// +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): +// Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): +// Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): +// Tests that v1 and v2 are within the given distance to each other. +// +// Google Test uses ULP-based comparison to automatically pick a default +// error bound that is appropriate for the operands. See the +// FloatingPoint template class in gtest-internal.h if you are +// interested in the implementation details. + +#define EXPECT_FLOAT_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_DOUBLE_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_FLOAT_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_DOUBLE_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_NEAR(val1, val2, abs_error)\ + EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +#define ASSERT_NEAR(val1, val2, abs_error)\ + ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +// These predicate format functions work on floating-point values, and +// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. +// +// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); + + +#if GTEST_OS_WINDOWS + +// Macros that test for HRESULT failure and success, these are only useful +// on Windows, and rely on Windows SDK macros and APIs to compile. +// +// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) +// +// When expr unexpectedly fails or succeeds, Google Test prints the +// expected result and the actual result with both a human-readable +// string representation of the error, if available, as well as the +// hex result code. +# define EXPECT_HRESULT_SUCCEEDED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define ASSERT_HRESULT_SUCCEEDED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define EXPECT_HRESULT_FAILED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +# define ASSERT_HRESULT_FAILED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +#endif // GTEST_OS_WINDOWS + +// Macros that execute statement and check that it doesn't generate new fatal +// failures in the current thread. +// +// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); +// +// Examples: +// +// EXPECT_NO_FATAL_FAILURE(Process()); +// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; +// +#define ASSERT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) +#define EXPECT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) + +// Causes a trace (including the source file path, the current line +// number, and the given message) to be included in every test failure +// message generated by code in the current scope. The effect is +// undone when the control leaves the current scope. +// +// The message argument can be anything streamable to std::ostream. +// +// In the implementation, we include the current line number as part +// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s +// to appear in the same block - as long as they are on different +// lines. +#define SCOPED_TRACE(message) \ + ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, ::testing::Message() << (message)) + +// Compile-time assertion for type equality. +// StaticAssertTypeEq() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq(); } +// }; +// +// the code: +// +// void Test1() { Foo foo; } +// +// will NOT generate a compiler error, as Foo::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo foo; foo.Bar(); } +// +// to cause a compiler error. +template +bool StaticAssertTypeEq() { + (void)internal::StaticAssertTypeEqHelper(); + return true; +} + +// Defines a test. +// +// The first parameter is the name of the test case, and the second +// parameter is the name of the test within the test case. +// +// The convention is to end the test case name with "Test". For +// example, a test case for the Foo class can be named FooTest. +// +// The user should put his test code between braces after using this +// macro. Example: +// +// TEST(FooTest, InitializesCorrectly) { +// Foo foo; +// EXPECT_TRUE(foo.StatusIsOK()); +// } + +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ + ::testing::Test, ::testing::internal::GetTestTypeId()) + +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif + +// Defines a test that uses a test fixture. +// +// The first parameter is the name of the test fixture class, which +// also doubles as the test case name. The second parameter is the +// name of the test within the test case. +// +// A test fixture class must be declared earlier. The user should put +// his test code between braces after using this macro. Example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { b_.AddElement(3); } +// +// Foo a_; +// Foo b_; +// }; +// +// TEST_F(FooTest, InitializesCorrectly) { +// EXPECT_TRUE(a_.StatusIsOK()); +// } +// +// TEST_F(FooTest, ReturnsElementCountCorrectly) { +// EXPECT_EQ(0, a_.size()); +// EXPECT_EQ(1, b_.size()); +// } + +#define TEST_F(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture, \ + ::testing::internal::GetTypeId()) + +} // namespace testing + +// Use this function in main() to run all tests. It returns 0 if all +// tests are successful, or 1 otherwise. +// +// RUN_ALL_TESTS() should be invoked after the command line has been +// parsed by InitGoogleTest(). +// +// This function was formerly a macro; thus, it is in the global +// namespace and has an all-caps name. +int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_; + +inline int RUN_ALL_TESTS() { + return ::testing::UnitTest::GetInstance()->Run(); +} + +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/VihrevIB/lab1/include/desktop.ini b/VihrevIB/lab1/include/desktop.ini new file mode 100644 index 000000000..d957fd188 --- /dev/null +++ b/VihrevIB/lab1/include/desktop.ini @@ -0,0 +1,4 @@ +[ViewState] +Mode= +Vid= +FolderType=Generic diff --git a/VihrevIB/lab1/include/list.h b/VihrevIB/lab1/include/list.h new file mode 100644 index 000000000..e69de29bb diff --git a/VihrevIB/lab1/include/monom.h b/VihrevIB/lab1/include/monom.h new file mode 100644 index 000000000..e69de29bb diff --git a/VihrevIB/lab1/include/node.h b/VihrevIB/lab1/include/node.h new file mode 100644 index 000000000..e69de29bb diff --git a/VihrevIB/lab1/include/polinom.h b/VihrevIB/lab1/include/polinom.h new file mode 100644 index 000000000..b1dcc9608 --- /dev/null +++ b/VihrevIB/lab1/include/polinom.h @@ -0,0 +1 @@ +//bbb \ No newline at end of file diff --git a/VihrevIB/lab1/samples/main_polinom.cpp b/VihrevIB/lab1/samples/main_polinom.cpp new file mode 100644 index 000000000..cf5604773 --- /dev/null +++ b/VihrevIB/lab1/samples/main_polinom.cpp @@ -0,0 +1,5 @@ +#include "polinom.h" + +void main() +{ +} \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/polinom.sln b/VihrevIB/lab1/sln/polinom/polinom.sln new file mode 100644 index 000000000..955bd3e92 --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/polinom.sln @@ -0,0 +1,61 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.15 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "polinom\polinom.vcxproj", "{75848823-0704-4D2D-94B3-8B8D8DB87437}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polinom_lib", "polinom_lib\polinom_lib.vcxproj", "{38F1E746-652E-4894-8D02-D0D7CFA31ECB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_polinom", "sample_polinom\sample_polinom.vcxproj", "{33024D8B-923D-4484-8B91-233E6E4BC0F5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polinom_test", "polinom_test\polinom_test.vcxproj", "{42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Debug|x64.ActiveCfg = Debug|x64 + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Debug|x64.Build.0 = Debug|x64 + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Debug|x86.ActiveCfg = Debug|Win32 + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Debug|x86.Build.0 = Debug|Win32 + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Release|x64.ActiveCfg = Release|x64 + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Release|x64.Build.0 = Release|x64 + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Release|x86.ActiveCfg = Release|Win32 + {75848823-0704-4D2D-94B3-8B8D8DB87437}.Release|x86.Build.0 = Release|Win32 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x64.ActiveCfg = Debug|x64 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x64.Build.0 = Debug|x64 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x86.ActiveCfg = Debug|Win32 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x86.Build.0 = Debug|Win32 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x64.ActiveCfg = Release|x64 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x64.Build.0 = Release|x64 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x86.ActiveCfg = Release|Win32 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x86.Build.0 = Release|Win32 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Debug|x64.ActiveCfg = Debug|x64 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Debug|x64.Build.0 = Debug|x64 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Debug|x86.ActiveCfg = Debug|Win32 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Debug|x86.Build.0 = Debug|Win32 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Release|x64.ActiveCfg = Release|x64 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Release|x64.Build.0 = Release|x64 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Release|x86.ActiveCfg = Release|Win32 + {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Release|x86.Build.0 = Release|Win32 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Debug|x64.ActiveCfg = Debug|x64 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Debug|x64.Build.0 = Debug|x64 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Debug|x86.ActiveCfg = Debug|Win32 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Debug|x86.Build.0 = Debug|Win32 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Release|x64.ActiveCfg = Release|x64 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Release|x64.Build.0 = Release|x64 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Release|x86.ActiveCfg = Release|Win32 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {49BC6E49-ED2A-45D4-9C34-FEA4E6E0659C} + EndGlobalSection +EndGlobal diff --git a/VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj b/VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj new file mode 100644 index 000000000..affb9c2af --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 15.0 + {75848823-0704-4D2D-94B3-8B8D8DB87437} + Win32Proj + polinom + 10.0.15063.0 + gtest + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj.filters b/VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj.filters new file mode 100644 index 000000000..6ee6db80c --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/polinom/polinom.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Файлы заголовков + + + + + Исходные файлы + + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj b/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj new file mode 100644 index 000000000..d53a9ed69 --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj @@ -0,0 +1,160 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 15.0 + {38F1E746-652E-4894-8D02-D0D7CFA31ECB} + Win32Proj + polinom_lib + 10.0.15063.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + ..\..\..\include;%(AdditionalIncludeDirectories) + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + ..\..\..\include;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj.filters b/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj.filters new file mode 100644 index 000000000..0cf9bc253 --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj new file mode 100644 index 000000000..c6dec7b81 --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D} + Win32Proj + polinom_test + 10.0.15063.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\..\include;..\..\..\gtest + + + Console + true + gtest.lib;polinom_lib.lib;%(AdditionalDependencies) + ..\Debug + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\..\include;..\..\..\gtest + + + Console + true + true + true + gtest.lib;polinom_lib.lib;%(AdditionalDependencies) + ..\Release + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters new file mode 100644 index 000000000..a787ec0c3 --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Исходные файлы + + + Исходные файлы + + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj b/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj new file mode 100644 index 000000000..623f73151 --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {33024D8B-923D-4484-8B91-233E6E4BC0F5} + Win32Proj + sample_polinom + 10.0.15063.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\..\include + + + Console + true + polinom_lib.lib;%(AdditionalDependencies) + ..\Debug + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ..\..\..\include + + + Console + true + true + true + polinom_lib.lib;%(AdditionalDependencies) + ..\Release + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj.filters b/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj.filters new file mode 100644 index 000000000..90c80f854 --- /dev/null +++ b/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Исходные файлы + + + \ No newline at end of file diff --git a/VihrevIB/lab1/src/list.cpp b/VihrevIB/lab1/src/list.cpp new file mode 100644 index 000000000..c1864f735 --- /dev/null +++ b/VihrevIB/lab1/src/list.cpp @@ -0,0 +1,5 @@ +#include "list.h" + +void main() +{ +} \ No newline at end of file diff --git a/VihrevIB/lab1/src/monom.cpp b/VihrevIB/lab1/src/monom.cpp new file mode 100644 index 000000000..3b6d1979c --- /dev/null +++ b/VihrevIB/lab1/src/monom.cpp @@ -0,0 +1,4 @@ +#include "monom.h" +void main() +{ +} \ No newline at end of file diff --git a/VihrevIB/lab1/src/node.cpp b/VihrevIB/lab1/src/node.cpp new file mode 100644 index 000000000..7c44c85b6 --- /dev/null +++ b/VihrevIB/lab1/src/node.cpp @@ -0,0 +1,4 @@ +#include "node.h" +void main() +{ +} \ No newline at end of file diff --git a/VihrevIB/lab1/src/polinom.cpp b/VihrevIB/lab1/src/polinom.cpp new file mode 100644 index 000000000..cf5604773 --- /dev/null +++ b/VihrevIB/lab1/src/polinom.cpp @@ -0,0 +1,5 @@ +#include "polinom.h" + +void main() +{ +} \ No newline at end of file diff --git a/VihrevIB/lab1/test/test_main.cpp b/VihrevIB/lab1/test/test_main.cpp new file mode 100644 index 000000000..3968c279a --- /dev/null +++ b/VihrevIB/lab1/test/test_main.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/VihrevIB/lab1/test/test_polinom.cpp b/VihrevIB/lab1/test/test_polinom.cpp new file mode 100644 index 000000000..4a12f5165 --- /dev/null +++ b/VihrevIB/lab1/test/test_polinom.cpp @@ -0,0 +1,4 @@ +#include +#include "polinom.h" +#include "monom.h" +// \ No newline at end of file From f50170eca94b4f37e0e2dbdf1a7f823557e40314 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Thu, 1 Mar 2018 16:54:15 +0300 Subject: [PATCH 04/16] mofified structure and some h files --- VihrevIB/lab1/include/list.h | 71 +++++++++++++++++++ VihrevIB/lab1/include/monom.h | 11 +++ VihrevIB/lab1/include/node.h | 14 ++++ .../polinom/polinom_test/polinom_test.vcxproj | 4 +- .../polinoms_lib.vcxproj} | 12 +++- .../polinoms_lib.vcxproj.filters} | 14 ++++ .../sample_polinom/sample_polinom.vcxproj | 4 +- VihrevIB/lab1/src/list.cpp | 4 -- VihrevIB/lab1/src/monom.cpp | 3 - VihrevIB/lab1/src/node.cpp | 3 - VihrevIB/lab1/src/polinom.cpp | 4 -- 11 files changed, 123 insertions(+), 21 deletions(-) rename VihrevIB/lab1/sln/polinom/{polinom_lib/polinom_lib.vcxproj => polinoms_lib/polinoms_lib.vcxproj} (94%) rename VihrevIB/lab1/sln/polinom/{polinom_lib/polinom_lib.vcxproj.filters => polinoms_lib/polinoms_lib.vcxproj.filters} (69%) diff --git a/VihrevIB/lab1/include/list.h b/VihrevIB/lab1/include/list.h index e69de29bb..b29334aca 100644 --- a/VihrevIB/lab1/include/list.h +++ b/VihrevIB/lab1/include/list.h @@ -0,0 +1,71 @@ +#include "Node.h" +// // +template +class Rlist +{ +private: + Node* head; +public: + // + Rlist(); + Rlist(const List& list2); + ~Rlist(); + + // + Rlist& operator=(const List& list2); + void InsertToTail(); // + void Insert(); // + Node* GetHead() const { return head; } // + void Clean(); // +}; + +template +Rlist::Rlist() +{ + head = new Node; + head->next = head; +} + +template +Rlist::Rlist(const List& list2) :Rlist() +{ + +} + +template +Rlist::~Rlist() +{ + Clean(); + delete head; +} + +template +Rlist& Rlist::operator=(const List& list2) +{ + +} + +template +void Rlist::InsertToTail() +{ + +} + +template +void Rlist::Insert() +{ + +} + +template +void Rlist::Clean() +{ + Node* curr = head->next; + while (curr != head) + { + Node* temp = curr->next; + delete curr; + curr = temp; + } + head->next = head; +} diff --git a/VihrevIB/lab1/include/monom.h b/VihrevIB/lab1/include/monom.h index e69de29bb..f582b5444 100644 --- a/VihrevIB/lab1/include/monom.h +++ b/VihrevIB/lab1/include/monom.h @@ -0,0 +1,11 @@ +#pragma once +// +class Monom +{ +public: + double coeff; // + unsigned int abc; // + Monom() { coeff = 0; abc = 0; } // + Monom(double COEFF, unsigned int ABC) { coeff = COEFF; abc = ABC; } + +}; \ No newline at end of file diff --git a/VihrevIB/lab1/include/node.h b/VihrevIB/lab1/include/node.h index e69de29bb..a2732ad50 100644 --- a/VihrevIB/lab1/include/node.h +++ b/VihrevIB/lab1/include/node.h @@ -0,0 +1,14 @@ +#pragma once +#include + +template + +class Node +{ +public: + T data; + Node* next; + Node(T d = NULL; Node* n = nullptr) { data = d; next = n; } + Node(Node &Node2) { data = node2.data; next = nullptr; } + bool operator==(const Node& node2) const { return (data == node2.data && next == node2.next); } +}; \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj index c6dec7b81..9b9f28e5d 100644 --- a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj +++ b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj @@ -95,7 +95,7 @@ Console true - gtest.lib;polinom_lib.lib;%(AdditionalDependencies) + gtest.lib;polinoms_lib.lib;%(AdditionalDependencies) ..\Debug @@ -130,7 +130,7 @@ true true true - gtest.lib;polinom_lib.lib;%(AdditionalDependencies) + gtest.lib;polinoms_lib.lib;%(AdditionalDependencies) ..\Release diff --git a/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj b/VihrevIB/lab1/sln/polinom/polinoms_lib/polinoms_lib.vcxproj similarity index 94% rename from VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj rename to VihrevIB/lab1/sln/polinom/polinoms_lib/polinoms_lib.vcxproj index d53a9ed69..9b68729dd 100644 --- a/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj +++ b/VihrevIB/lab1/sln/polinom/polinoms_lib/polinoms_lib.vcxproj @@ -24,11 +24,17 @@ + + + + + + 15.0 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB} + {00CE2F8E-573C-4585-94C4-33994370ADD1} Win32Proj - polinom_lib + polinoms_lib 10.0.15063.0 @@ -96,7 +102,7 @@ Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true - ..\..\..\include;%(AdditionalIncludeDirectories) + ..\..\..\include Windows diff --git a/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj.filters b/VihrevIB/lab1/sln/polinom/polinoms_lib/polinoms_lib.vcxproj.filters similarity index 69% rename from VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj.filters rename to VihrevIB/lab1/sln/polinom/polinoms_lib/polinoms_lib.vcxproj.filters index 0cf9bc253..874a25835 100644 --- a/VihrevIB/lab1/sln/polinom/polinom_lib/polinom_lib.vcxproj.filters +++ b/VihrevIB/lab1/sln/polinom/polinoms_lib/polinoms_lib.vcxproj.filters @@ -24,4 +24,18 @@ Файлы заголовков + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + \ No newline at end of file diff --git a/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj b/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj index 623f73151..bd8b4136e 100644 --- a/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj +++ b/VihrevIB/lab1/sln/polinom/sample_polinom/sample_polinom.vcxproj @@ -95,7 +95,7 @@ Console true - polinom_lib.lib;%(AdditionalDependencies) + polinoms_lib.lib;%(AdditionalDependencies) ..\Debug @@ -130,7 +130,7 @@ true true true - polinom_lib.lib;%(AdditionalDependencies) + polinoms_lib.lib;%(AdditionalDependencies) ..\Release diff --git a/VihrevIB/lab1/src/list.cpp b/VihrevIB/lab1/src/list.cpp index c1864f735..471c2a14b 100644 --- a/VihrevIB/lab1/src/list.cpp +++ b/VihrevIB/lab1/src/list.cpp @@ -1,5 +1 @@ #include "list.h" - -void main() -{ -} \ No newline at end of file diff --git a/VihrevIB/lab1/src/monom.cpp b/VihrevIB/lab1/src/monom.cpp index 3b6d1979c..8e7e2698d 100644 --- a/VihrevIB/lab1/src/monom.cpp +++ b/VihrevIB/lab1/src/monom.cpp @@ -1,4 +1 @@ #include "monom.h" -void main() -{ -} \ No newline at end of file diff --git a/VihrevIB/lab1/src/node.cpp b/VihrevIB/lab1/src/node.cpp index 7c44c85b6..b6347a4d7 100644 --- a/VihrevIB/lab1/src/node.cpp +++ b/VihrevIB/lab1/src/node.cpp @@ -1,4 +1 @@ #include "node.h" -void main() -{ -} \ No newline at end of file diff --git a/VihrevIB/lab1/src/polinom.cpp b/VihrevIB/lab1/src/polinom.cpp index cf5604773..8a9b7da69 100644 --- a/VihrevIB/lab1/src/polinom.cpp +++ b/VihrevIB/lab1/src/polinom.cpp @@ -1,5 +1 @@ #include "polinom.h" - -void main() -{ -} \ No newline at end of file From 2afff0b2d7e2a0f7dd90fad3f05ea520f793c453 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Wed, 21 Mar 2018 22:22:36 +0300 Subject: [PATCH 05/16] finished list and some tests --- VihrevIB/lab1/include/list.h | 105 +++++++++++++++--- VihrevIB/lab1/include/monom.h | 12 +- VihrevIB/lab1/include/node.h | 11 +- VihrevIB/lab1/include/polinom.h | 9 +- VihrevIB/lab1/sln/polinom/polinom.sln | 27 +++-- .../polinom/polinom_test/polinom_test.vcxproj | 1 + .../polinom_test/polinom_test.vcxproj.filters | 3 + VihrevIB/lab1/test/test_Rlist.cpp | 57 ++++++++++ 8 files changed, 192 insertions(+), 33 deletions(-) create mode 100644 VihrevIB/lab1/test/test_Rlist.cpp diff --git a/VihrevIB/lab1/include/list.h b/VihrevIB/lab1/include/list.h index b29334aca..269ab146a 100644 --- a/VihrevIB/lab1/include/list.h +++ b/VihrevIB/lab1/include/list.h @@ -1,35 +1,62 @@ +#pragma once #include "Node.h" // // + template class Rlist { -private: +protected: Node* head; + Node* current; public: // Rlist(); - Rlist(const List& list2); + Rlist(const Rlist& ListToCopy); ~Rlist(); // - Rlist& operator=(const List& list2); - void InsertToTail(); // - void Insert(); // + Rlist& operator=(const Rlist& ListToCopy); + //void InsertToTail(); // + void InsertAfter(Node* N, T Data); + void OrderedInsert(T Data); // + void Clean(); // + + // Node* GetHead() const { return head; } // - void Clean(); // + Node* GetCurr() const{ return current; } + void GetNext() { current = current->next; } + void Reset() { current = head->next; } // + bool IsEnded() { return current->next == head; } + + bool operator==(const Rlist& RLst) const; // + bool operator!=(const Rlist& RLst) const { return !(*this == RLst); } // + + }; template Rlist::Rlist() { head = new Node; + head->data = NULL; head->next = head; + current = head; } template -Rlist::Rlist(const List& list2) :Rlist() +Rlist::Rlist(const Rlist& ListToCopy) { - + Node* TempCurr = ListToCopy.head; + head = new Node(TempCurr->data); + head->next = head; + current = head; + while (TempCurr->next != ListToCopy.head) + { + TempCurr= TempCurr->next; + current->next = new Node(TempCurr->data); + GetNext(); + } + current->next = head; } template @@ -40,32 +67,74 @@ Rlist::~Rlist() } template -Rlist& Rlist::operator=(const List& list2) +Rlist& Rlist::operator=(const Rlist& ListToCopy) { - + Clean(); + Node* TempCurr1 = ListToCopy.head; + Node* TempCurr2 = head; + while (TempCurr1->next != ListToCopy.head) + { + TempCurr1 = TempCurr1->next; + TempCurr2->next = new Node(TempCurr1->data); + TempCurr2 = TempCurr1->next; + } + TempCurr2->next = head; + current = head; + return *this; } template -void Rlist::InsertToTail() +void Rlist::InsertAfter(Node* N, T Data) { - + Node* temp = N->next; + N->next = new Node(Data); + N->next->next = temp; } template -void Rlist::Insert() +void Rlist::OrderedInsert(T Data) { + Node* Temp; + current = head; + + while ( (current->next->data > Data) && current->next != head) + GetNext(); + Temp = current->next; + current->next = new Node(Data); + current->next->next = Temp; } template void Rlist::Clean() { - Node* curr = head->next; - while (curr != head) + Node* TempCurr = head->next; + Node* Temp; + while (TempCurr != head) { - Node* temp = curr->next; - delete curr; - curr = temp; + Temp = TempCurr->next; + delete TempCurr; + TempCurr = Temp; } head->next = head; } + +template +bool Rlist::operator==(const Rlist& RLst) const +{ + bool flag = true; + if (this != &RLst) + { + Node* temp1 = head->next; + Node* temp2 = RLst.head->next; + + while (temp1 != head && temp2 != RLst.head && temp1->data == temp2->data) + { + temp1 = temp1->next; + temp2 = temp2->next; + } + if (temp1->data != temp2->data) + flag = false; + } + return flag; +} \ No newline at end of file diff --git a/VihrevIB/lab1/include/monom.h b/VihrevIB/lab1/include/monom.h index f582b5444..57119e229 100644 --- a/VihrevIB/lab1/include/monom.h +++ b/VihrevIB/lab1/include/monom.h @@ -5,7 +5,15 @@ class Monom public: double coeff; // unsigned int abc; // + Monom() { coeff = 0; abc = 0; } // - Monom(double COEFF, unsigned int ABC) { coeff = COEFF; abc = ABC; } - + Monom(double COEFF = 0 , unsigned int ABC = 0) { coeff = COEFF; abc = ABC;} + + // + bool operator< (const Monom& m) { return (abc (const Monom& m) { return (abc>m.abc); } + bool operator==(const Monom& m) { return (abc = m.abc && coeff == m.coeff); } // + bool operator!=(const Monom& m) { return !(*this == m); } + + Monom& operator=(const Monom& m) { coeff = m.coeff; abc = m.abc; return *this; } }; \ No newline at end of file diff --git a/VihrevIB/lab1/include/node.h b/VihrevIB/lab1/include/node.h index a2732ad50..c322ed469 100644 --- a/VihrevIB/lab1/include/node.h +++ b/VihrevIB/lab1/include/node.h @@ -7,8 +7,15 @@ class Node { public: T data; - Node* next; - Node(T d = NULL; Node* n = nullptr) { data = d; next = n; } + Node* next; + + Node(T DATA = NULL, Node* NEXT = nullptr) { data = DATA; next = NEXT; } Node(Node &Node2) { data = node2.data; next = nullptr; } + + bool operator< (const Node& N) const { return (data (const Node& N) const { return (data>N.data); } +// bool operator== (const Node& N) const { return (data == N.data); } + bool operator!= (const Node& N) const { return !(*this == N); } + bool operator==(const Node& node2) const { return (data == node2.data && next == node2.next); } }; \ No newline at end of file diff --git a/VihrevIB/lab1/include/polinom.h b/VihrevIB/lab1/include/polinom.h index b1dcc9608..b5e2cbca7 100644 --- a/VihrevIB/lab1/include/polinom.h +++ b/VihrevIB/lab1/include/polinom.h @@ -1 +1,8 @@ -//bbb \ No newline at end of file +#pragma once + +#include +#include +#include +#include "monom.h" +#include "list.h" + diff --git a/VihrevIB/lab1/sln/polinom/polinom.sln b/VihrevIB/lab1/sln/polinom/polinom.sln index 955bd3e92..69b8e9ca1 100644 --- a/VihrevIB/lab1/sln/polinom/polinom.sln +++ b/VihrevIB/lab1/sln/polinom/polinom.sln @@ -5,11 +5,18 @@ VisualStudioVersion = 15.0.26730.15 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "polinom\polinom.vcxproj", "{75848823-0704-4D2D-94B3-8B8D8DB87437}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polinom_lib", "polinom_lib\polinom_lib.vcxproj", "{38F1E746-652E-4894-8D02-D0D7CFA31ECB}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_polinom", "sample_polinom\sample_polinom.vcxproj", "{33024D8B-923D-4484-8B91-233E6E4BC0F5}" + ProjectSection(ProjectDependencies) = postProject + {00CE2F8E-573C-4585-94C4-33994370ADD1} = {00CE2F8E-573C-4585-94C4-33994370ADD1} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polinom_test", "polinom_test\polinom_test.vcxproj", "{42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}" + ProjectSection(ProjectDependencies) = postProject + {75848823-0704-4D2D-94B3-8B8D8DB87437} = {75848823-0704-4D2D-94B3-8B8D8DB87437} + {00CE2F8E-573C-4585-94C4-33994370ADD1} = {00CE2F8E-573C-4585-94C4-33994370ADD1} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polinoms_lib", "polinoms_lib\polinoms_lib.vcxproj", "{00CE2F8E-573C-4585-94C4-33994370ADD1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -27,14 +34,6 @@ Global {75848823-0704-4D2D-94B3-8B8D8DB87437}.Release|x64.Build.0 = Release|x64 {75848823-0704-4D2D-94B3-8B8D8DB87437}.Release|x86.ActiveCfg = Release|Win32 {75848823-0704-4D2D-94B3-8B8D8DB87437}.Release|x86.Build.0 = Release|Win32 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x64.ActiveCfg = Debug|x64 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x64.Build.0 = Debug|x64 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x86.ActiveCfg = Debug|Win32 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Debug|x86.Build.0 = Debug|Win32 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x64.ActiveCfg = Release|x64 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x64.Build.0 = Release|x64 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x86.ActiveCfg = Release|Win32 - {38F1E746-652E-4894-8D02-D0D7CFA31ECB}.Release|x86.Build.0 = Release|Win32 {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Debug|x64.ActiveCfg = Debug|x64 {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Debug|x64.Build.0 = Debug|x64 {33024D8B-923D-4484-8B91-233E6E4BC0F5}.Debug|x86.ActiveCfg = Debug|Win32 @@ -51,6 +50,14 @@ Global {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Release|x64.Build.0 = Release|x64 {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Release|x86.ActiveCfg = Release|Win32 {42132143-D3D7-4E74-9A86-AEBFE1CF9B3D}.Release|x86.Build.0 = Release|Win32 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Debug|x64.ActiveCfg = Debug|x64 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Debug|x64.Build.0 = Debug|x64 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Debug|x86.ActiveCfg = Debug|Win32 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Debug|x86.Build.0 = Debug|Win32 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Release|x64.ActiveCfg = Release|x64 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Release|x64.Build.0 = Release|x64 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Release|x86.ActiveCfg = Release|Win32 + {00CE2F8E-573C-4585-94C4-33994370ADD1}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj index 9b9f28e5d..45cf541ea 100644 --- a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj +++ b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj @@ -155,6 +155,7 @@ + diff --git a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters index a787ec0c3..2e56903b6 100644 --- a/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters +++ b/VihrevIB/lab1/sln/polinom/polinom_test/polinom_test.vcxproj.filters @@ -13,5 +13,8 @@ Исходные файлы + + Исходные файлы + \ No newline at end of file diff --git a/VihrevIB/lab1/test/test_Rlist.cpp b/VihrevIB/lab1/test/test_Rlist.cpp new file mode 100644 index 000000000..baa6bbd72 --- /dev/null +++ b/VihrevIB/lab1/test/test_Rlist.cpp @@ -0,0 +1,57 @@ +#include +#include "list.h" + + +class TestList : public testing::Test +{ +protected: + Rlist list1; + Rlist list2; +public: + TestList() + { + list2.OrderedInsert(1); + list2.OrderedInsert(2); + list2.OrderedInsert(3); + }; + ~TestList() {}; +}; + +TEST_F(TestList, can_create_list) +{ + ASSERT_NO_THROW(Rlist list); +} + +TEST_F(TestList, empty_list_is_working) +{ + EXPECT_EQ(true, list1.IsEnded()); +} + +TEST_F(TestList, can_copy_empty_list) +{ + ASSERT_NO_THROW(Rlist list(list1)); +} + +TEST_F(TestList, copied_empty_list_is_correct) +{ + Rlist list(list1); + EXPECT_EQ(true, list.IsEnded()); + EXPECT_NE(list1.GetCurr(), list.GetCurr()); +} + +TEST_F(TestList, can_assign_empty_list) +{ + ASSERT_NO_THROW(Rlist list = list1); +} + +TEST_F(TestList, assigned_empty_list_is_correct) +{ + Rlist list = list1; + EXPECT_EQ(true, list.IsEnded()); + EXPECT_NE(list1.GetCurr(), list.GetCurr()); +} + +TEST_F(TestList, can_insert_in_ordered_empty_list) +{ + ASSERT_NO_THROW(list1.OrderedInsert(5)); +} From 1d10a99a186d58ad07cbdce6d423e9c605c2209c Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Wed, 28 Mar 2018 21:05:27 +0300 Subject: [PATCH 06/16] done polinom.h --- VihrevIB/lab1/include/list.h | 4 +-- VihrevIB/lab1/include/monom.h | 2 +- VihrevIB/lab1/include/node.h | 2 +- VihrevIB/lab1/include/polinom.h | 38 ++++++++++++++++++++++++-- VihrevIB/lab1/samples/main_polinom.cpp | 4 --- VihrevIB/lab1/src/polinom.cpp | 1 + 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/VihrevIB/lab1/include/list.h b/VihrevIB/lab1/include/list.h index 269ab146a..319d2af84 100644 --- a/VihrevIB/lab1/include/list.h +++ b/VihrevIB/lab1/include/list.h @@ -26,7 +26,7 @@ class Rlist Node* GetCurr() const{ return current; } void GetNext() { current = current->next; } void Reset() { current = head->next; } // - bool IsEnded() { return current->next == head; } + bool IsEnded() { return current == head; } bool operator==(const Rlist& RLst) const; // bool operator!=(const Rlist& RLst) const { return !(*this == RLst); } // @@ -76,7 +76,7 @@ Rlist& Rlist::operator=(const Rlist& ListToCopy) { TempCurr1 = TempCurr1->next; TempCurr2->next = new Node(TempCurr1->data); - TempCurr2 = TempCurr1->next; + TempCurr2 = TempCurr2->next; } TempCurr2->next = head; current = head; diff --git a/VihrevIB/lab1/include/monom.h b/VihrevIB/lab1/include/monom.h index 57119e229..69ede9920 100644 --- a/VihrevIB/lab1/include/monom.h +++ b/VihrevIB/lab1/include/monom.h @@ -6,7 +6,7 @@ class Monom double coeff; // unsigned int abc; // - Monom() { coeff = 0; abc = 0; } // + //Monom() { coeff = 0; abc = 0; } // Monom(double COEFF = 0 , unsigned int ABC = 0) { coeff = COEFF; abc = ABC;} // diff --git a/VihrevIB/lab1/include/node.h b/VihrevIB/lab1/include/node.h index c322ed469..96e17b6f6 100644 --- a/VihrevIB/lab1/include/node.h +++ b/VihrevIB/lab1/include/node.h @@ -14,8 +14,8 @@ class Node bool operator< (const Node& N) const { return (data (const Node& N) const { return (data>N.data); } -// bool operator== (const Node& N) const { return (data == N.data); } bool operator!= (const Node& N) const { return !(*this == N); } + //bool operator== (const Node& N) const { return (data == N.data); } bool operator==(const Node& node2) const { return (data == node2.data && next == node2.next); } }; \ No newline at end of file diff --git a/VihrevIB/lab1/include/polinom.h b/VihrevIB/lab1/include/polinom.h index b5e2cbca7..7e7e84815 100644 --- a/VihrevIB/lab1/include/polinom.h +++ b/VihrevIB/lab1/include/polinom.h @@ -2,7 +2,41 @@ #include #include -#include -#include "monom.h" +#include "Monom.h" #include "list.h" +using std::string; +using std::ostream; +using std::cout; +using std::endl; + +class Polinom { + +private: + + Rlist Pol_List; + +public: + + // + Polinom(const string expr); + Polinom(const Polinom& POL); + + // + Polinom operator+ (const Polinom&) const; + Polinom operator- (const Polinom& POL) const { return (*this + POL*(-1)); } + Polinom operator* (const Polinom&) const;// + Polinom operator* (const double) const; // + + + + bool operator== (const Polinom& POL) const { return Pol_List == POL.Pol_List; } + bool operator!= (const Polinom& POL) const { return Pol_List != POL.Pol_List; } + + Rlist FindSimilar (Rlist POL); // + Rlist Parsing (const string);// + + + friend Polinom operator* (const double CONST , const Polinom& POL) { return POL*CONST; } // + friend ostream& operator<< (ostream& os, const Polinom&); +}; \ No newline at end of file diff --git a/VihrevIB/lab1/samples/main_polinom.cpp b/VihrevIB/lab1/samples/main_polinom.cpp index cf5604773..8a9b7da69 100644 --- a/VihrevIB/lab1/samples/main_polinom.cpp +++ b/VihrevIB/lab1/samples/main_polinom.cpp @@ -1,5 +1 @@ #include "polinom.h" - -void main() -{ -} \ No newline at end of file diff --git a/VihrevIB/lab1/src/polinom.cpp b/VihrevIB/lab1/src/polinom.cpp index 8a9b7da69..feb9e1702 100644 --- a/VihrevIB/lab1/src/polinom.cpp +++ b/VihrevIB/lab1/src/polinom.cpp @@ -1 +1,2 @@ #include "polinom.h" + From b02d8200acf058fef8fa6d496a526a210121769b Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Wed, 28 Mar 2018 22:27:56 +0300 Subject: [PATCH 07/16] some functions in polinom.cpp --- VihrevIB/lab1/include/list.h | 10 +++---- VihrevIB/lab1/include/polinom.h | 13 +++++---- VihrevIB/lab1/samples/main_polinom.cpp | 11 ++++++++ VihrevIB/lab1/src/polinom.cpp | 38 ++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/VihrevIB/lab1/include/list.h b/VihrevIB/lab1/include/list.h index 319d2af84..a5996bbb3 100644 --- a/VihrevIB/lab1/include/list.h +++ b/VihrevIB/lab1/include/list.h @@ -22,11 +22,11 @@ class Rlist void Clean(); // // - Node* GetHead() const { return head; } // - Node* GetCurr() const{ return current; } - void GetNext() { current = current->next; } - void Reset() { current = head->next; } // - bool IsEnded() { return current == head; } + Node* GetHead() const { return head; } // + Node* GetCurr() const{ return current; } // + void GetNext() { current = current->next; }// + void Reset() { current = head->next; } // + bool IsEnded() { return current == head; } // bool operator==(const Rlist& RLst) const; // bool operator!=(const Rlist& RLst) const { return !(*this == RLst); } // diff --git a/VihrevIB/lab1/include/polinom.h b/VihrevIB/lab1/include/polinom.h index 7e7e84815..bb4ef8bec 100644 --- a/VihrevIB/lab1/include/polinom.h +++ b/VihrevIB/lab1/include/polinom.h @@ -19,14 +19,15 @@ class Polinom { public: // - Polinom(const string expr); - Polinom(const Polinom& POL); + Polinom(const string Line = "" ); + Polinom(Rlist &P2) : Pol_List(P2) {} + Polinom(const Polinom& POL) : Pol_List(POL.Pol_List) {}; // // Polinom operator+ (const Polinom&) const; Polinom operator- (const Polinom& POL) const { return (*this + POL*(-1)); } - Polinom operator* (const Polinom&) const;// - Polinom operator* (const double) const; // + Polinom operator* (const Polinom& POL) const;// + Polinom operator* (const double c) const; // @@ -34,9 +35,9 @@ class Polinom { bool operator!= (const Polinom& POL) const { return Pol_List != POL.Pol_List; } Rlist FindSimilar (Rlist POL); // - Rlist Parsing (const string);// + Rlist Parsing (const string Line);// - friend Polinom operator* (const double CONST , const Polinom& POL) { return POL*CONST; } // + friend Polinom operator* (const double C , const Polinom& POL) { return POL*C; } // friend ostream& operator<< (ostream& os, const Polinom&); }; \ No newline at end of file diff --git a/VihrevIB/lab1/samples/main_polinom.cpp b/VihrevIB/lab1/samples/main_polinom.cpp index 8a9b7da69..0f12ea1d0 100644 --- a/VihrevIB/lab1/samples/main_polinom.cpp +++ b/VihrevIB/lab1/samples/main_polinom.cpp @@ -1 +1,12 @@ #include "polinom.h" + +int main() +{ + Polinom A("11xyz+11yxz"); + Polinom B("11xyz"); + + //cout << A << endl; + //cout << B; + + return 0; +} \ No newline at end of file diff --git a/VihrevIB/lab1/src/polinom.cpp b/VihrevIB/lab1/src/polinom.cpp index feb9e1702..299d48a51 100644 --- a/VihrevIB/lab1/src/polinom.cpp +++ b/VihrevIB/lab1/src/polinom.cpp @@ -1,2 +1,40 @@ #include "polinom.h" + +const string xyz = "xyz"; +//............................................................................ +Polinom::Polinom(const string Line) +{ + Pol_List = Parsing(Line); + Pol_List = FindSimilar(Pol_List); +} +//............................................................................ +Rlist Polinom::FindSimilar(Rlist POL) +{ + Rlist res; + POL.Reset(); // current + res.Reset(); + Node tmp(POL.GetCurr()->data); // data urrent & + + while (!(POL.IsEnded())) + { + if (POL.GetCurr()->data.abc == POL.GetCurr()->next->data.abc) + { + tmp.data.coeff += POL.GetCurr()->next->data.coeff; + tmp.data.abc = POL.GetCurr()->next->data.abc; + } + else + { + if (tmp.data.coeff) + { + res.InsertAfter(res.GetCurr(), tmp.data); + res.GetNext(); + } + tmp.data.coeff = POL.GetCurr()->next->data.coeff; + tmp.data.abc = POL.GetCurr()->next->data.abc; + } + POL.GetNext(); + } + return res; +} +//............................................................................ \ No newline at end of file From 618c3be18cb5ee3129be2ff22eb41efd6b7f199c Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Mon, 16 Apr 2018 22:05:19 +0300 Subject: [PATCH 08/16] Done + Otchet --- VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx | Bin 0 -> 108364 bytes VihrevIB/lab1/include/list.h | 40 ++-- VihrevIB/lab1/include/monom.h | 10 +- VihrevIB/lab1/include/node.h | 6 +- VihrevIB/lab1/include/polinom.h | 30 +-- VihrevIB/lab1/samples/main_polinom.cpp | 48 +++- VihrevIB/lab1/src/polinom.cpp | 288 +++++++++++++++++++++-- VihrevIB/lab1/test/test_Rlist.cpp | 167 ++++++++++--- VihrevIB/lab1/test/test_polinom.cpp | 145 +++++++++++- 9 files changed, 628 insertions(+), 106 deletions(-) create mode 100644 VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx diff --git a/VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx b/VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx new file mode 100644 index 0000000000000000000000000000000000000000..c549d88dba3cac734f7389437cb08ce361bf6cee GIT binary patch literal 108364 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 ItQY|Q2V(64IRF3v literal 0 HcmV?d00001 diff --git a/VihrevIB/lab1/include/list.h b/VihrevIB/lab1/include/list.h index a5996bbb3..629ccd5f4 100644 --- a/VihrevIB/lab1/include/list.h +++ b/VihrevIB/lab1/include/list.h @@ -16,24 +16,24 @@ class Rlist // Rlist& operator=(const Rlist& ListToCopy); - //void InsertToTail(); // void InsertAfter(Node* N, T Data); void OrderedInsert(T Data); // void Clean(); // // - Node* GetHead() const { return head; } // - Node* GetCurr() const{ return current; } // - void GetNext() { current = current->next; }// + Node* GetCurr() const { return current; } // + void SetNext() { current = current->next; }// void Reset() { current = head->next; } // - bool IsEnded() { return current == head; } // - - bool operator==(const Rlist& RLst) const; // - bool operator!=(const Rlist& RLst) const { return !(*this == RLst); } // + bool IsEnd() const { return current == head; } // + + // + bool operator==(const Rlist& RLst) const; + bool operator!=(const Rlist& RLst) const { return !(*this == RLst); } }; +// ............................................................................ template Rlist::Rlist() { @@ -42,7 +42,7 @@ Rlist::Rlist() head->next = head; current = head; } - +// ............................................................................ template Rlist::Rlist(const Rlist& ListToCopy) { @@ -54,11 +54,11 @@ Rlist::Rlist(const Rlist& ListToCopy) { TempCurr= TempCurr->next; current->next = new Node(TempCurr->data); - GetNext(); + SetNext(); } current->next = head; } - +// ............................................................................ template Rlist::~Rlist() { @@ -72,6 +72,7 @@ Rlist& Rlist::operator=(const Rlist& ListToCopy) Clean(); Node* TempCurr1 = ListToCopy.head; Node* TempCurr2 = head; + while (TempCurr1->next != ListToCopy.head) { TempCurr1 = TempCurr1->next; @@ -82,7 +83,7 @@ Rlist& Rlist::operator=(const Rlist& ListToCopy) current = head; return *this; } - +// ............................................................................ template void Rlist::InsertAfter(Node* N, T Data) { @@ -90,7 +91,7 @@ void Rlist::InsertAfter(Node* N, T Data) N->next = new Node(Data); N->next->next = temp; } - +// ............................................................................ template void Rlist::OrderedInsert(T Data) { @@ -98,13 +99,13 @@ void Rlist::OrderedInsert(T Data) current = head; while ( (current->next->data > Data) && current->next != head) - GetNext(); + SetNext(); - Temp = current->next; + Temp = current->next; current->next = new Node(Data); current->next->next = Temp; } - +// ............................................................................ template void Rlist::Clean() { @@ -118,7 +119,7 @@ void Rlist::Clean() } head->next = head; } - +// ............................................................................ template bool Rlist::operator==(const Rlist& RLst) const { @@ -133,8 +134,9 @@ bool Rlist::operator==(const Rlist& RLst) const temp1 = temp1->next; temp2 = temp2->next; } - if (temp1->data != temp2->data) + if (temp1 != head || temp2 != RLst.head) flag = false; } return flag; -} \ No newline at end of file +} +// ............................................................................ \ No newline at end of file diff --git a/VihrevIB/lab1/include/monom.h b/VihrevIB/lab1/include/monom.h index 69ede9920..fe1518704 100644 --- a/VihrevIB/lab1/include/monom.h +++ b/VihrevIB/lab1/include/monom.h @@ -6,14 +6,14 @@ class Monom double coeff; // unsigned int abc; // - //Monom() { coeff = 0; abc = 0; } // + // Monom(double COEFF = 0 , unsigned int ABC = 0) { coeff = COEFF; abc = ABC;} // - bool operator< (const Monom& m) { return (abc (const Monom& m) { return (abc>m.abc); } - bool operator==(const Monom& m) { return (abc = m.abc && coeff == m.coeff); } // - bool operator!=(const Monom& m) { return !(*this == m); } + bool operator< (const Monom& m) const { return (abc (const Monom& m) const { return (abc>m.abc); } + bool operator==(const Monom& m) const { return (abc == m.abc && coeff == m.coeff); } // + bool operator!=(const Monom& m) const { return !(*this == m); } Monom& operator=(const Monom& m) { coeff = m.coeff; abc = m.abc; return *this; } }; \ No newline at end of file diff --git a/VihrevIB/lab1/include/node.h b/VihrevIB/lab1/include/node.h index 96e17b6f6..b33cd87ab 100644 --- a/VihrevIB/lab1/include/node.h +++ b/VihrevIB/lab1/include/node.h @@ -11,11 +11,9 @@ class Node Node(T DATA = NULL, Node* NEXT = nullptr) { data = DATA; next = NEXT; } Node(Node &Node2) { data = node2.data; next = nullptr; } - + // bool operator< (const Node& N) const { return (data (const Node& N) const { return (data>N.data); } bool operator!= (const Node& N) const { return !(*this == N); } - - //bool operator== (const Node& N) const { return (data == N.data); } - bool operator==(const Node& node2) const { return (data == node2.data && next == node2.next); } + bool operator==(const Node& N) const { return (data == N.data && next == N.next); } }; \ No newline at end of file diff --git a/VihrevIB/lab1/include/polinom.h b/VihrevIB/lab1/include/polinom.h index bb4ef8bec..0de3835a1 100644 --- a/VihrevIB/lab1/include/polinom.h +++ b/VihrevIB/lab1/include/polinom.h @@ -2,41 +2,43 @@ #include #include +#include #include "Monom.h" #include "list.h" + using std::string; using std::ostream; using std::cout; +using std::cin; using std::endl; class Polinom { -private: +protected: - Rlist Pol_List; + Rlist Monoms; + string name; + // + Rlist Simplify(Rlist POL); // + Rlist Parsing(const string Line);// public: // - Polinom(const string Line = "" ); - Polinom(Rlist &P2) : Pol_List(P2) {} - Polinom(const Polinom& POL) : Pol_List(POL.Pol_List) {}; // + Polinom(const string Line = "" ); // + Polinom(const Monom m) { Monoms.InsertAfter(Monoms.GetCurr(),m); }// : + Polinom(const Rlist &P2) : Monoms(P2) {}; // : + Polinom(const Polinom& POL) : Monoms(POL.Monoms) {}; // // Polinom operator+ (const Polinom&) const; - Polinom operator- (const Polinom& POL) const { return (*this + POL*(-1)); } + Polinom operator- (const Polinom& POL) const { return (*this + POL*(-1.0)); } Polinom operator* (const Polinom& POL) const;// Polinom operator* (const double c) const; // - - - bool operator== (const Polinom& POL) const { return Pol_List == POL.Pol_List; } - bool operator!= (const Polinom& POL) const { return Pol_List != POL.Pol_List; } - - Rlist FindSimilar (Rlist POL); // - Rlist Parsing (const string Line);// - + bool operator== (const Polinom& POL) const { return Monoms == POL.Monoms; } + bool operator!= (const Polinom& POL) const { return Monoms != POL.Monoms; } friend Polinom operator* (const double C , const Polinom& POL) { return POL*C; } // friend ostream& operator<< (ostream& os, const Polinom&); diff --git a/VihrevIB/lab1/samples/main_polinom.cpp b/VihrevIB/lab1/samples/main_polinom.cpp index 0f12ea1d0..d58bf5f1a 100644 --- a/VihrevIB/lab1/samples/main_polinom.cpp +++ b/VihrevIB/lab1/samples/main_polinom.cpp @@ -1,12 +1,48 @@ #include "polinom.h" - +#include +#include int main() { - Polinom A("11xyz+11yxz"); - Polinom B("11xyz"); - - //cout << A << endl; - //cout << B; + char ch = 0; + string exp1; + string exp2; + system("color F0"); + + cout << "Use only: " << endl << " letters x,y,z" << endl << " numbers 0...9" << endl << " symblols . ,^ , +, -" << endl ; + + while (ch != 27) + { + cout << "Enter first polinom: " << endl; + cin >> exp1; + Polinom A(exp1); + cout << "A = " <> exp2; + Polinom B(exp2); + cout <<"B = " << B << endl << "-----------------------------------------------------------------------------" << endl; + Polinom res = A + B; + cout << " A + B = "; + cout << res << endl; + + res = A - B; + cout << " A - B = "; + cout << res << endl; + + res = B - A; + cout << " B - A = "; + cout << res << endl; + + res = A * B; + cout << " A * B = "; + cout << res << endl; + cout << "-----------------------------------------------------------------------------" << endl; + cout << "Esc to exit " << endl; + + ch = _getch(); + } + + return 0; } \ No newline at end of file diff --git a/VihrevIB/lab1/src/polinom.cpp b/VihrevIB/lab1/src/polinom.cpp index 299d48a51..8c6cde772 100644 --- a/VihrevIB/lab1/src/polinom.cpp +++ b/VihrevIB/lab1/src/polinom.cpp @@ -1,40 +1,286 @@ #include "polinom.h" - - -const string xyz = "xyz"; //............................................................................ Polinom::Polinom(const string Line) -{ - Pol_List = Parsing(Line); - Pol_List = FindSimilar(Pol_List); +{ + Monoms = Parsing(Line); + Monoms = Simplify(Monoms); } //............................................................................ -Rlist Polinom::FindSimilar(Rlist POL) +Rlist Polinom::Simplify(Rlist POL) { Rlist res; - POL.Reset(); // current + POL.Reset(); // current res.Reset(); - Node tmp(POL.GetCurr()->data); // data urrent & - - while (!(POL.IsEnded())) + Monom tmp; + // , - + Node* p = POL.GetCurr(); + POL.SetNext(); + + if (!(POL.IsEnd())) { - if (POL.GetCurr()->data.abc == POL.GetCurr()->next->data.abc) + POL.Reset(); + + while (!(POL.IsEnd())) { - tmp.data.coeff += POL.GetCurr()->next->data.coeff; - tmp.data.abc = POL.GetCurr()->next->data.abc; + tmp.coeff = POL.GetCurr()->data.coeff; + tmp.abc = POL.GetCurr()->data.abc; + + while ((POL.GetCurr()->data.abc == POL.GetCurr()->next->data.abc) && !(POL.IsEnd())) + { + tmp.coeff += POL.GetCurr()->next->data.coeff; + POL.SetNext(); + } + + if (tmp.coeff) + { + res.OrderedInsert(tmp); + res.SetNext(); + } + + if (!(POL.IsEnd())) + POL.SetNext(); + } + res.Reset(); + // 0 + if (res.GetCurr()->data.abc == 0 && res.GetCurr()->data.coeff == 0) + res.InsertAfter(res.GetCurr(), NULL); + } + else + res = POL; + + return res; +} + +//............................................................................ +Polinom Polinom::operator+(const Polinom& POL) const +{ + Polinom res; + Rlist P1 = Monoms; + Rlist P2 = POL.Monoms; + + P1.Reset(); + P2.Reset(); + + res.Monoms.Reset(); + // + while (!P1.IsEnd() && !P2.IsEnd()) + { + if ((P1.GetCurr()->data > P2.GetCurr()->data) && P1.GetCurr()->data.coeff) // + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P1.GetCurr()->data); + P1.SetNext(); + res.Monoms.SetNext(); } else + if ((P1.GetCurr()->data < P2.GetCurr()->data) && P2.GetCurr()->data.coeff) + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P2.GetCurr()->data); + P2.SetNext(); + res.Monoms.SetNext(); + } + else // + { + double cf = P1.GetCurr()->data.coeff + P2.GetCurr()->data.coeff; + + if (cf) // + { + Monom temp(cf, P1.GetCurr()->data.abc); + res.Monoms.InsertAfter(res.Monoms.GetCurr(), temp); + + res.Monoms.SetNext(); + } + + P1.SetNext(); + P2.SetNext(); + } + } + // + while (!P1.IsEnd()) + { + if (P1.GetCurr()->data.coeff) + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P1.GetCurr()->data); + res.Monoms.SetNext(); + } + P1.SetNext(); + } + + while (!P2.IsEnd()) + { + if (P2.GetCurr()->data.coeff) + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P2.GetCurr()->data); + res.Monoms.SetNext(); + } + P2.SetNext(); + } + res.Monoms.Reset(); + // 0 + if (res.Monoms.GetCurr()->data.abc == 0 && res.Monoms.GetCurr()->data.coeff == 0) + res.Monoms.InsertAfter(res.Monoms.GetCurr(), NULL); + + return res; +} +//............................................................................ + +Rlist Polinom::Parsing(const string Line) +{ + Rlist List; + string SMonom, SPol = Line; + int k = 1; + int d[] = { 100,10,1 }; + + while (SPol.length()) + { + Monom tmp; + k = 1; + // + while (SPol[k] != '-' && SPol[k] != '+' && k < SPol.length()) + k++; + + SMonom = SPol.substr(0, k); + SPol.erase(0, k); + // + - + if (SMonom[0] == '-') { - if (tmp.data.coeff) + tmp.coeff = -1; + SMonom.erase(0, 1); + + } + else + { + tmp.coeff = 1; + if (SMonom[0] == '+') + SMonom.erase(0, 1); + } + // + if (isdigit(SMonom[0])) + { + k = 0; + while (isdigit(SMonom[k]) || SMonom[k] == '.' ) + k++; + tmp.coeff *= std::stod(SMonom.substr(0, k)); + SMonom.erase(0, k); + } + // + for (int i = 0; i < 3; i++) + { + int pos = SMonom.find("xyz"[i]); + if (pos != -1) + if (SMonom[pos + 1] == '^') + { + tmp.abc += d[i] * std::stoi(SMonom.substr(pos + 2, 1)); + } + else + tmp.abc += d[i]; + } + + List.OrderedInsert(tmp); + } + return List; +} +//............................................................................ + +Polinom Polinom::operator*(const double c) const +{ + + Polinom res; + + if (c) + { + res = *this; + res.Monoms.Reset(); + while (!(res.Monoms.IsEnd())) + { + res.Monoms.GetCurr()->data.coeff *= c; + res.Monoms.SetNext(); + } + } + else + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), NULL); + } + + return res; +} +//............................................................................ +Polinom Polinom::operator*(const Polinom& POL) const { + + Polinom res; + Polinom P1 = Monoms, P2 = POL; + int abc; + double coeff; + + P1.Monoms.Reset(); + P2.Monoms.Reset(); + + while (!P2.Monoms.IsEnd()) + { + Monom tmp; + P1.Monoms.Reset(); + while (!P1.Monoms.IsEnd()) + { + abc = P1.Monoms.GetCurr()->data.abc; + coeff = P1.Monoms.GetCurr()->data.coeff; + tmp = P2.Monoms.GetCurr()->data; + if ( (tmp.abc % 10 + abc % 10) < 10 && (tmp.abc /10 % 10 + abc / 10 % 10) < 10 && (tmp.abc / 100 + abc / 100 ) <10) + { + tmp.coeff *= coeff; + tmp.abc += abc; + res = res + tmp; + } + else { - res.InsertAfter(res.GetCurr(), tmp.data); - res.GetNext(); + throw "Degree>10"; } - tmp.data.coeff = POL.GetCurr()->next->data.coeff; - tmp.data.abc = POL.GetCurr()->next->data.abc; + P1.Monoms.SetNext(); } - POL.GetNext(); + P2.Monoms.SetNext(); } return res; } -//............................................................................ \ No newline at end of file +//............................................................................ + +ostream& operator<<(ostream& os, const Polinom& POL) +{ + Polinom tmpPol = POL; + tmpPol.Monoms.Reset(); + + Node* FirstNode =tmpPol.Monoms.GetCurr(); // + Node tmpMon; + while (!(tmpPol.Monoms.IsEnd())) + { + tmpMon = tmpPol.Monoms.GetCurr()->data; + if (tmpMon.data.coeff > 0 && tmpPol.Monoms.GetCurr() != FirstNode) + os << '+'; + if (tmpMon.data.coeff != 1 && tmpMon.data.coeff != -1 && tmpMon.data.coeff !=0) + os << tmpMon.data.coeff; + else + if (tmpMon.data.coeff == -1 && tmpMon.data.abc != 0) + os << '-'; + else + if ((tmpMon.data.coeff == 1 || tmpMon.data.coeff == -1 )&& tmpMon.data.abc == 0) + os << tmpMon.data.coeff; + int d[3] = { 100,10,1 }; + for (int i = 0; i < 3; i++) + { + if (tmpMon.data.abc / d[i] % 10 != 0) + { + os << "xyz"[i]; + if (tmpMon.data.abc / d[i] % 10 != 1) + os << '^' << tmpMon.data.abc / d[i] % 10; + } + } + tmpPol.Monoms.SetNext(); + } + tmpPol.Monoms.Reset(); + + if (tmpPol.Monoms.GetCurr()->data.abc == 0 && tmpPol.Monoms.GetCurr()->data.coeff == 0 && !(tmpPol.Monoms.IsEnd())) + { + os << "0"; + } + return os; +} + +// ............................................................................ + diff --git a/VihrevIB/lab1/test/test_Rlist.cpp b/VihrevIB/lab1/test/test_Rlist.cpp index baa6bbd72..605cb1d55 100644 --- a/VihrevIB/lab1/test/test_Rlist.cpp +++ b/VihrevIB/lab1/test/test_Rlist.cpp @@ -1,57 +1,156 @@ #include +#include "node.h" #include "list.h" - -class TestList : public testing::Test +// +//............................................................................ +TEST(Node, can_create_node) +{ + ASSERT_NO_THROW(Node N); +} +//............................................................................ +TEST(Rlist, can_create_Rlist) +{ + ASSERT_NO_THROW(Rlist L); +} +//............................................................................ +class EmptyRlist : public testing::Test { protected: - Rlist list1; - Rlist list2; + Rlist L; public: - TestList() - { - list2.OrderedInsert(1); - list2.OrderedInsert(2); - list2.OrderedInsert(3); - }; - ~TestList() {}; + EmptyRlist() {}; + ~EmptyRlist() {}; }; - -TEST_F(TestList, can_create_list) +//............................................................................ +TEST_F(EmptyRlist, new_list_is_empty) { - ASSERT_NO_THROW(Rlist list); + EXPECT_EQ(NULL, L.GetCurr()->data); } - -TEST_F(TestList, empty_list_is_working) +//............................................................................ +TEST_F(EmptyRlist, can_copy_empty_list) { - EXPECT_EQ(true, list1.IsEnded()); + ASSERT_NO_THROW(Rlist L2(L)); } - -TEST_F(TestList, can_copy_empty_list) +//............................................................................ +TEST_F(EmptyRlist, copied_empty_list_is_correct) { - ASSERT_NO_THROW(Rlist list(list1)); + Rlist L2(L); + EXPECT_EQ(NULL, L2.GetCurr()->data); } - -TEST_F(TestList, copied_empty_list_is_correct) +//............................................................................ +TEST_F(EmptyRlist, two_empty_lists_are_eq) { - Rlist list(list1); - EXPECT_EQ(true, list.IsEnded()); - EXPECT_NE(list1.GetCurr(), list.GetCurr()); + Rlist L2; + EXPECT_EQ(true, L == L2); } - -TEST_F(TestList, can_assign_empty_list) +//............................................................................ +TEST_F(EmptyRlist, can_assign_two_empty_lists) { - ASSERT_NO_THROW(Rlist list = list1); + Rlist L2; + ASSERT_NO_THROW(L = L2); +} +//............................................................................ +TEST_F(EmptyRlist, can_assign_empty_list_to_itself) +{ + ASSERT_NO_THROW(L = L); +} +//............................................................................ +TEST_F(EmptyRlist, can_clean_empty_list) +{ + ASSERT_NO_THROW(L.Clean()); } -TEST_F(TestList, assigned_empty_list_is_correct) +//............................................................................ +TEST_F(EmptyRlist, clean_empty_list_is_correct) +{ + L.Clean(); + EXPECT_EQ(NULL, L.GetCurr()->data); +} +//............................................................................ +TEST_F(EmptyRlist, can_get_current_from_empty_list) +{ + ASSERT_NO_THROW(L.GetCurr()); +} +//............................................................................ +TEST_F(EmptyRlist, can_reset_empty_list) { - Rlist list = list1; - EXPECT_EQ(true, list.IsEnded()); - EXPECT_NE(list1.GetCurr(), list.GetCurr()); + ASSERT_NO_THROW(L.Reset()); +} +//............................................................................ +TEST_F(EmptyRlist, reset_empty_list_is_correct) +{ + L.Reset(); + EXPECT_EQ(NULL, L.GetCurr()->data); } +//............................................................................ +TEST_F(EmptyRlist, is_end_is_correct) +{ + EXPECT_EQ(true, L.IsEnd()); +} +//............................................................................ +TEST_F(EmptyRlist, can_set_next_empty_list) +{ + ASSERT_NO_THROW(L.SetNext()); +} +//............................................................................ +TEST_F(EmptyRlist, can_insert_after_in_empty_list) +{ + L.Reset(); + ASSERT_NO_THROW(L.InsertAfter(L.GetCurr(), 1)); -TEST_F(TestList, can_insert_in_ordered_empty_list) +} +//............................................................................ +TEST_F(EmptyRlist, insert_after_in_empty_list_is_correct) +{ + L.Reset(); + L.InsertAfter(L.GetCurr(), 1); + L.Reset(); + int tmp = L.GetCurr()->data; + EXPECT_EQ(1, tmp); +} +//............................................................................ +class FilledRlist : public testing::Test +{ +protected: + Rlist L; +public: + FilledRlist() + { + for(int i = 0; i<3; i++) + L.OrderedInsert(i); + }; + ~FilledRlist() {}; +}; +//............................................................................ +TEST_F(FilledRlist, can_copy_filled_list) +{ + ASSERT_NO_THROW(Rlist A(L)); +} +//............................................................................ +TEST_F(FilledRlist, copied_filled_list_is_correct) +{ + Rlist A(L); + A.Reset(); + EXPECT_EQ(2, A.GetCurr()->data); + EXPECT_EQ(1, A.GetCurr()->next->data); + EXPECT_EQ(0, A.GetCurr()->next->next->data); + EXPECT_NE(L.GetCurr(), A.GetCurr()); +} +//............................................................................ +TEST_F(FilledRlist, can_assign_filled_list) +{ + ASSERT_NO_THROW(Rlist A = L); +} +//............................................................................ +TEST_F(FilledRlist, assigned_filled_list_is_correct) { - ASSERT_NO_THROW(list1.OrderedInsert(5)); + Rlist A = L; + A.Reset(); + L.Reset(); + EXPECT_EQ(2, A.GetCurr()->data); + EXPECT_EQ(1, A.GetCurr()->next->data); + EXPECT_EQ(0, A.GetCurr()->next->next->data); + EXPECT_NE(L.GetCurr(), A.GetCurr()); } +//............................................................................ \ No newline at end of file diff --git a/VihrevIB/lab1/test/test_polinom.cpp b/VihrevIB/lab1/test/test_polinom.cpp index 4a12f5165..ffb50eac4 100644 --- a/VihrevIB/lab1/test/test_polinom.cpp +++ b/VihrevIB/lab1/test/test_polinom.cpp @@ -1,4 +1,143 @@ -#include +#include "gtest.h" #include "polinom.h" -#include "monom.h" -// \ No newline at end of file +#include + +//тесты для мономов и полиномов +using std::vector; + +string Expr[] = {"0", "xyz","zxy","yzx","x","y","z","x^2","y^2","z^2", "x^2yz", "x+y", "x-y", "x^2-y^2","xyz+xyz","x^2y^2z^2"}; +Monom M[] = { Monom() ,Monom(1, 111),Monom(1, 111),Monom(1, 111), Monom(1, 100),Monom(1, 10),Monom(1, 1), Monom(1, 200),Monom(1, 20),Monom(1, 2),Monom(1, 211) }; +//............................................................................ +TEST(Monom, can_create_monom) +{ + ASSERT_NO_THROW(Monom M); +} +//............................................................................ + +TEST(Polinom, can_create_polinom) +{ + ASSERT_NO_THROW(Polinom p); +} +//............................................................................ +TEST(Polinom, can_copy_polinoms) +{ + Polinom a("x^5"); + ASSERT_NO_THROW(Polinom b(a)); +} +//............................................................................ +class PolTestParse +{ + public: + + string Line; + Polinom res; + + PolTestParse(string str , vector &M ) + { + Line = str; + Rlist temp; + for (int i = 0; i < M.size(); i++) + temp.OrderedInsert(M[i]); + res = Polinom(temp); + } +}; +//............................................................................ +class TestParsing : public ::testing::TestWithParam< PolTestParse> +{ +protected: + Polinom P1; +public: + TestParsing() : P1(GetParam().Line) {} + ~TestParsing() {} +}; +//............................................................................ +TEST_P(TestParsing, test_polinom_parsing) +{ + EXPECT_EQ(GetParam().res, P1); +} +//............................................................................ +INSTANTIATE_TEST_CASE_P(FIRST, TestParsing,::testing::Values( + PolTestParse(Expr[0], vector {M[0]}), + PolTestParse(Expr[1], vector {M[1]}), + PolTestParse(Expr[2], vector {M[2]}), + PolTestParse(Expr[3], vector {M[3]}), + PolTestParse(Expr[4], vector {M[4]}), + PolTestParse(Expr[5], vector {M[5]}), + PolTestParse(Expr[6], vector {M[6]}), + PolTestParse(Expr[7], vector {M[7]}), + PolTestParse(Expr[8], vector {M[8]}), + PolTestParse(Expr[9], vector {M[9]}), + PolTestParse(Expr[10], vector {M[10]}), + PolTestParse(Expr[11], vector {M[4], M[5]}), + PolTestParse(Expr[12], vector {Monom(1,100),Monom(-1,10)}), + PolTestParse(Expr[13], vector {Monom(1, 200), Monom(-1, 20)}), + PolTestParse(Expr[14], vector {Monom(2, 111)}), + PolTestParse(Expr[15], vector {Monom(1,222)}) +)); + +//............................................................................ +class TGeneralPol +{ + public: + string P1,P2, res; + TGeneralPol(string RES, string POL1, string POL2) + { + P1 = POL1; + P2 = POL2; + res = RES; + } +}; +//............................................................................ + +class TestSum : public ::testing::TestWithParam +{ + public: + Polinom pol1, pol2, Res; + TestSum() : pol1(GetParam().P1), pol2(GetParam().P2), Res(GetParam().res) {}; + ~TestSum() {}; +}; +//............................................................................ + +TEST_P(TestSum, sum) +{ + EXPECT_EQ(Res, pol1 + pol2); +} +//............................................................................ + +INSTANTIATE_TEST_CASE_P(SECOND, TestSum, ::testing::Values( + TGeneralPol("0", "1", "-1"), + TGeneralPol("0", "x", "-x"), + TGeneralPol("0", "-xyz", "xyz"), + TGeneralPol("2xyz", "yzx", "xyz"), + TGeneralPol("x+y", "x", "y"), + TGeneralPol("3.14x","3x","0.14x"), + TGeneralPol("18x^2y^2", "10x^2y^2+x^2", "8x^2y^2-x^2") + )); +//............................................................................ + + +class TestMult: public ::testing::TestWithParam +{ + public: + Polinom pol1, pol2, Res; + + TestMult() : pol1(GetParam().P1), pol2(GetParam().P2), Res(GetParam().res) {} + ~ TestMult() {} +}; + +TEST_P(TestMult, mult) +{ + EXPECT_EQ(Res, pol1 * pol2); +} + +INSTANTIATE_TEST_CASE_P(THIRD, TestMult, ::testing::Values( + TGeneralPol("2", "2", "1"), + TGeneralPol("xyz", "xyz", "1"), + TGeneralPol("xyz^2", "xz", "zy"), + TGeneralPol("100x^2", "50x", "2x"), + TGeneralPol("111xyz", "55.5xy", "2z"), + TGeneralPol("x+y+z", "1", "x+y+z"), + TGeneralPol("x^2-y^2", "x-y", "x+y"), + TGeneralPol("x^3+y^3", "x+y", "y^2-xy+x^2"), + TGeneralPol("x^3-y^3", "x-y", "y^2+xy+x^2") +)); From c9014e69daf8a5fe3eabe2c39d6695debb2f122f Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Mon, 16 Apr 2018 22:12:56 +0300 Subject: [PATCH 09/16] Report fix --- VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx | Bin 108364 -> 108558 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx b/VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx index c549d88dba3cac734f7389437cb08ce361bf6cee..fc0f16fd9ce7715958dc00b19713f06ec92e7b14 100644 GIT binary patch delta 55603 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

D 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 N(D7)#pT;cU{{gA#pS=J8 literal 0 HcmV?d00001 diff --git a/VihrevIB/lab2/include/table.h b/VihrevIB/lab2/include/table.h index 6a8cd27e8..625823206 100644 --- a/VihrevIB/lab2/include/table.h +++ b/VihrevIB/lab2/include/table.h @@ -11,7 +11,7 @@ class TabRecord { public: string Key; - T Data; // + T Data; TabRecord() { Key = "EMPTY RECORD"; Data = 0;} TabRecord(string K , T D ) { Key = K; Data = D;} // TabRecord(const TabRecord& TR) { Key = TR.Key; Data = TR.Data; } @@ -45,7 +45,6 @@ class Table virtual T* GetCurr() const; int GetCurrRecords() const { return CurrRecords; }; int GetMaxRecords() const { return MaxRecords; }; - // }; //.......................................................... template diff --git a/VihrevIB/lab2/samples/table_sample.cpp b/VihrevIB/lab2/samples/table_sample.cpp index 23d377874..4f6b48e2c 100644 --- a/VihrevIB/lab2/samples/table_sample.cpp +++ b/VihrevIB/lab2/samples/table_sample.cpp @@ -64,11 +64,11 @@ int main() cin >> Key; if (Key == "end") break; try - { + { + system("cls"); Utab.Delete(Key); Otab.Delete(Key); Htab.Delete(Key); - system("cls"); cout << "UnordTable: " << endl << Utab << endl; cout << "OrdTable :" << endl << Otab << endl; cout << "HashTable :" << endl << Htab << endl << endl; From fef9ebbd23a0a74761c736ec7988c4f4a974da37 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Thu, 31 May 2018 23:55:02 +0300 Subject: [PATCH 15/16] report fix(3) --- VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx | Bin 119022 -> 126470 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx b/VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx index d07d02277ac26d2ed49d99cd8c3e01400722e5ca..08e6294bd5b3b7b72cd49e72b5ad824d9906b38f 100644 GIT binary patch delta 45128 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 delta 37652 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 z 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 Date: Fri, 1 Jun 2018 18:46:06 +0300 Subject: [PATCH 16/16] last fix --- VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx | Bin 126470 -> 121292 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx b/VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx index 08e6294bd5b3b7b72cd49e72b5ad824d9906b38f..1698a8efd99d14304adef3316f85a0a076e5278a 100644 GIT binary patch delta 43728 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 z zA&^D_znQKRl@g?4r^DnHfaEKrHH-)r^A$Is!MmLVvC{d7+<(OB$a~<)W5}&UJrCN% zO!Wfb5;g-%yI$lfoI$c;-Yd^p~QkADo}_KVr52n%RTT&n_y{-(@9-|;dP;ro?Dxqx912030f}uN3f&RY$00030|LmOoZ`wE*$N!ZmKTPdOck_D^ zHY(Y9*{10FijY9J_aN4eAe?`H>C%huiuTMFHbL`h-?JKqm}{MdfnMQ=W+ z&t5Ki^K-Qb?&^1aK5m-=wJgVwLl#^Xbns zRWD6`wYkeYUHjzT0+QZ5uk$yfz7G+`JQUP#uPS+?%zxEj{qi^E+$rVWqBj>4d6{3A z>g$w&xr8}`aopDPm%;GQ76jYxz8@AtiO48P9bJ8OSRBo=_bzV1gS)%4XmAe_AXtLC zyAxR4gToReA-KC+aCdiy4eo9q@44S|&bhb$seWd9db)b1tE#(x-Bk)JX_xXnVHyXl z4SLx}jWQ2~Q<4NWQF|CVlV5F;N3i52&^zo-p^)W>Wub8*o_3tA9Ru0J4M(ux(bobt z+ty&oX3OPS!fm|5LitL|lfk#8pV>#2FGWX+y|1+VREK^-*YzPas$M?kipTD0@0?)( zU2-p7or@wqkV+9YvDN*eS{w;5O zu>k^Q(7KYEWEOO`hh`nOGI@&G%uOl;>I?%DX*!a6V&r8N>kG_J!oUC|DsiOm+UQ;4 z#1lDQS^k|Yaow_dc5Q8l>6lG;vo`_5~@2% z%U55#s6VXK#Kml}Ab=lY6YW_uXOS{E;hKm8PFYTj)&55QDt!2|q{s*Fl!|rada@&n z#vK=&(JT-$7JYUzu{mm6K8~oNGg7>dA0*on7mI0_+NdgN(Hi;V*0!|hZ^Nx7TiKo! zX4XK+A2-Cj#w$h3(D_rJc6-K`B8$`a7yh|OO<4L`w(jTx!I)s|vDKb_6E^|UaygE; ztj`!NBt!k;i;D`drWw=#U5pz!3UV8GAc87MFk5I5ce#7Ijy6F*i<7!~rcq^D#cxWi z@aEK2>Y5NJS49|(N^Fb$hxZP{8u!P!tE5#!3w@TqPO8>YP?X^uT{2{&UgugC-vaKI z--+CPreTy`DJuq(us#WqO@f}?efn-EG2l#taqtJ1-)p3YD8a=e!8uDtkEP9>#J6(D z#7&HF?ng#^H&AdKz}_J0tGZSar5Qq<*|B9? zdGN?5j{FGuZaH`8C5}g@gPTgf^0A3W!io6f#dgv(Unw>?>RK|rrh7=>%ZC)DBYX;B zI3928$F%t~vbZN=3DU>W&?G1E`qXE3`&08TH)&oXNxoqHVVSvKxnTGH5Y_9c;eId9 zW$G!oenzO%)?TRxNEOqZXH4Qro!Me}x)ZmG!st)m-@WYO@_a8}xAKcG`#vb#FdS8G zZ8{>e->#;B^m`)gBfEo4Lb9)k6&aZ1fnFKTq^W!6*ow6ZXRR59UCEF$&lpS zL2qVGCO_DP{wx;uQZHoBktsE$w(8-&ntA!E@PqH5%}+*Wc#?wrqmk{4Le?sLrl;@e zws!I6P7f0Y$~IchRfIC!;tgVIFIGh7baX$riq=Oru->?^;d}BBSiH!iw;l5f z&@F=PJF-f77z<(4KUw0zasY*T=4cMuAILT>UyZN;D2j+r8X*leVA&92fzLtXhAcMD zqbC!Q5uydbHu8%ipbjDEQD8b-P`r z75&^fl#M(CPC!Yn9I8S|bh6!-2P>$wg_J!EXftf`$_sM=+n=5+yV@>nY?>> z&w)^4#^vrP>snikE7o~+0d7Ya0|1mJ#^e%#9f&wF+qDkB zl{Yh*fvZZ$0U9acFyaEa;>b zu4B6JO)N#~&mXnQ&Wry6wxdsY=Y`Y)GW!=z0>dH(+=+lI!DnD5aFCh0Bi3x)8J9hA^SRdD* z0G2ysay~c!fpH|VI6wNfx^uIbO6QMePg)I=eNNYy6*qxRYd{_)SXjpIi$6be(w{K` z1X;x%)tPV;8j`)zBu7Q*#5=vRMH_q17f@i$I`Yg#?WSVgh(@=Jib)IBI4`7S#$kgg ztkob*Kxw2Kg}E_6IKnu}(?v<)Z>qO05GnzolzuZ@^X?bRyay-z zLRs^t03L)BKX!$V*!OmZ8)Q)jrTDKDip{sgu1moagv<>heFkXVPOspp^gYl4?$ptn z+(+DT^3=7ZZHbqTaO}sb&|($-{cO-Gm)dM-O}2kQ?gb46IMfn)Z8LJhY_e||!dvWd zSr)j*K7h@pg0%*xZdCd+Xs^?jKa(QZ@0)l-;^Y3#!^w*~zelIi0Ob|A7n;-esvU}1 zKODN}8dcABW)1x6kPIuv8thMZM_JHP>O|~#(7mo`vCf=2^T;1Xc7mHe@q$g$N&IH%tppR$Kkz&f19rZCJ_JtYyhNVABYPc`K;uS!-3gWG4tyGO@$*VMGsf4 zNW5jJ%(_LigO{!<@(3{tfGVk!T!caAS~G;z(F(tjrBawmY!>c-?KnD{_oI_bUy?(9|F)qE z|AC?m<|QaRN(w~!UCeK0gxZW|Lb7@C(JE_%0OBaV6H34{5fN*fmFhZ%QcE#scg=(= z^#^3VweY^`DP(@do|Lbh)QUp(d&;61=OXe&Tq!;e3$?_r#D*|jG2+hLW3JG&S!Gzc znmucSKCQ(Jmk$ZH%I~YNt_kLg8JcVnLg>oAf^UMM1MEI=g+99lgw)^qq=b9XonnGt zU1AjAHl2UneJm5Ow0FG}2)z3c@I?=lAxcD4XR!^bV%NZ^#L3^R4#fDKT=jiH1ew;7sg+4Nz47#(0D_FAYk4Qr-ubk> zaqrPbGlT*ARLFRBl3(n~RenxD#%E0n*4_;U2C-_HPc5!UKJse_)c}3Q-_MjLw$c$q zVl8DnzJvy5lF)kU#Y|@7f+4nYki7RQ8eYn5<5e&OJityA$3(mfCB*UWl!EESa*7BB zySOXhCN`@)<;}HP*>k;+bpHJiu&B$IVSvXpT{C#Np!u*n@Lu_bzHy2259_EN{hrk@ z+E20Gnpv43vvFFcu6XH%Ylf#e)46qi)y(_0P5?bx%}5ZfWrDOa!XV`s14&ne+E;6y`!Ip7Ch$6!=OQ4kuHE?ou`JtTVKi zu&;^$jmgY%pCJ#3B|=v639Cdn&J*-KHV$EacCyhH$I-Ka_E+)Gpc^%h_weq68b=@P70$H8`2Y~8N!(8;_Lj-5^Z2l`EN;cn8FM=moSB5@& z=FCdKUBaDyV}8BBo6a5Orgz+2?{FF#Z#uoUs?l=s#I5cs>U<)VP}kDmY#TZqF|X%E zLAaC;E{u5|DSH7oVcl_Xdp$TP2+xLjt#ez5W}Ub!AOBH%3iqV$tg`ViTL&iw9dxr8 z&g!CTu5&(k->A6W==9<+Q$dfeuF7^Ez$O%H9DgxHvj^dPOY8L}m7JV4bJpxcR`~3+ zY%y??bI0Dx*LtfM-H+FoRs7`ZuU?LKV8|!@su$bQ-pWjd(e2RtcAigc?QRhTAtQFvbNuNg=kew{Qt|Vs^{9b^ zAp0-VCclqgL64{UYiC|!{Is*X`|b*#sH`H>O0SsqMe2NpvY?|TTF;HtvVn=b zjr^#N0*ML(?Z3$VXs`F);=$NoUX}KT>toWT?h#7mekPl?94zY#Pj~?z9XEs}iuTMvst4;U@B{K-lYncwl_YJpL34PT>$xoOl#`5w|nR2t1+L zNaboa9ztKhR+p4qPPjyeOOi2}MO(FubYX0^=jFuQkm`9q6prblQnP3VDT;PL8`~(l zc!WlvREUYoep4WA@UxhGnmS9D?aa!VKNh7LYK{WxG4)Iskzr3$Rx&dBm(Rqkjs>$Z z?BE&IV>$BDqUnTA@2s{F*iwz9uiG361jJSExHg>(C}=nrM1Mr%EiEA>8WT|~mH&p5 z;e=-8%c$4&@TBD9vjl7dzlOzyDBEPXp}>8MnMb|}JO^#8Sz=>V;wxGU zgq_Q{1tQuW4)C1R(y1kMSX*Uh-$Y{$mw`KZCl$&arK@+Qab;R(6&wqT>J)4&Np0Q@ zXW=7Z@t2pGz^GWI2wQL{ZNR9YgC?Tk9*e%~ZvKNf?jqVMWMUc^RUHwswCN9VoS2LG z7S~NU$Y@gq&M>1406C7G!O2uy&TS3J${iS*H}(Elq4kyz>|q&cV?#>rD0Ege1K*L1 zr%KR>pC$Io`(nRKK$G2- z@K>De0z$+nPi>t_$fpSx5$+));+-@^7Ps)@EjP#oJh?K8*8hx9_WNcgua+- zj0Hq2Pq#B1W6V?6NHUwJA2g8ap?xr7z0x3wnZI-&Dv(DKSc8E2xexOGN#%5n^eI z(w521?08L2vxSoGVl6%)2o`{FhG8XqM1e08}6S?ax8o1 zrakpBJESWOImwj9$k=qGM_iooXyAZe3aS%DPRnGYMXH8-M(hguLNNHXd@XwZ^R`>( z74EWmV=;YXZDE6+hORFWdv$p~>GFw7VH)9jiie$+U(||-y@g}jPyco{^st5ZErk5= z8f}YO&z#Js%Hv@w(jMSVpS8)(SzoW)`HI#))XeI~kMkmA^jA&HG305!UaEm29%D%w z+}}zMyxPDkYh$04Cc$mrU_XE!|A@NL3+atqwi1#JHIp1)R`IX?&bV=pJv0FSif$8f zZP@mezc1n^E3ip9{_sbKwD>VBAeN67w(U6TU=1#uMYQR8sR*devFw%VcIxfNk#1TgC5w2zjl201%mprI%OLC z@|!zT(vac3ptmuw^oO)hHd5flIS0kRykds z^M?6y;!62B&oXbRhyRH;Ydu@mz>R5OzrJyfy)BSGlbpq9*sb~-`TN-XXq-N}WVC(N zH%l?QfU&R^jfrJe-EHfExs?9S;D`Do6Y*RTx^tPc-JEz!qo(fE0F5V`+T*DU)mX#c z=__pFZ)DsCofaSqE()^{>C7}L05Eq4i5&+LgY6F+vD(=uJdn_Kvhn-(e$g;397&`c z-{7`HWkYe>G)ZW&G(|&8Y0`&J60gc*Cq(*g=iw;-ie!@;BU&@T?;FMN-lIi{t zn?w0L>LH5wvKU0{(8kc3vB8*@(X=VpeABf&Jh5rATb-viKr(gGd z1V66(UV37!A!^xYXbOLPL~6i~O~2mVVUq{p*DSjGLJ`K?i98Samt^<`T}k0<{_gdC zZK>&JX#a^7topJ}7c+O_o_=E@v>8;BnY0Q&x|aQ&I3M33o8K|v%I2F8YQ|l`<7h$c z?e|1at)Hi~Dpu=q>uxxD$|u`r*+*OIyx^?TL21sc3zK=O6PNYuL8>q7i1w*F9vQvm zzhWp+8a&p_F(m67uC`Xo6A`h(!#dVyeO3%XCxk4WB{Zej#!kICBxWmEA|3CfVvzO0t+* z-RJc;lK4J8J{-L0>IwBv7e9?3>J^=?(MX@~u{+&th7gXG^0y&Un}bq>=vzlw`DRr$ zy)@^3?q<%0#U6I|d(q2V2dW9(Y?$*tbe`wP^1ZAnVe{F)?T3`4N|hI*dIy%f&OM39qM&Y+Dur(v*`+bhRSVEM=QI#|6J(OhhS*og(Oa)>QUuJL3qXvEynz)CGMT zr>qLiiM$yzUqlov(EKFQC{6I9Z`B1w2olDu&41(5yx1#Pplb=j&MS7KD)0$8Zt1W~ zU>Hyco}GcVh|*%O&Y}dMb6{&LEq-RklI_j-=mdu2%__=m(V3gGFQZ_RrZ9T0S~V*S z6(z#g-?d>D&1hwx=eyMjYqILY`u}yO;?l3yIV+4_3F8k3L|c-UO$X!87nVEYPQ!Pi z5~oJ*Fl;=vySs_}TEoJ4pI%Rieu9LB=|amFZ;A;bO2Zm>BYCR917V&FyB1_?VyMPA z`mKzg#=1rIdwTn4%Uf1=TS<@rm;egEYMeg+03;}K6$7lr0B{{HFpvOsu9?KtL3eOJ z@bVP*DMVP#JG+Cz5HT>w+TWvl-eD;e#DvYKk^MXb=`0N!(^QkK)v{Fgr08#!=Ax0c zSFHU{Su$a;u&3wQ*#()tgSY204`Izm-6`>>rhquRDijOaw|40pV11oOd(;qqA`fMX z5Wo2C+IP0CflIesnvYMn$Y7s=>p6L>F}b0g^N`B<8!aXt%kUX<%847MtEmS^O~^?_ z7CUZ6c_oMUtMg7YU@#Rvk1)V|W~2+5=ACiBC^4KT*C0uhAu{_xf zigepYAv=Q=_PTQw!!8CZ%S^lWW!UC7ZR(=Ad(h3h%a+<`uy^~Psb6PgVgv0S5)2@_ z=s>WTK`6(Eb%UhnxA+%As<;tFIiHTUHSHMkp^t|j0vtbhbia=~@}ZBT>NLlVdlvQq z4qSaR$YWQMVQ2{P`I`9NHJeeNE=HmTY;?z!wtwHQX&|O8lyT}MPM<~PE{GC0i81l^ zKovWkF&UA6YZi`r)dO*e)gRsx)akeDT40dz4}8}yrl$o4?LAEG=}X`1_5mJ0OR9@N zJX2V`#zoi7&)nxsX6*N$Oy@5b>g^(r+f0gs-yM2skDpR>dXvpvuErUDU@vj4{26xr z6zAfRCVQA?+95XVC7-sN^C-BvGS=_OU~UN8f#5xY^$+oX2Out#gaMs}+GhEKT{{q> zdnF{LPpQ%OI~mD4w0ECgVvhb$U!BE`6f}p0nYNppy=9@2ThwP__+mG6TvOFu%nlcg`=3}t~A8jpO&YfNXGwat*Pff zEe3!9wpkH!l%NUW!&oa91%|JE{%jFs7yyYB+2z z80Dv|2$oQqoMsMO7?Op#_;XxQx86%|;O^SI!$T|>Uw zZ!uMrT;4Dm*_}IQNK@#DU%^zj?sq?L*fcvRXVCQgq0Be)#qO80wgm~w{$U~f&BPAO@fj*gG*8BQe6$nEkNiyqx9y*eyW`|!fJC`Keen7ufIK$cO zscx=RR39~OCZTlD?8#(;H=}=T^5awD65G#PRNi-P=cC<{*Ligmm$L&JuU)#@rdCnw zz>ZMj1xMHlvW;2TR&Rn**RzApFfELnB<0^)7^B=D-zf-eJ;-58{E!Am(`pKiO^8c$ z^ae#C;;+9$))j8Ni&sEodwHk#?UF)GvWBJ4Hisb6wVZMutAU}&U(-00AGU|kKNx@< zuPI1DDJJ0`oPmvOMJ8o!i3*#SQb-WVf?UO7tdmBm?8KuvOv{U}h8RC*CYTXyszCWE z0pBC<+ck_wy4|DzGub&TJ75q4V=q|hTsAz2_8SB{Q-F-X>1iaJM6%4 zIGQ?cHZ;25t_KO2bS8MXR1zbXaE72|{xW<} z>>*sm4pPu}&Ukz=!|QF`BK$5pbBRr*yHqEB+ZcgKn9`EZA1vbeMFwO$O_#9M5G`EV`YVU2cP1UJrw zrWIz2*;Jl|!qg37)0t|ey@O;h|RahyLB@@w9DnBk*mhEqvFX9bvo)FcbM?fJj$ z!kdj3=mmIOtH+Svvi6qRSt~B4e5p>uD>xQ;L`a$eWg?UG5kO%n#bbuTE1hbptrmnF zq!j-mZawIKoaJvKFryxQgJW8msx=$0vq0>3BCqWX;bg=9b8K$Gbx0T;=Negm>0V@A~8`RXG^boj-sj z@yGUYO@`UCOx}`kGi#3Y| zH#0iJIGjqREBp@OS}0}pyal8~uVDpDPq~MXTB3OJ`rreG8c@CVi}fuIUGVF77k)Dgkj-RYjMn3Wef@t!yjqhcI<^>_q=dnKv&BA?qy#|+6(4x$tP{O z9I4Y~6JkXhjpqd?9!fCS(f%~ktl z3WBy@wH}p?4$-6q_o|7-qeNEt%e^U9^T8VgqyF$T_G^CR3-U|7`rFpCpd2|z|HRmw z?kWd+a%r-oRFLiGpsZ`*XsgHc9M6uACv3g`-#OcZT)U2w9#J?5N0JwNcW-*2$Xkfr}DY_gu-^|U< zq>-tf0|VvEwBc;rX?{_WNVfF(3U?qs8ULkaa7DF}sWpljVb2(6=BEvWKEf7%sQAUu zn70UA#~RghnoZgyPF+ZQ|1%pg+UcoMI}0VkpD=EdVSio@P5Lbuxy*wsoKUbgnP@Z< z*@0J#&4y^VLIk(;9t{-CJo+_B+Y?^*qgYsDB6j{xpQ|QJze=(kpfR01J`sCzSRq=7 z>D-N7lgR}gO+2IgUSEGo#N@8s}TNIz!`hXp9h80J4V+Uxo$SY%0uak zEhijzbQ^2NhXmz%OzTnCL=r}@>0!#D(``d}zsG<`H2Plnfr4UWeqf?lJi)8p6*jR6QS%HoB(d<6C`AWt7-sZG;yyo8=s1Ilmf$g`&5Xh)Q zItOmYY2uA2#X502ju>rncJXxXiR9Oo786C|(HqHnoRpVqp8y{Dd9t)=e#eW;n)O(V zXF%umC^>B#E1#x6n>;^qct3BD!e0$}GV+sht}Pu|H)&c+{RGm69rKs-Znv+s-|iEI z!i37gaP3fg6{_9K8NaPp^J>i~gR?e?@NGCE1vAo;D+=%1tjY-rLj|jF)fzL&;X9K^ zIQBl^7TR>)u~vTHT5`K?-^7l{I{w0Q^JA_(Y%Z{f2sZj_6jZeu%E)wug+o^%roaJ< zXU*5yO(J;kNt+BoFLwtyP9GsW2GAQh&ipQvjh3lHSvWXeK(Mf9j!dS46)dHZz>hS| zpDDe1fnB_6*HD{>eT@zNB@Mi7bst~cNPVW%Jmj0gm}pgI>k#<#x>NOC+UzD?Xx6gT z2}${A+HYONl3_b6H305Pi4Wa7SorX$dT2K)hOLAbO8+N!MwGM}!(d77LRi_{DK%O! zG>dxl(h5`7OXPqcFh&PYR{gGgsIR~TQ?Oe2W49GiNKOppU!-Y95eg?f#GF{8yMaWW zfoez4!<~W1L)GI>NFOro&pXo8kbpVoX@l>>t9;Lg!@hhuY7&pnhXp^~Z~D1jQU8%F z$Y7L;-j}!UeBQvj3#0^sSM8@caNA|KNU7E-X2tQ<9pJf_&whjaDvi`D%Fu?1`x)1qaAZxu=V} zJT`eSo3tGd%OFs=X^Y*UvW^>1_tOTB?eFJ=BZ*2>g|-!O>L)mGHxYHR(|07xW>#K} zJQ`i%`vre=9+hccNp-fC$R z9D?3DMuCN>vj8yfpNbiwMC}9q)Ax2;F&vCXX#vEAll1xVl1l)M&+kQ9;o{P%) zxjBVMf0#=T1;K5w())zvpKeobhCIqfo{8@UWDB|i3Znbyd`ftn2V8`G{N=_Y%5dDF z_rj-gF?7pvs@*7N8_9(qI3AWe?ZsTF^-*V4SHgP9OgY%j4{*>0=m!xuf8#jF-*hql zh9#Ur$my@U?mWM7dCYsB^Xq+$z43V*`AcwMq>E+3dniQ;?yxd;xN^n(h0Xf8uybA0 zbMy>jO=qM9%265fw`U~A;%U;&jEI@1SV=b67<}bX&oRGR|CDe!Lul6-gwpc;JvNkk z)EqkPNuEuxoQ1DIa>k!E*=c`bS56Vu z7o7ibj6&4^0%uV7=a+WB1_JlF z;ak;sd63aVASKCv7JUB!iTrnxXo8>|0YzY>dm#!(K#u=!AA*m7?_oanLsE`_QZP{i zkd-4KEy=%ZsW(O*-_-N}X2fw2LV66OCi#!@{=ctL9D(Q_zjelcge~BWk^fFBV~~tv cARWoShbip;{Q$cYkT--V6$0VRTO$Df5AXFm?*IS* delta 48920 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

`h@YggZ5|ViGVn|J)QG;+O9%@(3tJB&m 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

{L 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 J@^8H2{0oAkAAA4+ delta 55381 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 From 1d0613942cce5f36b64781777cadb568eada0246 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Sun, 6 May 2018 21:07:30 +0300 Subject: [PATCH 10/16] lab struct and 2 classes --- KorolevAP/lab1/build/lab1/lab1.sln | 29 - KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj | 90 - .../lab1/build/lab1/lab1/lab1.vcxproj.filters | 14 - .../lab1/build/lab1/library/library.vcxproj | 86 - .../lab1/library/library.vcxproj.filters | 29 - KorolevAP/lab1/include/tlink.h | 9 - KorolevAP/lab1/include/tstack.h | 0 KorolevAP/lab1/sample/main.cpp | 7 - KorolevAP/lab1/src/tlink.cpp | 1 - KustikovaVD/lab1/include/tstack.h | 10 - KustikovaVD/lab1/sample/main.cpp | 7 - .../lab1/sln/sample/library/library.vcxproj | 80 - .../sample/library/library.vcxproj.filters | 23 - KustikovaVD/lab1/sln/sample/sample.sln | 29 - .../lab1/sln/sample/sample/sample.vcxproj | 88 - .../sln/sample/sample/sample.vcxproj.filters | 14 - KustikovaVD/lab1/src/tstack.cpp | 0 VihrevIB/lab2/gtest/gtest-all.cc | 9592 ++++++++ VihrevIB/lab2/gtest/gtest.h | 20063 ++++++++++++++++ VihrevIB/lab2/include/hash_table.h | 1 + VihrevIB/lab2/include/list.h | 142 + VihrevIB/lab2/include/monom.h | 19 + VihrevIB/lab2/include/node.h | 19 + VihrevIB/lab2/include/ord_table.h | 129 + VihrevIB/lab2/include/polinom.h | 46 + VihrevIB/lab2/include/table.h | 46 + VihrevIB/lab2/include/unord_table.h | 111 + VihrevIB/lab2/samples/table_sample.cpp | 13 + .../sln/vc14/lab2_tables/gtest/gtest.vcxproj | 158 + .../lab2_tables/gtest/gtest.vcxproj.filters | 27 + .../polinom_lib/polinom_lib.vcxproj | 166 + .../polinom_lib/polinom_lib.vcxproj.filters | 45 + .../sample_table/sample_table.vcxproj | 162 + .../sample_table/sample_table.vcxproj.filters | 22 + .../lab2_tables/table_lib/table_lib.vcxproj | 166 + .../table_lib/table_lib.vcxproj.filters | 45 + .../lab2_tables/table_test/table_test.vcxproj | 164 + .../table_test/table_test.vcxproj.filters | 31 + VihrevIB/lab2/src/hash_table.cpp | 1 + VihrevIB/lab2/src/list.cpp | 1 + VihrevIB/lab2/src/monom.cpp | 1 + VihrevIB/lab2/src/node.cpp | 1 + VihrevIB/lab2/src/ord_table.cpp | 2 + VihrevIB/lab2/src/polinom.cpp | 286 + .../tlist.h => VihrevIB/lab2/src/table.cpp | 0 VihrevIB/lab2/src/unord_table.cpp | 2 + VihrevIB/lab2/test/hash_table_test.cpp | 1 + VihrevIB/lab2/test/ord_table_test.cpp | 1 + VihrevIB/lab2/test/test_main.cpp | 6 + VihrevIB/lab2/test/unord_table_test.cpp | 1 + 50 files changed, 31470 insertions(+), 516 deletions(-) delete mode 100644 KorolevAP/lab1/build/lab1/lab1.sln delete mode 100644 KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj delete mode 100644 KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters delete mode 100644 KorolevAP/lab1/build/lab1/library/library.vcxproj delete mode 100644 KorolevAP/lab1/build/lab1/library/library.vcxproj.filters delete mode 100644 KorolevAP/lab1/include/tlink.h delete mode 100644 KorolevAP/lab1/include/tstack.h delete mode 100644 KorolevAP/lab1/sample/main.cpp delete mode 100644 KorolevAP/lab1/src/tlink.cpp delete mode 100644 KustikovaVD/lab1/include/tstack.h delete mode 100644 KustikovaVD/lab1/sample/main.cpp delete mode 100644 KustikovaVD/lab1/sln/sample/library/library.vcxproj delete mode 100644 KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters delete mode 100644 KustikovaVD/lab1/sln/sample/sample.sln delete mode 100644 KustikovaVD/lab1/sln/sample/sample/sample.vcxproj delete mode 100644 KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters delete mode 100644 KustikovaVD/lab1/src/tstack.cpp create mode 100644 VihrevIB/lab2/gtest/gtest-all.cc create mode 100644 VihrevIB/lab2/gtest/gtest.h create mode 100644 VihrevIB/lab2/include/hash_table.h create mode 100644 VihrevIB/lab2/include/list.h create mode 100644 VihrevIB/lab2/include/monom.h create mode 100644 VihrevIB/lab2/include/node.h create mode 100644 VihrevIB/lab2/include/ord_table.h create mode 100644 VihrevIB/lab2/include/polinom.h create mode 100644 VihrevIB/lab2/include/table.h create mode 100644 VihrevIB/lab2/include/unord_table.h create mode 100644 VihrevIB/lab2/samples/table_sample.cpp create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj.filters create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj.filters create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj.filters create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj.filters create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj create mode 100644 VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj.filters create mode 100644 VihrevIB/lab2/src/hash_table.cpp create mode 100644 VihrevIB/lab2/src/list.cpp create mode 100644 VihrevIB/lab2/src/monom.cpp create mode 100644 VihrevIB/lab2/src/node.cpp create mode 100644 VihrevIB/lab2/src/ord_table.cpp create mode 100644 VihrevIB/lab2/src/polinom.cpp rename KorolevAP/lab1/include/tlist.h => VihrevIB/lab2/src/table.cpp (100%) create mode 100644 VihrevIB/lab2/src/unord_table.cpp create mode 100644 VihrevIB/lab2/test/hash_table_test.cpp create mode 100644 VihrevIB/lab2/test/ord_table_test.cpp create mode 100644 VihrevIB/lab2/test/test_main.cpp create mode 100644 VihrevIB/lab2/test/unord_table_test.cpp diff --git a/KorolevAP/lab1/build/lab1/lab1.sln b/KorolevAP/lab1/build/lab1/lab1.sln deleted file mode 100644 index 96588ef80..000000000 --- a/KorolevAP/lab1/build/lab1/lab1.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lab1", "lab1\lab1.vcxproj", "{B111E032-5082-4BC7-92E5-EA2B89A99884}" - ProjectSection(ProjectDependencies) = postProject - {7A1A924A-8268-416C-B8BB-107468B92BF4} = {7A1A924A-8268-416C-B8BB-107468B92BF4} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "library\library.vcxproj", "{7A1A924A-8268-416C-B8BB-107468B92BF4}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B111E032-5082-4BC7-92E5-EA2B89A99884}.Debug|Win32.ActiveCfg = Debug|Win32 - {B111E032-5082-4BC7-92E5-EA2B89A99884}.Debug|Win32.Build.0 = Debug|Win32 - {B111E032-5082-4BC7-92E5-EA2B89A99884}.Release|Win32.ActiveCfg = Release|Win32 - {B111E032-5082-4BC7-92E5-EA2B89A99884}.Release|Win32.Build.0 = Release|Win32 - {7A1A924A-8268-416C-B8BB-107468B92BF4}.Debug|Win32.ActiveCfg = Debug|Win32 - {7A1A924A-8268-416C-B8BB-107468B92BF4}.Debug|Win32.Build.0 = Debug|Win32 - {7A1A924A-8268-416C-B8BB-107468B92BF4}.Release|Win32.ActiveCfg = Release|Win32 - {7A1A924A-8268-416C-B8BB-107468B92BF4}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj b/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj deleted file mode 100644 index e0711ab42..000000000 --- a/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj +++ /dev/null @@ -1,90 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {B111E032-5082-4BC7-92E5-EA2B89A99884} - Win32Proj - lab1 - - - - Application - true - v110 - Unicode - - - Application - false - v110 - true - Unicode - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ../../../include - - - Console - true - library.lib;%(AdditionalDependencies) - ../Debug - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ../../../include - - - Console - true - true - true - library.lib;%(AdditionalDependencies) - ../Release - - - - - - - - - \ No newline at end of file diff --git a/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters b/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters deleted file mode 100644 index e887328dd..000000000 --- a/KorolevAP/lab1/build/lab1/lab1/lab1.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/KorolevAP/lab1/build/lab1/library/library.vcxproj b/KorolevAP/lab1/build/lab1/library/library.vcxproj deleted file mode 100644 index 140d149af..000000000 --- a/KorolevAP/lab1/build/lab1/library/library.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - {7A1A924A-8268-416C-B8BB-107468B92BF4} - Win32Proj - library - - - - StaticLibrary - true - v110 - Unicode - - - StaticLibrary - false - v110 - true - Unicode - - - - - - - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ../../../include - - - Windows - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ../../../include - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/KorolevAP/lab1/build/lab1/library/library.vcxproj.filters b/KorolevAP/lab1/build/lab1/library/library.vcxproj.filters deleted file mode 100644 index 67ea62a30..000000000 --- a/KorolevAP/lab1/build/lab1/library/library.vcxproj.filters +++ /dev/null @@ -1,29 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/KorolevAP/lab1/include/tlink.h b/KorolevAP/lab1/include/tlink.h deleted file mode 100644 index 735a23faf..000000000 --- a/KorolevAP/lab1/include/tlink.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -template -class TLink -{ -public: - T data; - TLink* pNext; -}; diff --git a/KorolevAP/lab1/include/tstack.h b/KorolevAP/lab1/include/tstack.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/KorolevAP/lab1/sample/main.cpp b/KorolevAP/lab1/sample/main.cpp deleted file mode 100644 index 386acef56..000000000 --- a/KorolevAP/lab1/sample/main.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "tlink.h" - -int main() -{ - TLink link; - return 0; -} diff --git a/KorolevAP/lab1/src/tlink.cpp b/KorolevAP/lab1/src/tlink.cpp deleted file mode 100644 index 9353c50e5..000000000 --- a/KorolevAP/lab1/src/tlink.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "tlink.h" diff --git a/KustikovaVD/lab1/include/tstack.h b/KustikovaVD/lab1/include/tstack.h deleted file mode 100644 index 6f26683ed..000000000 --- a/KustikovaVD/lab1/include/tstack.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CLASSSAMPLE_H -#define CLASSSAMPLE_H - -struct Node -{ - int key; - Node* pNext; -}; - -#endif diff --git a/KustikovaVD/lab1/sample/main.cpp b/KustikovaVD/lab1/sample/main.cpp deleted file mode 100644 index 17ad1cb49..000000000 --- a/KustikovaVD/lab1/sample/main.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "tstack.h" - -int main() -{ - Node* n; - return 0; -} diff --git a/KustikovaVD/lab1/sln/sample/library/library.vcxproj b/KustikovaVD/lab1/sln/sample/library/library.vcxproj deleted file mode 100644 index 4d1ae8cc1..000000000 --- a/KustikovaVD/lab1/sln/sample/library/library.vcxproj +++ /dev/null @@ -1,80 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - {A5813F0D-39E4-4CAC-A38E-8FD694C6E687} - Win32Proj - library - - - - StaticLibrary - true - Unicode - - - StaticLibrary - false - true - Unicode - - - - - - - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters b/KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters deleted file mode 100644 index 00608379f..000000000 --- a/KustikovaVD/lab1/sln/sample/library/library.vcxproj.filters +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/KustikovaVD/lab1/sln/sample/sample.sln b/KustikovaVD/lab1/sln/sample/sample.sln deleted file mode 100644 index cab1f4292..000000000 --- a/KustikovaVD/lab1/sln/sample/sample.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample\sample.vcxproj", "{38AF47B5-5FAA-4951-B929-EE62D627A2BF}" - ProjectSection(ProjectDependencies) = postProject - {A5813F0D-39E4-4CAC-A38E-8FD694C6E687} = {A5813F0D-39E4-4CAC-A38E-8FD694C6E687} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "library\library.vcxproj", "{A5813F0D-39E4-4CAC-A38E-8FD694C6E687}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Debug|Win32.ActiveCfg = Debug|Win32 - {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Debug|Win32.Build.0 = Debug|Win32 - {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Release|Win32.ActiveCfg = Release|Win32 - {38AF47B5-5FAA-4951-B929-EE62D627A2BF}.Release|Win32.Build.0 = Release|Win32 - {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Debug|Win32.ActiveCfg = Debug|Win32 - {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Debug|Win32.Build.0 = Debug|Win32 - {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Release|Win32.ActiveCfg = Release|Win32 - {A5813F0D-39E4-4CAC-A38E-8FD694C6E687}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj b/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj deleted file mode 100644 index e353c82b8..000000000 --- a/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {38AF47B5-5FAA-4951-B929-EE62D627A2BF} - Win32Proj - sample - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ../../../include - - - Console - true - library.lib;%(AdditionalDependencies) - ../Debug - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ../../../include - - - Console - true - true - true - library.lib;%(AdditionalDependencies) - ../Release - - - - - - - - - \ No newline at end of file diff --git a/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters b/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters deleted file mode 100644 index e887328dd..000000000 --- a/KustikovaVD/lab1/sln/sample/sample/sample.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - \ No newline at end of file diff --git a/KustikovaVD/lab1/src/tstack.cpp b/KustikovaVD/lab1/src/tstack.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/VihrevIB/lab2/gtest/gtest-all.cc b/VihrevIB/lab2/gtest/gtest-all.cc new file mode 100644 index 000000000..ff9e51235 --- /dev/null +++ b/VihrevIB/lab2/gtest/gtest-all.cc @@ -0,0 +1,9592 @@ +// 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: mheule@google.com (Markus Heule) +// +// Google C++ Testing Framework (Google Test) +// +// Sometimes it's desirable to build Google Test by compiling a single file. +// This file serves this purpose. + +// This line ensures that gtest.h can be compiled on its own, even +// when it's fused. +#include "gtest.h" + +// The following lines pull in the real gtest *.cc files. +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) + +// 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) +// +// Utilities for testing Google Test itself and code that uses Google Test +// (e.g. frameworks built on top of Google Test). + +#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + + +namespace testing { + +// This helper class can be used to mock out Google Test failure reporting +// so that we can test Google Test or code that builds on Google Test. +// +// An object of this class appends a TestPartResult object to the +// TestPartResultArray object given in the constructor whenever a Google Test +// failure is reported. It can either intercept only failures that are +// generated in the same thread that created this object or it can intercept +// all generated failures. The scope of this mock object can be controlled with +// the second argument to the two arguments constructor. +class GTEST_API_ ScopedFakeTestPartResultReporter + : public TestPartResultReporterInterface { + public: + // The two possible mocking modes of this object. + enum InterceptMode { + INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. + INTERCEPT_ALL_THREADS // Intercepts all failures. + }; + + // The c'tor sets this object as the test part result reporter used + // by Google Test. The 'result' parameter specifies where to report the + // results. This reporter will only catch failures generated in the current + // thread. DEPRECATED + explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); + + // Same as above, but you can choose the interception scope of this object. + ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, + TestPartResultArray* result); + + // The d'tor restores the previous test part result reporter. + virtual ~ScopedFakeTestPartResultReporter(); + + // Appends the TestPartResult object to the TestPartResultArray + // received in the constructor. + // + // This method is from the TestPartResultReporterInterface + // interface. + virtual void ReportTestPartResult(const TestPartResult& result); + private: + void Init(); + + const InterceptMode intercept_mode_; + TestPartResultReporterInterface* old_reporter_; + TestPartResultArray* const result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); +}; + +namespace internal { + +// A helper class for implementing EXPECT_FATAL_FAILURE() and +// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +class GTEST_API_ SingleFailureChecker { + public: + // The constructor remembers the arguments. + SingleFailureChecker(const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr); + ~SingleFailureChecker(); + private: + const TestPartResultArray* const results_; + const TestPartResult::Type type_; + const string substr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); +}; + +} // namespace internal + +} // namespace testing + +// A set of macros for testing Google Test assertions or code that's expected +// to generate Google Test fatal failures. It verifies that the given +// statement will cause exactly one fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_FATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - 'statement' cannot reference local non-static variables or +// non-static members of the current object. +// - 'statement' cannot return a value. +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. The AcceptsMacroThatExpandsToUnprotectedComma test in +// gtest_unittest.cc will fail to compile if we do that. +#define EXPECT_FATAL_FAILURE(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ALL_THREADS, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +// A macro for testing Google Test assertions or code that's expected to +// generate Google Test non-fatal failures. It asserts that the given +// statement will cause exactly one non-fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// 'statement' is allowed to reference local variables and members of +// the current object. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. +#define EXPECT_NONFATAL_FAILURE(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ + >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // NOLINT +#include +#include + +#if GTEST_OS_LINUX + +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +# include // NOLINT +# include // NOLINT +# include // NOLINT +// Declares vsnprintf(). This header is not available on Windows. +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include + +#elif GTEST_OS_SYMBIAN +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +#elif GTEST_OS_ZOS +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +// On z/OS we additionally need strings.h for strcasecmp. +# include // NOLINT + +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. + +# include // NOLINT + +#elif GTEST_OS_WINDOWS // We are on Windows proper. + +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT + +# if GTEST_OS_WINDOWS_MINGW +// MinGW has gettimeofday() but not _ftime64(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +// TODO(kenton@google.com): There are other ways to get the time on +// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW +// supports these. consider using them instead. +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT +# endif // GTEST_OS_WINDOWS_MINGW + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT + +#else + +// Assume other platforms have gettimeofday(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT +# include // NOLINT + +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +// Copyright 2005, 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. + +// Utility functions and classes used by the Google C++ testing framework. +// +// Author: wan@google.com (Zhanyong Wan) +// +// This file contains purely Google Test's internal implementation. Please +// DO NOT #INCLUDE IT IN A USER PROGRAM. + +#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ +#define GTEST_SRC_GTEST_INTERNAL_INL_H_ + +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ +// A user is trying to include this from his code - just say no. +# error "gtest-internal-inl.h is part of Google Test's internal implementation." +# error "It must not be included except by Google Test itself." +#endif // GTEST_IMPLEMENTATION_ + +#ifndef _WIN32_WCE +# include +#endif // !_WIN32_WCE +#include +#include // For strtoll/_strtoul64/malloc/free. +#include // For memmove. + +#include +#include +#include + + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +#if GTEST_OS_WINDOWS +# include // NOLINT +#endif // GTEST_OS_WINDOWS + + +namespace testing { + +// Declares the flags. +// +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); + +namespace internal { + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; + +// Names of the flags (needed for parsing Google Test flags). +const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; +const char kBreakOnFailureFlag[] = "break_on_failure"; +const char kCatchExceptionsFlag[] = "catch_exceptions"; +const char kColorFlag[] = "color"; +const char kFilterFlag[] = "filter"; +const char kListTestsFlag[] = "list_tests"; +const char kOutputFlag[] = "output"; +const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; +const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kStreamResultToFlag[] = "stream_result_to"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Converts the given time in milliseconds to a date string in the ISO 8601 +// format, without the timezone information. N.B.: due to the use the +// non-reentrant localtime() function, this function is not thread safe. Do +// not use it in any code that can be called from multiple threads. +GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast(GetTimeInMillis()) : + static_cast(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast((raw_seed - 1U) % + static_cast(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} + +// This class saves the values of all Google Test flags in its c'tor, and +// restores them in its d'tor. +class GTestFlagSaver { + public: + // The c'tor. + GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); + break_on_failure_ = GTEST_FLAG(break_on_failure); + catch_exceptions_ = GTEST_FLAG(catch_exceptions); + color_ = GTEST_FLAG(color); + death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); + filter_ = GTEST_FLAG(filter); + internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); + list_tests_ = GTEST_FLAG(list_tests); + output_ = GTEST_FLAG(output); + print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); + repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + stream_result_to_ = GTEST_FLAG(stream_result_to); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); + } + + // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. + ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; + GTEST_FLAG(break_on_failure) = break_on_failure_; + GTEST_FLAG(catch_exceptions) = catch_exceptions_; + GTEST_FLAG(color) = color_; + GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; + GTEST_FLAG(filter) = filter_; + GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; + GTEST_FLAG(list_tests) = list_tests_; + GTEST_FLAG(output) = output_; + GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; + GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(stream_result_to) = stream_result_to_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; + } + + private: + // Fields for saving the original values of flags. + bool also_run_disabled_tests_; + bool break_on_failure_; + bool catch_exceptions_; + std::string color_; + std::string death_test_style_; + bool death_test_use_fork_; + std::string filter_; + std::string internal_run_death_test_; + bool list_tests_; + std::string output_; + bool print_time_; + internal::Int32 random_seed_; + internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + std::string stream_result_to_; + bool throw_on_failure_; +} GTEST_ATTRIBUTE_UNUSED_; + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template +inline int CountIf(const Container& c, Predicate predicate) { + // Implemented as an explicit loop since std::count_if() in libCstd on + // Solaris has a non-standard signature. + int count = 0; + for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { + if (predicate(*it)) + ++count; + } + return count; +} + +// Applies a function/functor to each element in the container. +template +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} + +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template +inline E GetElementOr(const std::vector& v, int i, E default_value) { + return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; +} + +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector* v) { + const int size = static_cast(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); + } +} + +// Performs an in-place shuffle of the vector's elements. +template +inline void Shuffle(internal::Random* random, std::vector* v) { + ShuffleRange(random, 0, static_cast(v->size()), v); +} + +// A function for deleting an object. Handy for being used as a +// functor. +template +static void Delete(T* x) { + delete x; +} + +// A predicate that checks the key of a TestProperty against a known key. +// +// TestPropertyKeyIs is copyable. +class TestPropertyKeyIs { + public: + // Constructor. + // + // TestPropertyKeyIs has NO default constructor. + explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} + + // Returns true iff the test name of test property matches on key_. + bool operator()(const TestProperty& test_property) const { + return test_property.key() == key_; + } + + private: + std::string key_; +}; + +// Class UnitTestOptions. +// +// This class contains functions for processing options the user +// specifies when running the tests. It has only static members. +// +// In most cases, the user can specify an option using either an +// environment variable or a command line flag. E.g. you can set the +// test filter using either GTEST_FILTER or --gtest_filter. If both +// the variable and the flag are present, the latter overrides the +// former. +class GTEST_API_ UnitTestOptions { + public: + // Functions for processing the gtest_output flag. + + // Returns the output format, or "" for normal printed output. + static std::string GetOutputFormat(); + + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static std::string GetAbsolutePathToOutputFile(); + + // Functions for processing the gtest_filter flag. + + // Returns true iff the wildcard pattern matches the string. The + // first ':' or '\0' character in pattern marks the end of it. + // + // This recursive algorithm isn't very efficient, but is clear and + // works well enough for matching test names, which are short. + static bool PatternMatchesString(const char *pattern, const char *str); + + // Returns true iff the user-specified filter matches the test case + // name and the test name. + static bool FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name); + +#if GTEST_OS_WINDOWS + // Function for supporting the gtest_catch_exception flag. + + // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the + // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. + // This function is useful as an __except condition. + static int GTestShouldProcessSEH(DWORD exception_code); +#endif // GTEST_OS_WINDOWS + + // Returns true if "name" matches the ':' separated list of glob-style + // filters in "filter". + static bool MatchesFilter(const std::string& name, const char* filter); +}; + +// Returns the current application's name, removing directory path if that +// is present. Used by UnitTestOptions::GetOutputFile. +GTEST_API_ FilePath GetCurrentExecutableName(); + +// The role interface for getting the OS stack trace as a string. +class OsStackTraceGetterInterface { + public: + OsStackTraceGetterInterface() {} + virtual ~OsStackTraceGetterInterface() {} + + // Returns the current OS stack trace as an std::string. Parameters: + // + // max_depth - the maximum number of stack frames to be included + // in the trace. + // skip_count - the number of top frames to be skipped; doesn't count + // against max_depth. + virtual string CurrentStackTrace(int max_depth, int skip_count) = 0; + + // UponLeavingGTest() should be called immediately before Google Test calls + // user code. It saves some information about the current stack that + // CurrentStackTrace() will use to find and hide Google Test stack frames. + virtual void UponLeavingGTest() = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); +}; + +// A working implementation of the OsStackTraceGetterInterface interface. +class OsStackTraceGetter : public OsStackTraceGetterInterface { + public: + OsStackTraceGetter() : caller_frame_(NULL) {} + + virtual string CurrentStackTrace(int max_depth, int skip_count) + GTEST_LOCK_EXCLUDED_(mutex_); + + virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_); + + // This string is inserted in place of stack frames that are part of + // Google Test's implementation. + static const char* const kElidedFramesMarker; + + private: + Mutex mutex_; // protects all internal state + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to CurrentStackTrace() from within the user code. + void* caller_frame_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); +}; + +// Information about a Google Test trace point. +struct TraceInfo { + const char* file; + int line; + std::string message; +}; + +// This is the default global test part result reporter used in UnitTestImpl. +// This class should only be used by UnitTestImpl. +class DefaultGlobalTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. Reports the test part + // result in the current test. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); +}; + +// This is the default per thread test part result reporter used in +// UnitTestImpl. This class should only be used by UnitTestImpl. +class DefaultPerThreadTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. The implementation just + // delegates to the current global test part result reporter of *unit_test_. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); +}; + +// The private implementation of the UnitTest class. We don't protect +// the methods under a mutex, as this class is not accessible by a +// user and the UnitTest class that delegates work to this class does +// proper locking. +class GTEST_API_ UnitTestImpl { + public: + explicit UnitTestImpl(UnitTest* parent); + virtual ~UnitTestImpl(); + + // There are two different ways to register your own TestPartResultReporter. + // You can register your own repoter to listen either only for test results + // from the current thread or for results from all threads. + // By default, each per-thread test result repoter just passes a new + // TestPartResult to the global test result reporter, which registers the + // test part result for the currently running test. + + // Returns the global test part result reporter. + TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); + + // Sets the global test part result reporter. + void SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter); + + // Returns the test part result reporter for the current thread. + TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); + + // Sets the test part result reporter for the current thread. + void SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter); + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const { return start_timestamp_; } + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const { return !Failed(); } + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const { + return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; + } + + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); + + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } + + // Sets the OS stack trace getter. + // + // Does nothing if the input and the current OS stack trace getter + // are the same; otherwise, deletes the old getter and makes the + // input the current getter. + void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); + + // Returns the current OS stack trace getter if it is not NULL; + // otherwise, creates an OsStackTraceGetter, makes it the current + // getter, and returns it. + OsStackTraceGetterInterface* os_stack_trace_getter(); + + // Returns the current OS stack trace as an std::string. + // + // The maximum number of stack frames to be included is specified by + // the gtest_stack_trace_depth flag. The skip_count parameter + // specifies the number of top frames to be skipped, which doesn't + // count against the number of frames to be included. + // + // For example, if Foo() calls Bar(), which in turn calls + // CurrentOsStackTraceExceptTop(1), Foo() will be included in the + // trace but Bar() and CurrentOsStackTraceExceptTop() won't. + std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; + + // Finds and returns a TestCase with the given name. If one doesn't + // exist, creates one and returns it. + // + // Arguments: + // + // test_case_name: name of the test case + // type_param: the name of the test's type parameter, or NULL if + // this is not a typed or a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase* GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Adds a TestInfo to the unit test. + // + // Arguments: + // + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + // test_info: the TestInfo object + void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + TestInfo* test_info) { + // In order to support thread-safe death tests, we need to + // remember the original working directory when the test program + // was first invoked. We cannot do this in RUN_ALL_TESTS(), as + // the user may have changed the current directory before calling + // RUN_ALL_TESTS(). Therefore we capture the current directory in + // AddTestInfo(), which is called to register a TEST or TEST_F + // before main() is reached. + if (original_working_dir_.IsEmpty()) { + original_working_dir_.Set(FilePath::GetCurrentDir()); + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; + } + + GetTestCase(test_info->test_case_name(), + test_info->type_param(), + set_up_tc, + tear_down_tc)->AddTestInfo(test_info); + } + +#if GTEST_HAS_PARAM_TEST + // Returns ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + return parameterized_test_registry_; + } +#endif // GTEST_HAS_PARAM_TEST + + // Sets the TestCase object for the test that's currently running. + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; + } + + // Sets the TestInfo object for the test that's currently running. If + // current_test_info is NULL, the assertion results will be stored in + // ad_hoc_test_result_. + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; + } + + // Registers all parameterized tests defined using TEST_P and + // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // combination. This method can be called more then once; it has guards + // protecting from registering the tests more then once. If + // value-parameterized tests are disabled, RegisterParameterizedTests is + // present but does nothing. + void RegisterParameterizedTests(); + + // Runs all tests in this UnitTest object, prints the result, and + // returns true if all tests are successful. If any exception is + // thrown during a test, this test is considered to be failed, but + // the rest of the tests will still be run. + bool RunAllTests(); + + // Clears the results of all tests, except the ad hoc tests. + void ClearNonAdHocTestResult() { + ForEach(test_cases_, TestCase::ClearTestCaseResult); + } + + // Clears the results of ad-hoc test assertions. + void ClearAdHocTestResult() { + ad_hoc_test_result_.Clear(); + } + + // Adds a TestProperty to the current TestResult object when invoked in a + // context of a test or a test case, or to the global property set. If the + // result already contains a property with the same key, the value will be + // updated. + void RecordProperty(const TestProperty& test_property); + + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + + // Matches the full name of each test against the user-specified + // filter to decide whether the test should run, then records the + // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. + // Returns the number of tests that should run. + int FilterTests(ReactionToSharding shard_tests); + + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); + + const TestCase* current_test_case() const { return current_test_case_; } + TestInfo* current_test_info() { return current_test_info_; } + const TestInfo* current_test_info() const { return current_test_info_; } + + // Returns the vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector& environments() { return environments_; } + + // Getters for the per-thread Google Test trace stack. + std::vector& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); + } + const std::vector& gtest_trace_stack() const { + return gtest_trace_stack_.get(); + } + +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } + // Returns a pointer to the parsed --gtest_internal_run_death_test + // flag, or NULL if that flag was not specified. + // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. + const InternalRunDeathTestFlag* internal_run_death_test_flag() const { + return internal_run_death_test_flag_.get(); + } + + // Returns a pointer to the current death test factory. + internal::DeathTestFactory* death_test_factory() { + return death_test_factory_.get(); + } + + void SuppressTestEventsIfInSubprocess(); + + friend class ReplaceDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Initializes the event listener for streaming test results to a socket. + // Must not be called before InitGoogleTest. + void ConfigureStreamingOutput(); +#endif + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + + // Returns the value of GTEST_FLAG(catch_exceptions) at the moment + // UnitTest::Run() starts. + bool catch_exceptions() const { return catch_exceptions_; } + + private: + friend class ::testing::UnitTest; + + // Used by UnitTest::Run() to capture the state of + // GTEST_FLAG(catch_exceptions) at the moment it starts. + void set_catch_exceptions(bool value) { catch_exceptions_ = value; } + + // The UnitTest object that owns this implementation object. + UnitTest* const parent_; + + // The working directory when the first TEST() or TEST_F() was + // executed. + internal::FilePath original_working_dir_; + + // The default test part result reporters. + DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; + DefaultPerThreadTestPartResultReporter + default_per_thread_test_part_result_reporter_; + + // Points to (but doesn't own) the global test part result reporter. + TestPartResultReporterInterface* global_test_part_result_repoter_; + + // Protects read and write access to global_test_part_result_reporter_. + internal::Mutex global_test_part_result_reporter_mutex_; + + // Points to (but doesn't own) the per-thread test part result reporter. + internal::ThreadLocal + per_thread_test_part_result_reporter_; + + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector test_cases_; + + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector test_case_indices_; + +#if GTEST_HAS_PARAM_TEST + // ParameterizedTestRegistry object used to register value-parameterized + // tests. + internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + + // Indicates whether RegisterParameterizedTests() has been called already. + bool parameterized_tests_registered_; +#endif // GTEST_HAS_PARAM_TEST + + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; + + // This points to the TestCase for the currently running test. It + // changes as Google Test goes through one test case after another. + // When no test is running, this is set to NULL and Google Test + // stores assertion results in ad_hoc_test_result_. Initially NULL. + TestCase* current_test_case_; + + // This points to the TestInfo for the currently running test. It + // changes as Google Test goes through one test after another. When + // no test is running, this is set to NULL and Google Test stores + // assertion results in ad_hoc_test_result_. Initially NULL. + TestInfo* current_test_info_; + + // Normally, a user only writes assertions inside a TEST or TEST_F, + // or inside a function called by a TEST or TEST_F. Since Google + // Test keeps track of which test is current running, it can + // associate such an assertion with the test it belongs to. + // + // If an assertion is encountered when no TEST or TEST_F is running, + // Google Test attributes the assertion result to an imaginary "ad hoc" + // test, and records the result in ad_hoc_test_result_. + TestResult ad_hoc_test_result_; + + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; + + // The OS stack trace getter. Will be deleted when the UnitTest + // object is destructed. By default, an OsStackTraceGetter is used, + // but the user can set this field to use a custom getter if that is + // desired. + OsStackTraceGetterInterface* os_stack_trace_getter_; + + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + + // The time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp_; + + // How long the test took to run, in milliseconds. + TimeInMillis elapsed_time_; + +#if GTEST_HAS_DEATH_TEST + // The decomposed components of the gtest_internal_run_death_test flag, + // parsed when RUN_ALL_TESTS is called. + internal::scoped_ptr internal_run_death_test_flag_; + internal::scoped_ptr death_test_factory_; +#endif // GTEST_HAS_DEATH_TEST + + // A per-thread stack of traces created by the SCOPED_TRACE() macro. + internal::ThreadLocal > gtest_trace_stack_; + + // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() + // starts. + bool catch_exceptions_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); +}; // class UnitTestImpl + +// Convenience function for accessing the global UnitTest +// implementation object. +inline UnitTestImpl* GetUnitTestImpl() { + return UnitTest::GetInstance()->impl(); +} + +#if GTEST_USES_SIMPLE_RE + +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsAsciiDigit(char ch); +GTEST_API_ bool IsAsciiPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsAsciiWhiteSpace(char ch); +GTEST_API_ bool IsAsciiWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + +#endif // GTEST_USES_SIMPLE_RE + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +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 +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !IsDigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. + +# if GTEST_OS_WINDOWS && !defined(__GNUC__) + + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); + +# else + + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); + +# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast(parsed); + if (parse_success && static_cast(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const std::string& xml_element, + const TestProperty& property) { + test_result->RecordProperty(xml_element, property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; + +#if GTEST_CAN_STREAM_RESULTS_ + +// Streams test results to the given port on the given host machine. +class StreamingListener : public EmptyTestEventListener { + public: + // Abstract base class for writing strings to a socket. + class AbstractSocketWriter { + public: + virtual ~AbstractSocketWriter() {} + + // Sends a string to the socket. + virtual void Send(const string& message) = 0; + + // Closes the socket. + virtual void CloseConnection() {} + + // Sends a string and a newline to the socket. + void SendLn(const string& message) { + Send(message + "\n"); + } + }; + + // Concrete class for actually writing strings to a socket. + class SocketWriter : public AbstractSocketWriter { + public: + SocketWriter(const string& host, const string& port) + : sockfd_(-1), host_name_(host), port_num_(port) { + MakeConnection(); + } + + virtual ~SocketWriter() { + if (sockfd_ != -1) + CloseConnection(); + } + + // Sends a string to the socket. + virtual void Send(const string& message) { + GTEST_CHECK_(sockfd_ != -1) + << "Send() can be called only when there is a connection."; + + const int len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != len) { + GTEST_LOG_(WARNING) + << "stream_result_to: failed to stream to " + << host_name_ << ":" << port_num_; + } + } + + private: + // Creates a client socket and connects to the server. + void MakeConnection(); + + // Closes the socket. + void CloseConnection() { + GTEST_CHECK_(sockfd_ != -1) + << "CloseConnection() can be called only when there is a connection."; + + close(sockfd_); + sockfd_ = -1; + } + + int sockfd_; // socket file descriptor + const string host_name_; + const string port_num_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); + }; // class SocketWriter + + // Escapes '=', '&', '%', and '\n' characters in str as "%xx". + static string UrlEncode(const char* str); + + StreamingListener(const string& host, const string& port) + : socket_writer_(new SocketWriter(host, port)) { Start(); } + + explicit StreamingListener(AbstractSocketWriter* socket_writer) + : socket_writer_(socket_writer) { Start(); } + + void OnTestProgramStart(const UnitTest& /* unit_test */) { + SendLn("event=TestProgramStart"); + } + + void OnTestProgramEnd(const UnitTest& unit_test) { + // Note that Google Test current only report elapsed time for each + // test iteration, not for the entire test program. + SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); + + // Notify the streaming server to stop. + socket_writer_->CloseConnection(); + } + + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + SendLn("event=TestIterationStart&iteration=" + + StreamableToString(iteration)); + } + + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + SendLn("event=TestIterationEnd&passed=" + + FormatBool(unit_test.Passed()) + "&elapsed_time=" + + StreamableToString(unit_test.elapsed_time()) + "ms"); + } + + void OnTestCaseStart(const TestCase& test_case) { + SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); + } + + void OnTestCaseEnd(const TestCase& test_case) { + SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + + "ms"); + } + + void OnTestStart(const TestInfo& test_info) { + SendLn(std::string("event=TestStart&name=") + test_info.name()); + } + + void OnTestEnd(const TestInfo& test_info) { + SendLn("event=TestEnd&passed=" + + FormatBool((test_info.result())->Passed()) + + "&elapsed_time=" + + StreamableToString((test_info.result())->elapsed_time()) + "ms"); + } + + void OnTestPartResult(const TestPartResult& test_part_result) { + const char* file_name = test_part_result.file_name(); + if (file_name == NULL) + file_name = ""; + SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + + "&line=" + StreamableToString(test_part_result.line_number()) + + "&message=" + UrlEncode(test_part_result.message())); + } + + private: + // Sends the given message and a newline to the socket. + void SendLn(const string& message) { socket_writer_->SendLn(message); } + + // Called at the start of streaming to notify the receiver what + // protocol we are using. + void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } + + string FormatBool(bool value) { return value ? "1" : "0"; } + + const scoped_ptr socket_writer_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); +}; // class StreamingListener + +#endif // GTEST_CAN_STREAM_RESULTS_ + +} // namespace internal +} // namespace testing + +#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ +#undef GTEST_IMPLEMENTATION_ + +#if GTEST_OS_WINDOWS +# define vsnprintf _vsnprintf +#endif // GTEST_OS_WINDOWS + +namespace testing { + +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + +// Constants. + +// A test whose test case name or test name matches this filter is +// disabled and not run. +static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; + +// A test case whose name matches this filter is considered a death +// test case and will be run before test cases whose name doesn't +// match this filter. +static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; + +// A test filter that matches everything. +static const char kUniversalFilter[] = "*"; + +// The default output file for XML output. +static const char kDefaultOutputFile[] = "test_detail.xml"; + +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + +namespace internal { + +// The text used in failure messages to indicate the start of the +// stack trace. +const char kStackTraceMarker[] = "\nStack trace:\n"; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + +} // namespace internal + +static const char* GetDefaultFilter() { + return kUniversalFilter; +} + +GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( + break_on_failure, + internal::BoolFromGTestEnv("break_on_failure", false), + "True iff a failed assertion should be a debugger break-point."); + +GTEST_DEFINE_bool_( + catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True iff " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); + +GTEST_DEFINE_string_( + color, + internal::StringFromGTestEnv("color", "auto"), + "Whether to use colors in the output. Valid values: yes, no, " + "and auto. 'auto' means to use colors if the output is " + "being sent to a terminal and the TERM environment variable " + "is set to a terminal type that supports colors."); + +GTEST_DEFINE_string_( + filter, + internal::StringFromGTestEnv("filter", GetDefaultFilter()), + "A colon-separated list of glob (not regex) patterns " + "for filtering the tests to run, optionally followed by a " + "'-' and a : separated list of negative patterns (tests to " + "exclude). A test is run if it matches one of the positive " + "patterns and does not match any of the negative patterns."); + +GTEST_DEFINE_bool_(list_tests, false, + "List all tests without running them."); + +GTEST_DEFINE_string_( + output, + internal::StringFromGTestEnv("output", ""), + "A format (currently must be \"xml\"), optionally followed " + "by a colon and an output file name or directory. A directory " + "is indicated by a trailing pathname separator. " + "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " + "If a directory is specified, output files will be created " + "within that directory, with file-names based on the test " + "executable's name and, if necessary, made unique by adding " + "digits."); + +GTEST_DEFINE_bool_( + print_time, + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( + repeat, + internal::Int32FromGTestEnv("repeat", 1), + "How many times to repeat each test. Specify a negative number " + "for repeating forever. Useful for shaking out flaky tests."); + +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + +GTEST_DEFINE_int32_( + stack_trace_depth, + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + "The maximum number of stack frames to print when an " + "assertion fails. The valid range is 0 through 100, inclusive."); + +GTEST_DEFINE_string_( + stream_result_to, + internal::StringFromGTestEnv("stream_result_to", ""), + "This flag specifies the host name and the port number on which to stream " + "test results. Example: \"localhost:555\". The flag is effective only on " + "Linux."); + +GTEST_DEFINE_bool_( + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); + +namespace internal { + +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + +// GTestIsInitialized() returns true iff the user has initialized +// Google Test. Useful for catching the user mistake of not initializing +// Google Test before calling RUN_ALL_TESTS(). +// +// A user must call testing::InitGoogleTest() to initialize Google +// Test. g_init_gtest_count is set to the number of times +// InitGoogleTest() has been called. We don't protect this variable +// under a mutex as it is only accessed in the main thread. +GTEST_API_ int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } + +// Iterates over a vector of TestCases, keeping a running sum of the +// results of calling a given int-returning method on each. +// Returns the sum. +static int SumOverTestCaseList(const std::vector& case_list, + int (TestCase::*method)() const) { + int sum = 0; + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); + } + return sum; +} + +// Returns true iff the test case passed. +static bool TestCasePassed(const TestCase* test_case) { + return test_case->should_run() && test_case->Passed(); +} + +// Returns true iff the test case failed. +static bool TestCaseFailed(const TestCase* test_case) { + return test_case->should_run() && test_case->Failed(); +} + +// Returns true iff test_case contains at least one test that should +// run. +static bool ShouldRunTestCase(const TestCase* test_case) { + return test_case->should_run(); +} + +// AssertHelper constructor. +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; +} + +// Message assignment, for assertion streaming support. +void AssertHelper::operator=(const Message& message) const { + UnitTest::GetInstance()-> + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), + UnitTest::GetInstance()->impl() + ->CurrentOsStackTraceExceptTop(1) + // Skips the stack frame for this function itself. + ); // NOLINT +} + +// Mutex for linked pointers. +GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// Application pathname gotten in InitGoogleTest. +std::string g_executable_path; + +// Returns the current application's name, removing directory path if that +// is present. +FilePath GetCurrentExecutableName() { + FilePath result; + +#if GTEST_OS_WINDOWS + result.Set(FilePath(g_executable_path).RemoveExtension("exe")); +#else + result.Set(FilePath(g_executable_path)); +#endif // GTEST_OS_WINDOWS + + return result.RemoveDirectoryName(); +} + +// Functions for processing the gtest_output flag. + +// Returns the output format, or "" for normal printed output. +std::string UnitTestOptions::GetOutputFormat() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) return std::string(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + return (colon == NULL) ? + std::string(gtest_output_flag) : + std::string(gtest_output_flag, colon - gtest_output_flag); +} + +// Returns the name of the requested output file, or the default if none +// was explicitly specified. +std::string UnitTestOptions::GetAbsolutePathToOutputFile() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) + return ""; + + const char* const colon = strchr(gtest_output_flag, ':'); + if (colon == NULL) + return internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).string(); + + internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + + if (!output_name.IsDirectory()) + return output_name.string(); + + internal::FilePath result(internal::FilePath::GenerateUniqueFileName( + output_name, internal::GetCurrentExecutableName(), + GetOutputFormat().c_str())); + return result.string(); +} + +// Returns true iff the wildcard pattern matches the string. The +// first ':' or '\0' character in pattern marks the end of it. +// +// This recursive algorithm isn't very efficient, but is clear and +// works well enough for matching test names, which are short. +bool UnitTestOptions::PatternMatchesString(const char *pattern, + const char *str) { + switch (*pattern) { + case '\0': + case ':': // Either ':' or '\0' marks the end of the pattern. + return *str == '\0'; + case '?': // Matches any single character. + return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); + case '*': // Matches any string (possibly empty) of characters. + return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || + PatternMatchesString(pattern + 1, str); + default: // Non-special character. Matches itself. + return *pattern == *str && + PatternMatchesString(pattern + 1, str + 1); + } +} + +bool UnitTestOptions::MatchesFilter( + const std::string& name, const char* filter) { + const char *cur_pattern = filter; + for (;;) { + if (PatternMatchesString(cur_pattern, name.c_str())) { + return true; + } + + // Finds the next pattern in the filter. + cur_pattern = strchr(cur_pattern, ':'); + + // Returns if no more pattern can be found. + if (cur_pattern == NULL) { + return false; + } + + // Skips the pattern separater (the ':' character). + cur_pattern++; + } +} + +// Returns true iff the user-specified filter matches the test case +// name and the test name. +bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name) { + const std::string& full_name = test_case_name + "." + test_name.c_str(); + + // Split --gtest_filter at '-', if there is one, to separate into + // positive filter and negative filter portions + const char* const p = GTEST_FLAG(filter).c_str(); + const char* const dash = strchr(p, '-'); + std::string positive; + std::string negative; + if (dash == NULL) { + positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter + negative = ""; + } else { + positive = std::string(p, dash); // Everything up to the dash + negative = std::string(dash + 1); // Everything after the dash + if (positive.empty()) { + // Treat '-test1' as the same as '*-test1' + positive = kUniversalFilter; + } + } + + // A filter is a colon-separated list of patterns. It matches a + // test if any pattern in it matches the test. + return (MatchesFilter(full_name, positive.c_str()) && + !MatchesFilter(full_name, negative.c_str())); +} + +#if GTEST_HAS_SEH +// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the +// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. +// This function is useful as an __except condition. +int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { + // Google Test should handle a SEH exception if: + // 1. the user wants it to, AND + // 2. this is not a breakpoint exception, AND + // 3. this is not a C++ exception (VC++ implements them via SEH, + // apparently). + // + // SEH exception code for C++ exceptions. + // (see http://support.microsoft.com/kb/185294 for more information). + const DWORD kCxxExceptionCode = 0xe06d7363; + + bool should_handle = true; + + if (!GTEST_FLAG(catch_exceptions)) + should_handle = false; + else if (exception_code == EXCEPTION_BREAKPOINT) + should_handle = false; + else if (exception_code == kCxxExceptionCode) + should_handle = false; + + return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +} +#endif // GTEST_HAS_SEH + +} // namespace internal + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. Intercepts only failures from the current thread. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + TestPartResultArray* result) + : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), + result_(result) { + Init(); +} + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + InterceptMode intercept_mode, TestPartResultArray* result) + : intercept_mode_(intercept_mode), + result_(result) { + Init(); +} + +void ScopedFakeTestPartResultReporter::Init() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + old_reporter_ = impl->GetGlobalTestPartResultReporter(); + impl->SetGlobalTestPartResultReporter(this); + } else { + old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); + impl->SetTestPartResultReporterForCurrentThread(this); + } +} + +// The d'tor restores the test part result reporter used by Google Test +// before. +ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + impl->SetGlobalTestPartResultReporter(old_reporter_); + } else { + impl->SetTestPartResultReporterForCurrentThread(old_reporter_); + } +} + +// Increments the test part result count and remembers the result. +// This method is from the TestPartResultReporterInterface interface. +void ScopedFakeTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + result_->Append(result); +} + +namespace internal { + +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + +// This predicate-formatter checks that 'results' contains a test part +// failure of the given type and that the failure message contains the +// given substring. +AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const string& substr) { + const std::string expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); + Message msg; + if (results.size() != 1) { + msg << "Expected: " << expected << "\n" + << " Actual: " << results.size() << " failures"; + for (int i = 0; i < results.size(); i++) { + msg << "\n" << results.GetTestPartResult(i); + } + return AssertionFailure() << msg; + } + + const TestPartResult& r = results.GetTestPartResult(0); + if (r.type() != type) { + return AssertionFailure() << "Expected: " << expected << "\n" + << " Actual:\n" + << r; + } + + if (strstr(r.message(), substr.c_str()) == NULL) { + return AssertionFailure() << "Expected: " << expected << " containing \"" + << substr << "\"\n" + << " Actual:\n" + << r; + } + + return AssertionSuccess(); +} + +// The constructor of SingleFailureChecker remembers where to look up +// test part results, what type of failure we expect, and what +// substring the failure message should contain. +SingleFailureChecker:: SingleFailureChecker( + const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr) + : results_(results), + type_(type), + substr_(substr) {} + +// The destructor of SingleFailureChecker verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +SingleFailureChecker::~SingleFailureChecker() { + EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); +} + +DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultGlobalTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->current_test_result()->AddTestPartResult(result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); +} + +DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); +} + +// Returns the global test part result reporter. +TestPartResultReporterInterface* +UnitTestImpl::GetGlobalTestPartResultReporter() { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + return global_test_part_result_repoter_; +} + +// Sets the global test part result reporter. +void UnitTestImpl::SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter) { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + global_test_part_result_repoter_ = reporter; +} + +// Returns the test part result reporter for the current thread. +TestPartResultReporterInterface* +UnitTestImpl::GetTestPartResultReporterForCurrentThread() { + return per_thread_test_part_result_reporter_.get(); +} + +// Sets the test part result reporter for the current thread. +void UnitTestImpl::SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter) { + per_thread_test_part_result_reporter_.set(reporter); +} + +// Gets the number of successful test cases. +int UnitTestImpl::successful_test_case_count() const { + return CountIf(test_cases_, TestCasePassed); +} + +// Gets the number of failed test cases. +int UnitTestImpl::failed_test_case_count() const { + return CountIf(test_cases_, TestCaseFailed); +} + +// Gets the number of all test cases. +int UnitTestImpl::total_test_case_count() const { + return static_cast(test_cases_.size()); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTestImpl::test_case_to_run_count() const { + return CountIf(test_cases_, ShouldRunTestCase); +} + +// Gets the number of successful tests. +int UnitTestImpl::successful_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); +} + +// Gets the number of failed tests. +int UnitTestImpl::failed_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTestImpl::reportable_disabled_test_count() const { + return SumOverTestCaseList(test_cases_, + &TestCase::reportable_disabled_test_count); +} + +// Gets the number of disabled tests. +int UnitTestImpl::disabled_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTestImpl::reportable_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count); +} + +// Gets the number of all tests. +int UnitTestImpl::total_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); +} + +// Gets the number of tests that should run. +int UnitTestImpl::test_to_run_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// CurrentOsStackTraceExceptTop(1), Foo() will be included in the +// trace but Bar() and CurrentOsStackTraceExceptTop() won't. +std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { + (void)skip_count; + return ""; +} + +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. + // http://analogous.blogspot.com/2005/04/epoch.html + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast(116444736UL) * 100000UL; + const DWORD kTenthMicrosInMilliSecond = 10000; + + SYSTEMTIME now_systime; + FILETIME now_filetime; + ULARGE_INTEGER now_int64; + // TODO(kenton@google.com): Shouldn't this just use + // GetSystemTimeAsFileTime()? + GetSystemTime(&now_systime); + if (SystemTimeToFileTime(&now_systime, &now_filetime)) { + now_int64.LowPart = now_filetime.dwLowDateTime; + now_int64.HighPart = now_filetime.dwHighDateTime; + now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - + kJavaEpochToWinFileTimeDelta; + return now_int64.QuadPart; + } + return 0; +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ + __timeb64 now; + +# ifdef _MSC_VER + + // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 + // (deprecated function) there. + // TODO(kenton@google.com): Use GetTickCount()? Or use + // SystemTimeToFileTime() +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + _ftime64(&now); +# pragma warning(pop) // Restores the warning state. +# else + + _ftime64(&now); + +# endif // _MSC_VER + + return static_cast(now.time) * 1000 + now.millitm; +#elif GTEST_HAS_GETTIMEOFDAY_ + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; +#else +# error "Don't know how to get the current time on your system." +#endif +} + +// Utilities + +// class String. + +#if GTEST_OS_WINDOWS_MOBILE +// Creates a UTF-16 wide string from the given ANSI string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the wide string, or NULL if the +// input is NULL. +LPCWSTR String::AnsiToUtf16(const char* ansi) { + if (!ansi) return NULL; + const int length = strlen(ansi); + const int unicode_length = + MultiByteToWideChar(CP_ACP, 0, ansi, length, + NULL, 0); + WCHAR* unicode = new WCHAR[unicode_length + 1]; + MultiByteToWideChar(CP_ACP, 0, ansi, length, + unicode, unicode_length); + unicode[unicode_length] = 0; + return unicode; +} + +// Creates an ANSI string from the given wide string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the ANSI string, or NULL if the +// input is NULL. +const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { + if (!utf16_str) return NULL; + const int ansi_length = + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + NULL, 0, NULL, NULL); + char* ansi = new char[ansi_length + 1]; + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + ansi, ansi_length, NULL, NULL); + ansi[ansi_length] = 0; + return ansi; +} + +#endif // GTEST_OS_WINDOWS_MOBILE + +// Compares two C strings. Returns true iff they have the same content. +// +// Unlike strcmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CStringEquals(const char * lhs, const char * rhs) { + if ( lhs == NULL ) return rhs == NULL; + + if ( rhs == NULL ) return false; + + return strcmp(lhs, rhs) == 0; +} + +#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +// Converts an array of wide chars to a narrow string using the UTF-8 +// encoding, and streams the result to the given Message object. +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, + Message* msg) { + for (size_t i = 0; i != length; ) { // NOLINT + if (wstr[i] != L'\0') { + *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); + while (i != length && wstr[i] != L'\0') + i++; + } else { + *msg << '\0'; + i++; + } + } +} + +#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +} // namespace internal + +// Constructs an empty Message. +// We allocate the stringstream separately because otherwise each use of +// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's +// stack frame leading to huge stack frames in some cases; gcc does not reuse +// the stack space. +Message::Message() : ss_(new ::std::stringstream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); +} + +// These two overloads allow streaming a wide C string to a Message +// using the UTF-8 encoding. +Message& Message::operator <<(const wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} +Message& Message::operator <<(wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} + +#if GTEST_HAS_STD_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::std::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Gets the text streamed to this object so far as an std::string. +// Each '\0' character in the buffer is replaced with "\\0". +std::string Message::GetString() const { + return internal::StringStreamToString(ss_.get()); +} + +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new ::std::string(*other.message_) : + static_cast< ::std::string*>(NULL)) { +} + +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} + +// Makes a successful assertion result. +AssertionResult AssertionSuccess() { + return AssertionResult(true); +} + +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. +AssertionResult AssertionFailure(const Message& message) { + return AssertionFailure() << message; +} + +namespace internal { + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case) { + Message msg; + msg << "Value of: " << actual_expression; + if (actual_value != actual_expression) { + msg << "\n Actual: " << actual_value; + } + + msg << "\nExpected: " << expected_expression; + if (ignoring_case) { + msg << " (ignoring case)"; + } + if (expected_value != expected_expression) { + msg << "\nWhich is: " << expected_value; + } + + return AssertionFailure() << msg; +} + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +// Helper function for implementing ASSERT_NEAR. +AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error) { + const double diff = fabs(val1 - val2); + if (diff <= abs_error) return AssertionSuccess(); + + // TODO(wan): do not print the value of an expression if it's + // already a literal. + return AssertionFailure() + << "The difference between " << expr1 << " and " << expr2 + << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} + + +// Helper template for implementing FloatLE() and DoubleLE(). +template +AssertionResult FloatingPointLE(const char* expr1, + const char* expr2, + RawType val1, + RawType val2) { + // Returns success if val1 is less than val2, + if (val1 < val2) { + return AssertionSuccess(); + } + + // or if val1 is almost equal to val2. + const FloatingPoint lhs(val1), rhs(val2); + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + // Note that the above two checks will both fail if either val1 or + // val2 is NaN, as the IEEE floating-point standard requires that + // any predicate involving a NaN must return false. + + ::std::stringstream val1_ss; + val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val1; + + ::std::stringstream val2_ss; + val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val2; + + return AssertionFailure() + << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" + << " Actual: " << StringStreamToString(&val1_ss) << " vs " + << StringStreamToString(&val2_ss); +} + +} // namespace internal + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +namespace internal { + +// The helper function for {ASSERT|EXPECT}_EQ with int or enum +// arguments. +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + if (expected == actual) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here +// just to avoid copy-and-paste of similar code. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + BiggestInt val1, BiggestInt val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +} + +// Implements the helper function for {ASSERT|EXPECT}_NE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(NE, !=) +// Implements the helper function for {ASSERT|EXPECT}_LE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LE, <=) +// Implements the helper function for {ASSERT|EXPECT}_LT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LT, < ) +// Implements the helper function for {ASSERT|EXPECT}_GE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GE, >=) +// Implements the helper function for {ASSERT|EXPECT}_GT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GT, > ) + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CaseInsensitiveCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + true); +} + +// The helper function for {ASSERT|EXPECT}_STRNE. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CaseInsensitiveCStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() + << "Expected: (" << s1_expression << ") != (" + << s2_expression << ") (ignoring case), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +} // namespace internal + +namespace { + +// Helper functions for implementing IsSubString() and IsNotSubstring(). + +// This group of overloaded functions return true iff needle is a +// substring of haystack. NULL is considered a substring of itself +// only. + +bool IsSubstringPred(const char* needle, const char* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return strstr(haystack, needle) != NULL; +} + +bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return wcsstr(haystack, needle) != NULL; +} + +// StringType here can be either ::std::string or ::std::wstring. +template +bool IsSubstringPred(const StringType& needle, + const StringType& haystack) { + return haystack.find(needle) != StringType::npos; +} + +// This function implements either IsSubstring() or IsNotSubstring(), +// depending on the value of the expected_to_be_substring parameter. +// StringType here can be const char*, const wchar_t*, ::std::string, +// or ::std::wstring. +template +AssertionResult IsSubstringImpl( + bool expected_to_be_substring, + const char* needle_expr, const char* haystack_expr, + const StringType& needle, const StringType& haystack) { + if (IsSubstringPred(needle, haystack) == expected_to_be_substring) + return AssertionSuccess(); + + const bool is_wide_string = sizeof(needle[0]) > 1; + const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; + return AssertionFailure() + << "Value of: " << needle_expr << "\n" + << " Actual: " << begin_string_quote << needle << "\"\n" + << "Expected: " << (expected_to_be_substring ? "" : "not ") + << "a substring of " << haystack_expr << "\n" + << "Which is: " << begin_string_quote << haystack << "\""; +} + +} // namespace + +// IsSubstring() and IsNotSubstring() check whether needle is a +// substring of haystack (NULL is considered a substring of itself +// only), and return an appropriate error message when they fail. + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +#if GTEST_HAS_STD_WSTRING +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +#if GTEST_OS_WINDOWS + +namespace { + +// Helper function for IsHRESULT{SuccessFailure} predicates +AssertionResult HRESULTFailureHelper(const char* expr, + const char* expected, + long hr) { // NOLINT +# if GTEST_OS_WINDOWS_MOBILE + + // Windows CE doesn't support FormatMessage. + const char error_text[] = ""; + +# else + + // Looks up the human-readable system message for the HRESULT code + // and since we're not passing any params to FormatMessage, we don't + // want inserts expanded. + const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + const DWORD kBufSize = 4096; + // Gets the system's human readable message string for this HRESULT. + char error_text[kBufSize] = { '\0' }; + DWORD message_length = ::FormatMessageA(kFlags, + 0, // no source, we're asking system + hr, // the error + 0, // no line width restrictions + error_text, // output buffer + kBufSize, // buf size + NULL); // no arguments for inserts + // Trims tailing white space (FormatMessage leaves a trailing CR-LF) + for (; message_length && IsSpace(error_text[message_length - 1]); + --message_length) { + error_text[message_length - 1] = '\0'; + } + +# endif // GTEST_OS_WINDOWS_MOBILE + + const std::string error_hex("0x" + String::FormatHexInt(hr)); + return ::testing::AssertionFailure() + << "Expected: " << expr << " " << expected << ".\n" + << " Actual: " << error_hex << " " << error_text << "\n"; +} + +} // namespace + +AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT + if (SUCCEEDED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "succeeds", hr); +} + +AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT + if (FAILED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "fails", hr); +} + +#endif // GTEST_OS_WINDOWS + +// Utility functions for encoding Unicode text (wide strings) in +// UTF-8. + +// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// like this: +// +// Code-point length Encoding +// 0 - 7 bits 0xxxxxxx +// 8 - 11 bits 110xxxxx 10xxxxxx +// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx +// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +// The maximum code-point a one-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; + +// The maximum code-point a two-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; + +// The maximum code-point a three-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; + +// The maximum code-point a four-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; + +// Chops off the n lowest bits from a bit pattern. Returns the n +// lowest bits. As a side effect, the original bit pattern will be +// shifted to the right by n bits. +inline UInt32 ChopLowBits(UInt32* bits, int n) { + const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); + *bits >>= n; + return low_bits; +} + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +std::string CodePointToUtf8(UInt32 code_point) { + if (code_point > kMaxCodePoint4) { + return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; + } + + char str[5]; // Big enough for the largest valid code point. + if (code_point <= kMaxCodePoint1) { + str[1] = '\0'; + str[0] = static_cast(code_point); // 0xxxxxxx + } else if (code_point <= kMaxCodePoint2) { + str[2] = '\0'; + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xC0 | code_point); // 110xxxxx + } else if (code_point <= kMaxCodePoint3) { + str[3] = '\0'; + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xE0 | code_point); // 1110xxxx + } else { // code_point <= kMaxCodePoint4 + str[4] = '\0'; + str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xF0 | code_point); // 11110xxx + } + return str; +} + +// The following two functions only make sense if the the system +// uses UTF-16 for wide string encoding. All supported systems +// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. + +// Determines if the arguments constitute UTF-16 surrogate pair +// and thus should be combined into a single Unicode code point +// using CreateCodePointFromUtf16SurrogatePair. +inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; +} + +// Creates a Unicode code point from UTF16 surrogate pair. +inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, + wchar_t second) { + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast(first); +} + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +std::string WideStringToUtf8(const wchar_t* str, int num_chars) { + if (num_chars == -1) + num_chars = static_cast(wcslen(str)); + + ::std::stringstream stream; + for (int i = 0; i < num_chars; ++i) { + UInt32 unicode_code_point; + + if (str[i] == L'\0') { + break; + } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { + unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], + str[i + 1]); + i++; + } else { + unicode_code_point = static_cast(str[i]); + } + + stream << CodePointToUtf8(unicode_code_point); + } + return StringStreamToString(&stream); +} + +// Converts a wide C string to an std::string using the UTF-8 encoding. +// NULL will be converted to "(null)". +std::string String::ShowWideCString(const wchar_t * wide_c_str) { + if (wide_c_str == NULL) return "(null)"; + + return internal::WideStringToUtf8(wide_c_str, -1); +} + +// Compares two wide C strings. Returns true iff they have the same +// content. +// +// Unlike wcscmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + + return wcscmp(lhs, rhs) == 0; +} + +// Helper function for *_STREQ on wide strings. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual) { + if (String::WideCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// Helper function for *_STRNE on wide strings. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2) { + if (!String::WideCStringEquals(s1, s2)) { + return AssertionSuccess(); + } + + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: " + << PrintToString(s1) + << " vs " << PrintToString(s2); +} + +// Compares two C strings, ignoring case. Returns true iff they have +// the same content. +// +// Unlike strcasecmp(), this function can handle NULL argument(s). A +// NULL C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; +} + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. +bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + +#if GTEST_OS_WINDOWS + return _wcsicmp(lhs, rhs) == 0; +#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID + return wcscasecmp(lhs, rhs) == 0; +#else + // Android, Mac OS X and Cygwin don't define wcscasecmp. + // Other unknown OSes may not define it either. + wint_t left, right; + do { + left = towlower(*lhs++); + right = towlower(*rhs++); + } while (left && left == right); + return left == right; +#endif // OS selector +} + +// Returns true iff str ends with the given suffix, ignoring case. +// Any string is considered to end with an empty suffix. +bool String::EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix) { + const size_t str_len = str.length(); + const size_t suffix_len = suffix.length(); + return (str_len >= suffix_len) && + CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len, + suffix.c_str()); +} + +// Formats an int value as "%02d". +std::string String::FormatIntWidth2(int value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << value; + return ss.str(); +} + +// Formats an int value as "%X". +std::string String::FormatHexInt(int value) { + std::stringstream ss; + ss << std::hex << std::uppercase << value; + return ss.str(); +} + +// Formats a byte as "%02X". +std::string String::FormatByte(unsigned char value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase + << static_cast(value); + return ss.str(); +} + +// Converts the buffer in a stringstream to an std::string, converting NUL +// bytes to "\\0" along the way. +std::string StringStreamToString(::std::stringstream* ss) { + const ::std::string& str = ss->str(); + const char* const start = str.c_str(); + const char* const end = start + str.length(); + + std::string result; + result.reserve(2 * (end - start)); + for (const char* ch = start; ch != end; ++ch) { + if (*ch == '\0') { + result += "\\0"; // Replaces NUL with "\\0"; + } else { + result += *ch; + } + } + + return result; +} + +// Appends the user-supplied message to the Google-Test-generated message. +std::string AppendUserMessage(const std::string& gtest_msg, + const Message& user_msg) { + // Appends the user message if it's non-empty. + const std::string user_msg_string = user_msg.GetString(); + if (user_msg_string.empty()) { + return gtest_msg; + } + + return gtest_msg + "\n" + user_msg_string; +} + +} // namespace internal + +// class TestResult + +// Creates an empty TestResult. +TestResult::TestResult() + : death_test_count_(0), + elapsed_time_(0) { +} + +// D'tor. +TestResult::~TestResult() { +} + +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + +// Adds a test part result to the list. +void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { + test_part_results_.push_back(test_part_result); +} + +// Adds a test property to the list. If a property with the same key as the +// supplied property is already represented, the value of this test_property +// replaces the old value for that key. +void TestResult::RecordProperty(const std::string& xml_element, + const TestProperty& test_property) { + if (!ValidateTestProperty(xml_element, test_property)) { + return; + } + internal::MutexLock lock(&test_properites_mutex_); + const std::vector::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); + return; + } + property_with_matching_key->SetValue(test_property.value()); +} + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuitesAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "random_seed", + "tests", + "time", + "timestamp" +}; + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuiteAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "tests", + "time" +}; + +// The list of reserved attributes used in the element of XML output. +static const char* const kReservedTestCaseAttributes[] = { + "classname", + "name", + "status", + "time", + "type_param", + "value_param" +}; + +template +std::vector ArrayAsVector(const char* const (&array)[kSize]) { + return std::vector(array, array + kSize); +} + +static std::vector GetReservedAttributesForElement( + const std::string& xml_element) { + if (xml_element == "testsuites") { + return ArrayAsVector(kReservedTestSuitesAttributes); + } else if (xml_element == "testsuite") { + return ArrayAsVector(kReservedTestSuiteAttributes); + } else if (xml_element == "testcase") { + return ArrayAsVector(kReservedTestCaseAttributes); + } else { + GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; + } + // This code is unreachable but some compilers may not realizes that. + return std::vector(); +} + +static std::string FormatWordList(const std::vector& words) { + Message word_list; + for (size_t i = 0; i < words.size(); ++i) { + if (i > 0 && words.size() > 2) { + word_list << ", "; + } + if (i == words.size() - 1) { + word_list << "and "; + } + word_list << "'" << words[i] << "'"; + } + return word_list.GetString(); +} + +bool ValidateTestPropertyName(const std::string& property_name, + const std::vector& reserved_names) { + if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != + reserved_names.end()) { + ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name + << " (" << FormatWordList(reserved_names) + << " are reserved by " << GTEST_NAME_ << ")"; + return false; + } + return true; +} + +// Adds a failure if the key is a reserved attribute of the element named +// xml_element. Returns true if the property is valid. +bool TestResult::ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property) { + return ValidateTestPropertyName(test_property.key(), + GetReservedAttributesForElement(xml_element)); +} + +// Clears the object. +void TestResult::Clear() { + test_part_results_.clear(); + test_properties_.clear(); + death_test_count_ = 0; + elapsed_time_ = 0; +} + +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; +} + +// Returns true iff the test part fatally failed. +static bool TestPartFatallyFailed(const TestPartResult& result) { + return result.fatally_failed(); +} + +// Returns true iff the test fatally failed. +bool TestResult::HasFatalFailure() const { + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; +} + +// Gets the number of all test parts. This is the sum of the number +// of successful test parts and the number of failed test parts. +int TestResult::total_part_count() const { + return static_cast(test_part_results_.size()); +} + +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast(test_properties_.size()); +} + +// class Test + +// Creates a Test object. + +// The c'tor saves the values of all Google Test flags. +Test::Test() + : gtest_flag_saver_(new internal::GTestFlagSaver) { +} + +// The d'tor restores the values of all Google Test flags. +Test::~Test() { + delete gtest_flag_saver_; +} + +// Sets up the test fixture. +// +// A sub-class may override this. +void Test::SetUp() { +} + +// Tears down the test fixture. +// +// A sub-class may override this. +void Test::TearDown() { +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, const std::string& value) { + UnitTest::GetInstance()->RecordProperty(key, value); +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, int value) { + Message value_message; + value_message << value; + RecordProperty(key, value_message.GetString().c_str()); +} + +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + ""); // No stack trace, either. +} + +} // namespace internal + +// Google Test requires all tests in the same test case to use the same test +// fixture class. This function checks if the current test has the +// same fixture class as the first test in the current test case. If +// yes, it returns true; otherwise it generates a Google Test failure and +// returns false. +bool Test::HasSameFixtureClass() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + const TestCase* const test_case = impl->current_test_case(); + + // Info about the first test in the current test case. + const TestInfo* const first_test_info = test_case->test_info_list()[0]; + const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; + const char* const first_test_name = first_test_info->name(); + + // Info about the current test. + const TestInfo* const this_test_info = impl->current_test_info(); + const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; + const char* const this_test_name = this_test_info->name(); + + if (this_fixture_id != first_fixture_id) { + // Is the first test defined using TEST? + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); + // Is this test defined using TEST? + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); + + if (first_is_TEST || this_is_TEST) { + // The user mixed TEST and TEST_F in this test case - we'll tell + // him/her how to fix it. + + // Gets the name of the TEST and the name of the TEST_F. Note + // that first_is_TEST and this_is_TEST cannot both be true, as + // the fixture IDs are different for the two tests. + const char* const TEST_name = + first_is_TEST ? first_test_name : this_test_name; + const char* const TEST_F_name = + first_is_TEST ? this_test_name : first_test_name; + + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test case is\n" + << "illegal. In test case " << this_test_info->test_case_name() + << ",\n" + << "test " << TEST_F_name << " is defined using TEST_F but\n" + << "test " << TEST_name << " is defined using TEST. You probably\n" + << "want to change the TEST to TEST_F or move it to another test\n" + << "case."; + } else { + // The user defined two fixture classes with the same name in + // two namespaces - we'll tell him/her how to fix it. + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " + << this_test_info->test_case_name() << ",\n" + << "you defined test " << first_test_name + << " and test " << this_test_name << "\n" + << "using two different test fixture classes. This can happen if\n" + << "the two classes are from different namespaces or translation\n" + << "units and have the same name. You should probably rename one\n" + << "of the classes to put the tests into different test cases."; + } + return false; + } + + return true; +} + +#if GTEST_HAS_SEH + +// Adds an "exception thrown" fatal failure to the current test. This +// function returns its result via an output parameter pointer because VC++ +// prohibits creation of objects with destructors on stack in functions +// using __try (see error C2712). +static std::string* FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << + exception_code << std::setbase(10) << " thrown in " << location << "."; + + return new std::string(message.GetString()); +} + +#endif // GTEST_HAS_SEH + +namespace internal { + +#if GTEST_HAS_EXCEPTIONS + +// Adds an "exception thrown" fatal failure to the current test. +static std::string FormatCxxExceptionMessage(const char* description, + const char* location) { + Message message; + if (description != NULL) { + message << "C++ exception with description \"" << description << "\""; + } else { + message << "Unknown C++ exception"; + } + message << " thrown in " << location << "."; + + return message.GetString(); +} + +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result); + +GoogleTestFailureException::GoogleTestFailureException( + const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} + +#endif // GTEST_HAS_EXCEPTIONS + +// We put these helper functions in the internal namespace as IBM's xlC +// compiler rejects the code if they were declared static. + +// Runs the given method and handles SEH exceptions it throws, when +// SEH is supported; returns the 0-value for type Result in case of an +// SEH exception. (Microsoft compilers cannot handle SEH and C++ +// exceptions in the same function. Therefore, we provide a separate +// wrapper function for handling SEH exceptions.) +template +Result HandleSehExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { +#if GTEST_HAS_SEH + __try { + return (object->*method)(); + } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT + GetExceptionCode())) { + // We create the exception message on the heap because VC++ prohibits + // creation of objects with destructors on stack in functions using __try + // (see error C2712). + std::string* exception_message = FormatSehExceptionMessage( + GetExceptionCode(), location); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + *exception_message); + delete exception_message; + return static_cast(0); + } +#else + (void)location; + return (object->*method)(); +#endif // GTEST_HAS_SEH +} + +// Runs the given method and catches and reports C++ and/or SEH-style +// exceptions, if they are supported; returns the 0-value for type +// Result in case of an SEH exception. +template +Result HandleExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { + // NOTE: The user code can affect the way in which Google Test handles + // exceptions by setting GTEST_FLAG(catch_exceptions), but only before + // RUN_ALL_TESTS() starts. It is technically possible to check the flag + // after the exception is caught and either report or re-throw the + // exception based on the flag's value: + // + // try { + // // Perform the test method. + // } catch (...) { + // if (GTEST_FLAG(catch_exceptions)) + // // Report the exception as failure. + // else + // throw; // Re-throws the original exception. + // } + // + // However, the purpose of this flag is to allow the program to drop into + // the debugger when the exception is thrown. On most platforms, once the + // control enters the catch block, the exception origin information is + // lost and the debugger will stop the program at the point of the + // re-throw in this function -- instead of at the point of the original + // throw statement in the code under test. For this reason, we perform + // the check early, sacrificing the ability to affect Google Test's + // exception handling in the method where the exception is thrown. + if (internal::GetUnitTestImpl()->catch_exceptions()) { +#if GTEST_HAS_EXCEPTIONS + try { + return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const internal::GoogleTestFailureException&) { // NOLINT + // This exception type can only be thrown by a failed Google + // Test assertion with the intention of letting another testing + // framework catch it. Therefore we just re-throw it. + throw; + } catch (const std::exception& e) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(e.what(), location)); + } catch (...) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(NULL, location)); + } + return static_cast(0); +#else + return HandleSehExceptionsInMethodIfSupported(object, method, location); +#endif // GTEST_HAS_EXCEPTIONS + } else { + return (object->*method)(); + } +} + +} // namespace internal + +// Runs the test and updates the test result. +void Test::Run() { + if (!HasSameFixtureClass()) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); + // We will run the test only if SetUp() was successful. + if (!HasFatalFailure()) { + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TestBody, "the test body"); + } + + // However, we want to clean up as much as possible. Hence we will + // always call TearDown(), even if SetUp() or the test body has + // failed. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TearDown, "TearDown()"); +} + +// Returns true iff the current test has a fatal failure. +bool Test::HasFatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); +} + +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + +// class TestInfo + +// Constructs a TestInfo object. It assumes ownership of the test factory +// object. +TestInfo::TestInfo(const std::string& a_test_case_name, + const std::string& a_name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory) + : test_case_name_(a_test_case_name), + name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + value_param_(a_value_param ? new std::string(a_value_param) : NULL), + fixture_class_id_(fixture_class_id), + should_run_(false), + is_disabled_(false), + matches_filter_(false), + factory_(factory), + result_() {} + +// Destructs a TestInfo object. +TestInfo::~TestInfo() { delete factory_; } + +namespace internal { + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param: the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param: text representation of the test's value parameter, +// or NULL if this is not a value-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory) { + TestInfo* const test_info = + new TestInfo(test_case_name, name, type_param, value_param, + fixture_class_id, factory); + GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); + return test_info; +} + +#if GTEST_HAS_PARAM_TEST +void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line) { + Message errors; + errors + << "Attempted redefinition of test case " << test_case_name << ".\n" + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " << test_case_name << ", you tried\n" + << "to define a test using a fixture class different from the one\n" + << "used earlier. This can happen if the two fixture classes are\n" + << "from different namespaces and have the same name. You should\n" + << "probably rename one of the classes to put the tests into different\n" + << "test cases."; + + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors.GetString().c_str()); +} +#endif // GTEST_HAS_PARAM_TEST + +} // namespace internal + +namespace { + +// A predicate that checks the test name of a TestInfo against a known +// value. +// +// This is used for implementation of the TestCase class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestNameIs is copyable. +class TestNameIs { + public: + // Constructor. + // + // TestNameIs has NO default constructor. + explicit TestNameIs(const char* name) + : name_(name) {} + + // Returns true iff the test name of test_info matches name_. + bool operator()(const TestInfo * test_info) const { + return test_info && test_info->name() == name_; + } + + private: + std::string name_; +}; + +} // namespace + +namespace internal { + +// This method expands all parameterized tests registered with macros TEST_P +// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// This will be done just once during the program runtime. +void UnitTestImpl::RegisterParameterizedTests() { +#if GTEST_HAS_PARAM_TEST + if (!parameterized_tests_registered_) { + parameterized_test_registry_.RegisterTests(); + parameterized_tests_registered_ = true; + } +#endif +} + +} // namespace internal + +// Creates the test object, runs it, records its result, and then +// deletes it. +void TestInfo::Run() { + if (!should_run_) return; + + // Tells UnitTest where to store test result. + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_info(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*this); + + const TimeInMillis start = internal::GetTimeInMillis(); + + impl->os_stack_trace_getter()->UponLeavingGTest(); + + // Creates the test object. + Test* const test = internal::HandleExceptionsInMethodIfSupported( + factory_, &internal::TestFactoryBase::CreateTest, + "the test fixture's constructor"); + + // Runs the test only if the test object was created and its + // constructor didn't generate a fatal failure. + if ((test != NULL) && !Test::HasFatalFailure()) { + // This doesn't throw as all user code that can throw are wrapped into + // exception handling code. + test->Run(); + } + + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + + result_.set_elapsed_time(internal::GetTimeInMillis() - start); + + // Notifies the unit test event listener that a test has just finished. + repeater->OnTestEnd(*this); + + // Tells UnitTest to stop associating assertion results to this + // test. + impl->set_current_test_info(NULL); +} + +// class TestCase + +// Gets the number of successful tests in this test case. +int TestCase::successful_test_count() const { + return CountIf(test_info_list_, TestPassed); +} + +// Gets the number of failed tests in this test case. +int TestCase::failed_test_count() const { + return CountIf(test_info_list_, TestFailed); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int TestCase::reportable_disabled_test_count() const { + return CountIf(test_info_list_, TestReportableDisabled); +} + +// Gets the number of disabled tests in this test case. +int TestCase::disabled_test_count() const { + return CountIf(test_info_list_, TestDisabled); +} + +// Gets the number of tests to be printed in the XML report. +int TestCase::reportable_test_count() const { + return CountIf(test_info_list_, TestReportable); +} + +// Get the number of tests in this test case that should run. +int TestCase::test_to_run_count() const { + return CountIf(test_info_list_, ShouldRunTest); +} + +// Gets the number of all tests. +int TestCase::total_test_count() const { + return static_cast(test_info_list_.size()); +} + +// Creates a TestCase with the given name. +// +// Arguments: +// +// name: name of the test case +// a_type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase::TestCase(const char* a_name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) + : name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + set_up_tc_(set_up_tc), + tear_down_tc_(tear_down_tc), + should_run_(false), + elapsed_time_(0) { +} + +// Destructor of TestCase. +TestCase::~TestCase() { + // Deletes every Test in the collection. + ForEach(test_info_list_, internal::Delete); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Adds a test to this test case. Will delete the test upon +// destruction of the TestCase object. +void TestCase::AddTestInfo(TestInfo * test_info) { + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast(test_indices_.size())); +} + +// Runs every test in this TestCase. +void TestCase::Run() { + if (!should_run_) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_case(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + repeater->OnTestCaseStart(*this); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + + const internal::TimeInMillis start = internal::GetTimeInMillis(); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->Run(); + } + elapsed_time_ = internal::GetTimeInMillis() - start; + + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + + repeater->OnTestCaseEnd(*this); + impl->set_current_test_case(NULL); +} + +// Clears the results of all tests in this test case. +void TestCase::ClearResult() { + ad_hoc_test_result_.Clear(); + ForEach(test_info_list_, TestInfo::ClearTestResult); +} + +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast(i); + } +} + +// Formats a countable noun. Depending on its quantity, either the +// singular form or the plural form is used. e.g. +// +// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". +// FormatCountableNoun(5, "book", "books") returns "5 books". +static std::string FormatCountableNoun(int count, + const char * singular_form, + const char * plural_form) { + return internal::StreamableToString(count) + " " + + (count == 1 ? singular_form : plural_form); +} + +// Formats the count of tests. +static std::string FormatTestCount(int test_count) { + return FormatCountableNoun(test_count, "test", "tests"); +} + +// Formats the count of test cases. +static std::string FormatTestCaseCount(int test_case_count) { + return FormatCountableNoun(test_case_count, "test case", "test cases"); +} + +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { + switch (type) { + case TestPartResult::kSuccess: + return "Success"; + + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: +#ifdef _MSC_VER + return "error: "; +#else + return "Failure\n"; +#endif + default: + return "Unknown result type"; + } +} + +namespace internal { + +// Prints a TestPartResult to an std::string. +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + +// Prints a TestPartResult. +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const std::string& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); + fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif +} + +// class PrettyUnitTestResultPrinter + +enum GTestColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW +}; + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns the character attribute for the given color. +WORD GetColorAttribute(GTestColor color) { + switch (color) { + case COLOR_RED: return FOREGROUND_RED; + case COLOR_GREEN: return FOREGROUND_GREEN; + case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; + } +} + +#else + +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. +const char* GetAnsiColorCode(GTestColor color) { + switch (color) { + case COLOR_RED: return "1"; + case COLOR_GREEN: return "2"; + case COLOR_YELLOW: return "3"; + default: return NULL; + }; +} + +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns true iff Google Test should use colors in the output. +bool ShouldUseColor(bool stdout_is_tty) { + const char* const gtest_color = GTEST_FLAG(color).c_str(); + + if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { +#if GTEST_OS_WINDOWS + // On Windows the TERM variable is usually not set, but the + // console there does support colors. + return stdout_is_tty; +#else + // On non-Windows platforms, we rely on the TERM variable. + const char* const term = posix::GetEnv("TERM"); + const bool term_supports_color = + String::CStringEquals(term, "xterm") || + String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "screen") || + String::CStringEquals(term, "screen-256color") || + String::CStringEquals(term, "linux") || + String::CStringEquals(term, "cygwin"); + return stdout_is_tty && term_supports_color; +#endif // GTEST_OS_WINDOWS + } + + return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || + String::CaseInsensitiveCStringEquals(gtest_color, "true") || + String::CaseInsensitiveCStringEquals(gtest_color, "t") || + String::CStringEquals(gtest_color, "1"); + // We take "yes", "true", "t", and "1" as meaning "yes". If the + // value is neither one of these nor "auto", we treat it as "no" to + // be conservative. +} + +// Helpers for printing colored strings to stdout. Note that on Windows, we +// cannot simply emit special characters and have the terminal change colors. +// This routine must actually emit the characters rather than return a string +// that would be colored when printed, as can be done on Linux. +void ColoredPrintf(GTestColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS + const bool use_color = false; +#else + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + // The '!= 0' comparison is necessary to satisfy MSVC 7.1. + + if (!use_color) { + vprintf(fmt, args); + va_end(args); + return; + } + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetColorAttribute(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + printf("\033[0;3%sm", GetAnsiColorCode(color)); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + va_end(args); +} + +// Text printed in Google Test's text output and --gunit_list_tests +// output to label the type parameter and value parameter for a test. +static const char kTypeParamLabel[] = "TypeParam"; +static const char kValueParamLabel[] = "GetParam()"; + +void PrintFullTestCommentIfPresent(const TestInfo& test_info) { + const char* const type_param = test_info.type_param(); + const char* const value_param = test_info.value_param(); + + if (type_param != NULL || value_param != NULL) { + printf(", where "); + if (type_param != NULL) { + printf("%s = %s", kTypeParamLabel, type_param); + if (value_param != NULL) + printf(" and "); + } + if (value_param != NULL) { + printf("%s = %s", kValueParamLabel, value_param); + } + } +} + +// This class implements the TestEventListener interface. +// +// Class PrettyUnitTestResultPrinter is copyable. +class PrettyUnitTestResultPrinter : public TestEventListener { + public: + PrettyUnitTestResultPrinter() {} + static void PrintTestName(const char * test_case, const char * test) { + printf("%s.%s", test_case, test); + } + + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + + private: + static void PrintFailedTests(const UnitTest& unit_test); +}; + + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); + + // Prints the filter if it's not *. This reminds the user that some + // tests may be skipped. + if (!String::CStringEquals(filter, kUniversalFilter)) { + ColoredPrintf(COLOR_YELLOW, + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %d of %s.\n", + static_cast(shard_index) + 1, + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); + } + + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("Running %s from %s.\n", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment set-up.\n"); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_case.name()); + if (test_case.type_param() == NULL) { + printf("\n"); + } else { + printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { + ColoredPrintf(COLOR_GREEN, "[ RUN ] "); + PrintTestName(test_info.test_case_name(), test_info.name()); + printf("\n"); + fflush(stdout); +} + +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { + ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else { + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + } + PrintTestName(test_info.test_case_name(), test_info.name()); + if (test_info.result()->Failed()) + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", internal::StreamableToString( + test_info.result()->elapsed_time()).c_str()); + } else { + printf("\n"); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; + + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case.name(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment tear-down\n"); + fflush(stdout); +} + +// Internal helper for printing the list of failed tests. +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); + if (failed_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { + continue; + } + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s.%s", test_case.name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + printf("\n"); + } + } +} + +void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); + PrintFailedTests(unit_test); + printf("\n%2d FAILED %s\n", num_failures, + num_failures == 1 ? "TEST" : "TESTS"); + } + + int num_disabled = unit_test.reportable_disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (!num_failures) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(COLOR_YELLOW, + " YOU HAVE %d DISABLED %s\n\n", + num_disabled, + num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End PrettyUnitTestResultPrinter + +// class TestEventRepeater +// +// This class forwards events to other event listeners. +class TestEventRepeater : public TestEventListener { + public: + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); + + private: + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector listeners_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); +}; + +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete); +} + +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); +} + +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. +#define GTEST_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} + +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) + +#undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ + +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater + +// This class generates an XML output file. +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit XmlUnitTestResultPrinter(const char* output_file); + + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + + private: + // Is c a whitespace character that is normalized to a space character + // when it appears in an XML attribute value? + static bool IsNormalizableWhitespace(char c) { + return c == 0x9 || c == 0xA || c == 0xD; + } + + // May c appear in a well-formed XML document? + static bool IsValidXmlCharacter(char c) { + return IsNormalizableWhitespace(c) || c >= 0x20; + } + + // Returns an XML-escaped copy of the input string str. If + // is_attribute is true, the text is meant to appear as an attribute + // value, and normalizable whitespace is preserved by replacing it + // with character references. + static std::string EscapeXml(const std::string& str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static std::string RemoveInvalidXmlCharacters(const std::string& str); + + // Convenience wrapper around EscapeXml when str is an attribute value. + static std::string EscapeXmlAttribute(const std::string& str) { + return EscapeXml(str, true); + } + + // Convenience wrapper around EscapeXml when str is not an attribute value. + static std::string EscapeXmlText(const char* str) { + return EscapeXml(str, false); + } + + // Verifies that the given attribute belongs to the given element and + // streams the attribute as XML. + static void OutputXmlAttribute(std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value); + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); + + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); + + // Prints an XML representation of a TestCase object + static void PrintXmlTestCase(::std::ostream* stream, + const TestCase& test_case); + + // Prints an XML summary of unit_test to output stream out. + static void PrintXmlUnitTest(::std::ostream* stream, + const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as space + // delimited XML attributes based on the property key="value" pairs. + // When the std::string is not empty, it includes a space at the beginning, + // to delimit this attribute from prior attributes. + static std::string TestPropertiesAsXmlAttributes(const TestResult& result); + + // The output file. + const std::string output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); +}; + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.c_str() == NULL || output_file_.empty()) { + fprintf(stderr, "XML output file may not be null\n"); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = NULL; + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + xmlout = posix::FOpen(output_file_.c_str(), "w"); + } + if (xmlout == NULL) { + // TODO(wan): report the reason of the failure. + // + // We don't do it for now as: + // + // 1. There is no urgent need for it. + // 2. It's a bit involved to make the errno variable thread-safe on + // all three operating systems (Linux, Windows, and Mac OS). + // 3. To interpret the meaning of errno in a thread-safe way, + // we need the strerror_r() function, which is not available on + // Windows. + fprintf(stderr, + "Unable to open file \"%s\"\n", + output_file_.c_str()); + fflush(stderr); + exit(EXIT_FAILURE); + } + std::stringstream stream; + PrintXmlUnitTest(&stream, unit_test); + fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); + fclose(xmlout); +} + +// Returns an XML-escaped copy of the input string str. If is_attribute +// is true, the text is meant to appear as an attribute value, and +// normalizable whitespace is preserved by replacing it with character +// references. +// +// Invalid XML characters in str, if any, are stripped from the output. +// It is expected that most, if not all, of the text processed by this +// module will consist of ordinary English text. +// If this module is ever modified to produce version 1.1 XML output, +// most invalid characters can be retained using character references. +// TODO(wan): It might be nice to have a minimally invasive, human-readable +// escaping scheme for invalid characters, rather than dropping them. +std::string XmlUnitTestResultPrinter::EscapeXml( + const std::string& str, bool is_attribute) { + Message m; + + for (size_t i = 0; i < str.size(); ++i) { + const char ch = str[i]; + switch (ch) { + case '<': + m << "<"; + break; + case '>': + m << ">"; + break; + case '&': + m << "&"; + break; + case '\'': + if (is_attribute) + m << "'"; + else + m << '\''; + break; + case '"': + if (is_attribute) + m << """; + else + m << '"'; + break; + default: + if (IsValidXmlCharacter(ch)) { + if (is_attribute && IsNormalizableWhitespace(ch)) + m << "&#x" << String::FormatByte(static_cast(ch)) + << ";"; + else + m << ch; + } + break; + } + } + + return m.GetString(); +} + +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( + const std::string& str) { + std::string output; + output.reserve(str.size()); + for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) + if (IsValidXmlCharacter(*it)) + output.push_back(*it); + + return output; +} + +// The following routines generate an XML representation of a UnitTest +// object. +// +// This is how Google Test concepts map to the DTD: +// +// <-- corresponds to a UnitTest object +// <-- corresponds to a TestCase object +// <-- corresponds to a TestInfo object +// ... +// ... +// ... +// <-- individual assertion failures +// +// +// + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Converts the given epoch time in milliseconds to a date string in the ISO +// 8601 format, without the timezone information. +std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { + // Using non-reentrant version as localtime_r is not portable. + time_t seconds = static_cast(ms / 1000); +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# 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 + const struct tm* const time_struct = localtime(&seconds); // NOLINT +#endif + if (time_struct == NULL) + return ""; // Invalid ms value + + // YYYY-MM-DDThh:mm:ss + return StreamableToString(time_struct->tm_year + 1900) + "-" + + String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + + String::FormatIntWidth2(time_struct->tm_mday) + "T" + + String::FormatIntWidth2(time_struct->tm_hour) + ":" + + String::FormatIntWidth2(time_struct->tm_min) + ":" + + String::FormatIntWidth2(time_struct->tm_sec); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << ""); + if (next_segment != NULL) { + stream->write( + segment, static_cast(next_segment - segment)); + *stream << "]]>]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; +} + +void XmlUnitTestResultPrinter::OutputXmlAttribute( + std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value) { + const std::vector& allowed_names = + GetReservedAttributesForElement(element_name); + + GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != + allowed_names.end()) + << "Attribute " << name << " is not allowed for element <" << element_name + << ">."; + + *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\""; +} + +// Prints an XML representation of a TestInfo object. +// TODO(wan): There is also value in printing properties with the plain printer. +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + const std::string kTestcase = "testcase"; + + *stream << " \n"; + } + const string location = internal::FormatCompilerIndependentFileLocation( + part.file_name(), part.line_number()); + const string summary = location + "\n" + part.summary(); + *stream << " "; + const string detail = location + "\n" + part.message(); + OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str()); + *stream << "\n"; + } + } + + if (failures == 0) + *stream << " />\n"; + else + *stream << " \n"; +} + +// Prints an XML representation of a TestCase object +void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, + const TestCase& test_case) { + const std::string kTestsuite = "testsuite"; + *stream << " <" << kTestsuite; + OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); + OutputXmlAttribute(stream, kTestsuite, "tests", + StreamableToString(test_case.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuite, "failures", + StreamableToString(test_case.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuite, "disabled", + StreamableToString(test_case.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuite, "errors", "0"); + OutputXmlAttribute(stream, kTestsuite, "time", + FormatTimeInMillisAsSeconds(test_case.elapsed_time())); + *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) + << ">\n"; + + for (int i = 0; i < test_case.total_test_count(); ++i) { + if (test_case.GetTestInfo(i)->is_reportable()) + OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); + } + *stream << " \n"; +} + +// Prints an XML summary of unit_test to output stream out. +void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, + const UnitTest& unit_test) { + const std::string kTestsuites = "testsuites"; + + *stream << "\n"; + *stream << "<" << kTestsuites; + + OutputXmlAttribute(stream, kTestsuites, "tests", + StreamableToString(unit_test.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuites, "failures", + StreamableToString(unit_test.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuites, "disabled", + StreamableToString(unit_test.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuites, "errors", "0"); + OutputXmlAttribute( + stream, kTestsuites, "timestamp", + FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); + OutputXmlAttribute(stream, kTestsuites, "time", + FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); + + if (GTEST_FLAG(shuffle)) { + OutputXmlAttribute(stream, kTestsuites, "random_seed", + StreamableToString(unit_test.random_seed())); + } + + *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); + + OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); + *stream << ">\n"; + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + if (unit_test.GetTestCase(i)->reportable_test_count() > 0) + PrintXmlTestCase(stream, *unit_test.GetTestCase(i)); + } + *stream << "\n"; +} + +// Produces a string representing the test properties in a result as space +// delimited XML attributes based on the property key="value" pairs. +std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << " " << property.key() << "=" + << "\"" << EscapeXmlAttribute(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End XmlUnitTestResultPrinter + +#if GTEST_CAN_STREAM_RESULTS_ + +// Checks if str contains '=', '&', '%' or '\n' characters. If yes, +// replaces them by "%xx" where xx is their hexadecimal value. For +// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) +// in both time and space -- important as the input str may contain an +// arbitrarily long test failure message and stack trace. +string StreamingListener::UrlEncode(const char* str) { + string result; + result.reserve(strlen(str) + 1); + for (char ch = *str; ch != '\0'; ch = *++str) { + switch (ch) { + case '%': + case '=': + case '&': + case '\n': + result.append("%" + String::FormatByte(static_cast(ch))); + break; + default: + result.push_back(ch); + break; + } + } + return result; +} + +void StreamingListener::SocketWriter::MakeConnection() { + GTEST_CHECK_(sockfd_ == -1) + << "MakeConnection() can't be called when there is already a connection."; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. + hints.ai_socktype = SOCK_STREAM; + addrinfo* servinfo = NULL; + + // Use the getaddrinfo() to get a linked list of IP addresses for + // the given host name. + const int error_num = getaddrinfo( + host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); + if (error_num != 0) { + GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " + << gai_strerror(error_num); + } + + // Loop through all the results and connect to the first we can. + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + cur_addr = cur_addr->ai_next) { + sockfd_ = socket( + cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); + if (sockfd_ != -1) { + // Connect the client socket to the server socket. + if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { + close(sockfd_); + sockfd_ = -1; + } + } + } + + freeaddrinfo(servinfo); // all done with this structure + + if (sockfd_ == -1) { + GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " + << host_name_ << ":" << port_num_; + } +} + +// End of class Streaming Listener +#endif // GTEST_CAN_STREAM_RESULTS__ + +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message = message.GetString(); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +ScopedTrace::~ScopedTrace() + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + UnitTest::GetInstance()->PopGTestTrace(); +} + + +// class OsStackTraceGetter + +// Returns the current OS stack trace as an std::string. Parameters: +// +// max_depth - the maximum number of stack frames to be included +// in the trace. +// skip_count - the number of top frames to be skipped; doesn't count +// against max_depth. +// +string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */, + int /* skip_count */) + GTEST_LOCK_EXCLUDED_(mutex_) { + return ""; +} + +void OsStackTraceGetter::UponLeavingGTest() + GTEST_LOCK_EXCLUDED_(mutex_) { +} + +const char* const +OsStackTraceGetter::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; + +// A helper class that creates the premature-exit file in its +// constructor and deletes the file in its destructor. +class ScopedPrematureExitFile { + public: + explicit ScopedPrematureExitFile(const char* premature_exit_filepath) + : premature_exit_filepath_(premature_exit_filepath) { + // If a path to the premature-exit file is specified... + if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { + // create the file with a single "0" character in it. I/O + // errors are ignored as there's nothing better we can do and we + // don't want to fail the test because of this. + FILE* pfile = posix::FOpen(premature_exit_filepath, "w"); + fwrite("0", 1, 1, pfile); + fclose(pfile); + } + } + + ~ScopedPrematureExitFile() { + if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { + remove(premature_exit_filepath_); + } + } + + private: + const char* const premature_exit_filepath_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); +}; + +} // namespace internal + +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + +// class UnitTest + +// Gets the singleton UnitTest object. The first time this method is +// called, a UnitTest object is constructed and returned. Consecutive +// calls will return the same object. +// +// We don't protect this under mutex_ as a user is not supposed to +// call this before main() starts, from which point on the return +// value will never change. +UnitTest* UnitTest::GetInstance() { + // When compiled with MSVC 7.1 in optimized mode, destroying the + // UnitTest object upon exiting the program messes up the exit code, + // causing successful tests to appear failed. We have to use a + // different implementation in this case to bypass the compiler bug. + // This implementation makes the compiler happy, at the cost of + // leaking the UnitTest object. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) + static UnitTest* const instance = new UnitTest; + return instance; +#else + static UnitTest instance; + return &instance; +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTest::reportable_disabled_test_count() const { + return impl()->reportable_disabled_test_count(); +} + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTest::reportable_test_count() const { + return impl()->reportable_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the time of the test program start, in ms from the start of the +// UNIX epoch. +internal::TimeInMillis UnitTest::start_timestamp() const { + return impl()->start_timestamp(); +} + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Returns the TestResult containing information on test failures and +// properties logged outside of individual test cases. +const TestResult& UnitTest::ad_hoc_test_result() const { + return *impl()->ad_hoc_test_result(); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); +} + +// Registers and returns a global test environment. When a test +// program is run, all global test environments will be set-up in the +// order they were registered. After all tests in the program have +// finished, all global test environments will be torn-down in the +// *reverse* order they were registered. +// +// The UnitTest object takes ownership of the given environment. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +Environment* UnitTest::AddEnvironment(Environment* env) { + if (env == NULL) { + return NULL; + } + + impl_->environments().push_back(env); + return env; +} + +// Adds a TestPartResult to the current TestResult object. All Google Test +// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call +// this to report their results. The user code should use the +// assertion macros instead of calling this directly. +void UnitTest::AddTestPartResult( + TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) { + Message msg; + msg << message; + + internal::MutexLock lock(&mutex_); + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; + } + } + + if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + msg << internal::kStackTraceMarker << os_stack_trace; + } + + const TestPartResult result = + TestPartResult(result_type, file_name, line_number, + msg.GetString().c_str()); + impl_->GetTestPartResultReporterForCurrentThread()-> + ReportTestPartResult(result); + + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + // Dereference NULL through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: Symbian doesn't implement abort() well, and some debuggers + // don't correctly trap abort(). + *static_cast(NULL) = 1; +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw internal::GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } + } +} + +// Adds a TestProperty to the current TestResult object when invoked from +// inside a test, to current TestCase's ad_hoc_test_result_ when invoked +// from SetUpTestCase or TearDownTestCase, or to the global property set +// when invoked elsewhere. If the result already contains a property with +// the same key, the value will be updated. +void UnitTest::RecordProperty(const std::string& key, + const std::string& value) { + impl_->RecordProperty(TestProperty(key, value)); +} + +// Runs all tests in this UnitTest object and prints the result. +// Returns 0 if successful, or 1 otherwise. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +int UnitTest::Run() { + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Google Test implements this protocol for catching that a test + // program exits before returning control to Google Test: + // + // 1. Upon start, Google Test creates a file whose absolute path + // is specified by the environment variable + // TEST_PREMATURE_EXIT_FILE. + // 2. When Google Test has finished its work, it deletes the file. + // + // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before + // running a Google-Test-based test program and check the existence + // of the file at the end of the test execution to see if it has + // exited prematurely. + + // If we are in the child process of a death test, don't + // create/delete the premature exit file, as doing so is unnecessary + // and will confuse the parent process. Otherwise, create/delete + // the file upon entering/leaving this function. If the program + // somehow exits before this function has a chance to return, the + // premature-exit file will be left undeleted, causing a test runner + // that understands the premature-exit-file protocol to report the + // test as having failed. + const internal::ScopedPrematureExitFile premature_exit_file( + in_death_test_child_process ? + NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); + + // Captures the value of GTEST_FLAG(catch_exceptions). This value will be + // used for the duration of the program. + impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); + +#if GTEST_HAS_SEH + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected. + if (impl()->catch_exceptions() || in_death_test_child_process) { +# if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +# endif // !GTEST_OS_WINDOWS_MOBILE + +# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +# endif + +# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +# endif + } +#endif // GTEST_HAS_SEH + + return internal::HandleExceptionsInMethodIfSupported( + impl(), + &internal::UnitTestImpl::RunAllTests, + "auxiliary test code (environments or event listeners)") ? 0 : 1; +} + +// Returns the working directory when the first TEST() or TEST_F() was +// executed. +const char* UnitTest::original_working_dir() const { + return impl_->original_working_dir_.c_str(); +} + +// Returns the TestCase object for the test that's currently running, +// or NULL if no test is running. +const TestCase* UnitTest::current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_case(); +} + +// Returns the TestInfo object for the test that's currently running, +// or NULL if no test is running. +const TestInfo* UnitTest::current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_info(); +} + +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST +// Returns ParameterizedTestCaseRegistry object used to keep track of +// value-parameterized tests and instantiate and register them. +internal::ParameterizedTestCaseRegistry& + UnitTest::parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_) { + return impl_->parameterized_test_registry(); +} +#endif // GTEST_HAS_PARAM_TEST + +// Creates an empty UnitTest. +UnitTest::UnitTest() { + impl_ = new internal::UnitTestImpl(this); +} + +// Destructor of UnitTest. +UnitTest::~UnitTest() { + delete impl_; +} + +// Pushes a trace defined by SCOPED_TRACE() on to the per-thread +// Google Test trace stack. +void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().push_back(trace); +} + +// Pops a trace from the per-thread Google Test trace stack. +void UnitTest::PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().pop_back(); +} + +namespace internal { + +UnitTestImpl::UnitTestImpl(UnitTest* parent) + : parent_(parent), +#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_per_thread_test_part_result_reporter_(this), +# 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_( + &default_global_test_part_result_reporter_), + per_thread_test_part_result_reporter_( + &default_per_thread_test_part_result_reporter_), +#if GTEST_HAS_PARAM_TEST + parameterized_test_registry_(), + parameterized_tests_registered_(false), +#endif // GTEST_HAS_PARAM_TEST + last_death_test_case_(-1), + current_test_case_(NULL), + current_test_info_(NULL), + ad_hoc_test_result_(), + os_stack_trace_getter_(NULL), + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. + start_timestamp_(0), + elapsed_time_(0), +#if GTEST_HAS_DEATH_TEST + death_test_factory_(new DefaultDeathTestFactory), +#endif + // Will be overridden by the flag before first use. + catch_exceptions_(false) { + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); +} + +UnitTestImpl::~UnitTestImpl() { + // Deletes every TestCase. + ForEach(test_cases_, internal::Delete); + + // Deletes every Environment. + ForEach(environments_, internal::Delete); + + delete os_stack_trace_getter_; +} + +// Adds a TestProperty to the current TestResult object when invoked in a +// context of a test, to current test case's ad_hoc_test_result when invoke +// from SetUpTestCase/TearDownTestCase, or to the global property set +// otherwise. If the result already contains a property with the same key, +// the value will be updated. +void UnitTestImpl::RecordProperty(const TestProperty& test_property) { + std::string xml_element; + TestResult* test_result; // TestResult appropriate for property recording. + + if (current_test_info_ != NULL) { + xml_element = "testcase"; + test_result = &(current_test_info_->result_); + } else if (current_test_case_ != NULL) { + xml_element = "testsuite"; + test_result = &(current_test_case_->ad_hoc_test_result_); + } else { + xml_element = "testsuites"; + test_result = &ad_hoc_test_result_; + } + test_result->RecordProperty(xml_element, test_property); +} + +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const std::string& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +#if GTEST_CAN_STREAM_RESULTS_ +// Initializes event listeners for streaming test results in string form. +// Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureStreamingOutput() { + const std::string& target = GTEST_FLAG(stream_result_to); + if (!target.empty()) { + const size_t pos = target.find(':'); + if (pos != std::string::npos) { + listeners()->Append(new StreamingListener(target.substr(0, pos), + target.substr(pos+1))); + } else { + printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", + target.c_str()); + fflush(stdout); + } + } +} +#endif // GTEST_CAN_STREAM_RESULTS_ + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Configures listeners for streaming test results to the specified server. + ConfigureStreamingOutput(); +#endif // GTEST_CAN_STREAM_RESULTS_ + } +} + +// A predicate that checks the name of a TestCase against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestCaseNameIs is copyable. +class TestCaseNameIs { + public: + // Constructor. + explicit TestCaseNameIs(const std::string& name) + : name_(name) {} + + // Returns true iff the name of test_case matches name_. + bool operator()(const TestCase* test_case) const { + return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + } + + private: + std::string name_; +}; + +// Finds and returns a TestCase with the given name. If one doesn't +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. +// +// Arguments: +// +// test_case_name: name of the test case +// type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) { + // Can we find a TestCase with the given name? + const std::vector::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; + + // No. Let's create one. + TestCase* const new_test_case = + new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(test_case_name, + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); + } + + test_case_indices_.push_back(static_cast(test_case_indices_.size())); + return new_test_case; +} + +// Helpers for setting up / tearing down the given environment. They +// are for use in the ForEach() function. +static void SetUpEnvironment(Environment* env) { env->SetUp(); } +static void TearDownEnvironment(Environment* env) { env->TearDown(); } + +// Runs all tests in this UnitTest object, prints the result, and +// returns true if all tests are successful. If any exception is +// thrown during a test, the test is considered to be failed, but the +// rest of the tests will still be run. +// +// When parameterized tests are enabled, it expands and registers +// parameterized tests first in RegisterParameterizedTests(). +// All other functions called from RunAllTests() may safely assume that +// parameterized tests are ready to be counted and run. +bool UnitTestImpl::RunAllTests() { + // Makes sure InitGoogleTest() was called. + if (!GTestIsInitialized()) { + printf("%s", + "\nThis test program did NOT call ::testing::InitGoogleTest " + "before calling RUN_ALL_TESTS(). Please fix it.\n"); + return false; + } + + // Do not run any test if the --help flag was specified. + if (g_help_flag) + return true; + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); + + // True iff we are in a subprocess for running a thread-safe-style + // death test. + bool in_subprocess_for_death_test = false; + +#if GTEST_HAS_DEATH_TEST + in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); +#endif // GTEST_HAS_DEATH_TEST + + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); + + // Compares the full test names with the filter to decide which + // tests to run. + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return true; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + + // True iff at least one test has failed. + bool failed = false; + + TestEventListener* repeater = listeners()->repeater(); + + start_timestamp_ = GetTimeInMillis(); + repeater->OnTestProgramStart(*parent_); + + // How many times to repeat the tests? We don't want to repeat them + // when we are inside the subprocess of a death test. + const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); + // Repeats forever if the repeat count is negative. + const bool forever = repeat < 0; + for (int i = 0; forever || i != repeat; i++) { + // We want to preserve failures generated by ad-hoc test + // assertions executed before RUN_ALL_TESTS(). + ClearNonAdHocTestResult(); + + const TimeInMillis start = GetTimeInMillis(); + + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + + // Runs each test case if there is at least one test to run. + if (has_tests_to_run) { + // Sets up all environments beforehand. + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); + + // Runs the tests only if there was no fatal failure during global + // set-up. + if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } + } + + // Tears down all environments in reverse order afterwards. + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); + } + + elapsed_time_ = GetTimeInMillis() - start; + + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); + + // Gets the result and clears it. + if (!Passed()) { + failed = true; + } + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } + } + + repeater->OnTestProgramEnd(*parent_); + + return !failed; +} + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + +// Compares the name of each test with the user-specified filter to +// decide whether the test should be run, then records the result in +// each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. +// Returns the number of tests that should run. +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. + int num_runnable_tests = 0; + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; + const std::string &test_case_name = test_case->name(); + test_case->set_should_run(false); + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; + const std::string test_name(test_info->name()); + // A test is disabled if test case name or test name matches + // kDisableTestFilter. + const bool is_disabled = + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); + test_info->is_disabled_ = is_disabled; + + const bool matches_filter = + internal::UnitTestOptions::FilterMatchesTest(test_case_name, + test_name); + test_info->matches_filter_ = matches_filter; + + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; + + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); + + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; + + test_info->should_run_ = is_selected; + test_case->set_should_run(test_case->should_run() || is_selected); + } + } + return num_selected_tests; +} + +// Prints the given C-string on a single line by replacing all '\n' +// characters with string "\\n". If the output takes more than +// max_length characters, only prints the first max_length characters +// and "...". +static void PrintOnOneLine(const char* str, int max_length) { + if (str != NULL) { + for (int i = 0; *str != '\0'; ++str) { + if (i >= max_length) { + printf("..."); + break; + } + if (*str == '\n') { + printf("\\n"); + i += 2; + } else { + printf("%c", *str); + ++i; + } + } + } +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + // Print at most this many characters for each type/value parameter. + const int kMaxParamLength = 250; + + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter_) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.", test_case->name()); + if (test_case->type_param() != NULL) { + printf(" # %s = ", kTypeParamLabel); + // We print the type parameter on a single line to make + // the output easy to parse by a program. + PrintOnOneLine(test_case->type_param(), kMaxParamLength); + } + printf("\n"); + } + printf(" %s", test_info->name()); + if (test_info->value_param() != NULL) { + printf(" # %s = ", kValueParamLabel); + // We print the value parameter on a single line to make the + // output easy to parse by a program. + PrintOnOneLine(test_info->value_param(), kMaxParamLength); + } + printf("\n"); + } + } + } + fflush(stdout); +} + +// Sets the OS stack trace getter. +// +// Does nothing if the input and the current OS stack trace getter are +// the same; otherwise, deletes the old getter and makes the input the +// current getter. +void UnitTestImpl::set_os_stack_trace_getter( + OsStackTraceGetterInterface* getter) { + if (os_stack_trace_getter_ != getter) { + delete os_stack_trace_getter_; + os_stack_trace_getter_ = getter; + } +} + +// Returns the current OS stack trace getter if it is not NULL; +// otherwise, creates an OsStackTraceGetter, makes it the current +// getter, and returns it. +OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { + if (os_stack_trace_getter_ == NULL) { + os_stack_trace_getter_ = new OsStackTraceGetter; + } + + return os_stack_trace_getter_; +} + +// Returns the TestResult for the test that's currently running, or +// the TestResult for the ad hoc test if no test is running. +TestResult* UnitTestImpl::current_test_result() { + return current_test_info_ ? + &(current_test_info_->result_) : &ad_hoc_test_result_; +} + +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast(i); + } +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { + // We pass skip_count + 1 to skip this wrapper function in addition + // to what the user really wants to skip. + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); +} + +// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to +// suppress unreachable code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Parses a string as a command line flag. The string should have +// the format "--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. +const char* ParseFlagValue(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 "--" followed by GTEST_FLAG_PREFIX_. + const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + 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 bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(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 an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, std::string* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(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; +} + +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", std::string(str, p).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +#if GTEST_CAN_STREAM_RESULTS_ +" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" +" Stream test results to the given server.\n" +#endif // GTEST_CAN_STREAM_RESULTS_ +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" +" Do not report exceptions as test failures. Instead, allow them\n" +" to crash the program or throw a pop-up (on Windows).\n" +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. +template +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { + const std::string arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + using internal::ParseBoolFlag; + using internal::ParseInt32Flag; + using internal::ParseStringFlag; + + // Do we see a Google Test flag? + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, + >EST_FLAG(throw_on_failure)) + ) { + // 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--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; + } + } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } +} + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#if GTEST_HAS_DEATH_TEST + + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } + +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); +} + +} // namespace internal + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +void InitGoogleTest(int* argc, char** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleTest(int* argc, wchar_t** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +} // namespace testing +// Copyright 2005, 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), vladl@google.com (Vlad Losev) +// +// This file implements death tests. + + +#if GTEST_HAS_DEATH_TEST + +# if GTEST_OS_MAC +# include +# endif // GTEST_OS_MAC + +# include +# include +# include + +# if GTEST_OS_LINUX +# include +# endif // GTEST_OS_LINUX + +# include + +# if GTEST_OS_WINDOWS +# include +# else +# include +# include +# endif // GTEST_OS_WINDOWS + +# if GTEST_OS_QNX +# include +# endif // GTEST_OS_QNX + +#endif // GTEST_HAS_DEATH_TEST + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +// Constants. + +// The default death test style. +static const char kDefaultDeathTestStyle[] = "fast"; + +GTEST_DEFINE_string_( + death_test_style, + internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), + "Indicates how to run a death test in a forked child process: " + "\"threadsafe\" (child process re-executes the test binary " + "from the beginning, running only the specific death test) or " + "\"fast\" (child process runs the death test immediately " + "after forking)."); + +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + +namespace internal { +GTEST_DEFINE_string_( + internal_run_death_test, "", + "Indicates the file, line number, temporal index of " + "the single death test to run, and a file descriptor to " + "which a success code may be sent, all separated by " + "the '|' characters. This flag is specified if and only if the current " + "process is a sub-process launched for running a thread-safe " + "death test. FOR INTERNAL USE ONLY."); +} // namespace internal + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Valid only for fast death tests. Indicates the code is running in the +// child process of a fast style death test. +static bool g_in_fast_death_test_child = false; + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +bool InDeathTestChild() { +# if GTEST_OS_WINDOWS + + // On Windows, death tests are thread-safe regardless of the value of the + // death_test_style flag. + return !GTEST_FLAG(internal_run_death_test).empty(); + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") + return !GTEST_FLAG(internal_run_death_test).empty(); + else + return g_in_fast_death_test_child; +#endif +} + +} // namespace internal + +// ExitedWithCode constructor. +ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { +} + +// ExitedWithCode function-call operator. +bool ExitedWithCode::operator()(int exit_status) const { +# if GTEST_OS_WINDOWS + + return exit_status == exit_code_; + +# else + + return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; + +# endif // GTEST_OS_WINDOWS +} + +# if !GTEST_OS_WINDOWS +// KilledBySignal constructor. +KilledBySignal::KilledBySignal(int signum) : signum_(signum) { +} + +// KilledBySignal function-call operator. +bool KilledBySignal::operator()(int exit_status) const { + return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; +} +# endif // !GTEST_OS_WINDOWS + +namespace internal { + +// Utilities needed for death tests. + +// Generates a textual description of a given exit code, in the format +// specified by wait(2). +static std::string ExitSummary(int exit_code) { + Message m; + +# if GTEST_OS_WINDOWS + + m << "Exited with exit status " << exit_code; + +# else + + if (WIFEXITED(exit_code)) { + m << "Exited with exit status " << WEXITSTATUS(exit_code); + } else if (WIFSIGNALED(exit_code)) { + m << "Terminated by signal " << WTERMSIG(exit_code); + } +# ifdef WCOREDUMP + if (WCOREDUMP(exit_code)) { + m << " (core dumped)"; + } +# endif +# endif // GTEST_OS_WINDOWS + + return m.GetString(); +} + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +bool ExitedUnsuccessfully(int exit_status) { + return !ExitedWithCode(0)(exit_status); +} + +# if !GTEST_OS_WINDOWS +// Generates a textual failure message when a death test finds more than +// one thread running, or cannot determine the number of threads, prior +// to executing the given statement. It is the responsibility of the +// caller not to pass a thread_count of 1. +static std::string DeathTestThreadWarning(size_t thread_count) { + Message msg; + msg << "Death tests use fork(), which is unsafe particularly" + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; + if (thread_count == 0) + msg << "couldn't detect the number of threads."; + else + msg << "detected " << thread_count << " threads."; + return msg.GetString(); +} +# endif // !GTEST_OS_WINDOWS + +// Flag characters for reporting a death test that did not die. +static const char kDeathTestLived = 'L'; +static const char kDeathTestReturned = 'R'; +static const char kDeathTestThrew = 'T'; +static const char kDeathTestInternalError = 'I'; + +// An enumeration describing all of the possible ways that a death test can +// conclude. DIED means that the process died while executing the test +// code; LIVED means that process lived beyond the end of the test code; +// RETURNED means that the test statement attempted to execute a return +// statement, which is not allowed; THREW means that the test statement +// returned control by throwing an exception. IN_PROGRESS means the test +// has not yet concluded. +// TODO(vladl@google.com): Unify names and possibly values for +// AbortReason, DeathTestOutcome, and flag characters above. +enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; + +// Routine for aborting the program which is safe to call from an +// exec-style death test child process, in which case the error +// message is propagated back to the parent process. Otherwise, the +// message is simply printed to stderr. In either case, the program +// then exits with status 1. +void DeathTestAbort(const std::string& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. + const InternalRunDeathTestFlag* const flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + if (flag != NULL) { + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); + fputc(kDeathTestInternalError, parent); + fprintf(parent, "%s", message.c_str()); + fflush(parent); + _exit(1); + } else { + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); + posix::Abort(); + } +} + +// A replacement for CHECK that calls DeathTestAbort if the assertion +// fails. +# define GTEST_DEATH_TEST_CHECK_(expression) \ + do { \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for +// evaluating any system call that fulfills two conditions: it must return +// -1 on failure, and set errno to EINTR when it is interrupted and +// should be tried again. The macro expands to a loop that repeatedly +// evaluates the expression as long as it evaluates to -1 and sets +// errno to EINTR. If the expression evaluates to -1 but errno is +// something other than EINTR, DeathTestAbort is called. +# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ + do { \ + int gtest_retval; \ + do { \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression + " != -1"); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +std::string GetLastErrnoDescription() { + return errno == 0 ? "" : posix::StrError(errno); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} + +// Death test constructor. Increments the running death test count +// for the current test. +DeathTest::DeathTest() { + TestInfo* const info = GetUnitTestImpl()->current_test_info(); + if (info == NULL) { + DeathTestAbort("Cannot run a death test outside of a TEST or " + "TEST_F construct"); + } +} + +// Creates and returns a death test by dispatching to the current +// death test factory. +bool DeathTest::Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) { + return GetUnitTestImpl()->death_test_factory()->Create( + statement, regex, file, line, test); +} + +const char* DeathTest::LastMessage() { + return last_death_test_message_.c_str(); +} + +void DeathTest::set_last_death_test_message(const std::string& message) { + last_death_test_message_ = message; +} + +std::string DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } + void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } + void set_write_fd(int fd) { write_fd_ = fd; } + + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + + private: + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. + const char* const statement_; + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // True if the death test child process has been successfully spawned. + bool spawned_; + // The exit status of the child process. + int status_; + // How the death test concluded. + DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; +}; + +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; + + // The read() here blocks until data is available (signifying the + // failure of the death test) or until the pipe is closed (signifying + // its success), so it's okay to call this in the parent before + // the child process has exited. + do { + bytes_read = posix::Read(read_fd(), &flag, 1); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestThrew: + set_outcome(THREW); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_fd()); // Does not return. + break; + default: + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast(flag) << ")"; + } + } else { + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); + } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} + +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : + reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; + + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + // We are leaking the descriptor here because on some platforms (i.e., + // when built as Windows DLL), destructors of global objects will still + // run after calling _exit(). On such systems, write_fd_ will be + // indirectly closed from the destructor of UnitTestImpl, causing double + // close if it is also closed here. On debug configurations, double close + // may assert. As there are no in-process buffers to flush here, we are + // relying on the OS to close the descriptor after the process terminates + // when the destructors are not run. + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// Returns an indented copy of stderr output for a death test. +// This makes distinguishing death test output lines from regular log lines +// much easier. +static ::std::string FormatDeathTestOutput(const ::std::string& output) { + ::std::string ret; + for (size_t at = 0; ; ) { + const size_t line_end = output.find('\n', at); + ret += "[ DEATH ] "; + if (line_end == ::std::string::npos) { + ret += output.substr(at); + break; + } + ret += output.substr(at, line_end + 1 - at); + at = line_end + 1; + } + return ret; +} + +// Assesses the success or failure of a death test, using both private +// members which have previously been set, and one argument: +// +// Private data members: +// outcome: An enumeration describing how the death test +// concluded: DIED, LIVED, THREW, or RETURNED. The death test +// fails in the latter three cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to +// the test's captured standard error output; the death test +// fails if it does not match. +// +// Argument: +// status_ok: true if exit_status is acceptable in the context of +// this particular death test, which fails if it is false +// +// Returns true iff all of the above conditions are met. Otherwise, the +// first failing condition, in the order given above, is the one that is +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) + return false; + + const std::string error_message = GetCapturedStderr(); + + bool success = false; + Message buffer; + + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { + case LIVED: + buffer << " Result: failed to die.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case THREW: + buffer << " Result: threw an exception.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case RETURNED: + buffer << " Result: illegal return in test statement.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case DIED: + if (status_ok) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { + success = true; + } else { + buffer << " Result: died but not with expected error.\n" + << " Expected: " << regex()->pattern() << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + } else { + buffer << " Result: died but not with expected exit code:\n" + << " " << ExitSummary(status()) << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + break; + case IN_PROGRESS: + default: + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; + } + + DeathTest::set_last_death_test_message(buffer.GetString()); + return success; +} + +# if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status_code; + GTEST_DEATH_TEST_CHECK_( + ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); + child_handle_.Reset(); + set_status(static_cast(status_code)); + return status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + + "=" + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(static_cast(::GetCurrentProcessId())) + + // size_t has the same width as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + "|" + StreamableToString(reinterpret_cast(write_handle)) + + "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + std::string command_line = + std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + + internal_flag + "\""; + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +# else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; +} + +// A concrete death test class that forks, then immediately runs the test +// in the child process. +class NoExecDeathTest : public ForkingDeathTest { + public: + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } + virtual TestRole AssumeRole(); +}; + +// The AssumeRole process for a fork-and-run death test. It implements a +// straightforward fork, with a simple pipe to transmit the status byte. +DeathTest::TestRole NoExecDeathTest::AssumeRole() { + const size_t thread_count = GetThreadCount(); + if (thread_count != 1) { + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + + DeathTest::set_last_death_test_message(""); + CaptureStderr(); + // When we fork the process below, the log file buffers are copied, but the + // file descriptors are shared. We flush all log files here so that closing + // the file descriptors in the child process doesn't throw off the + // synchronization between descriptors and buffers in the parent process. + // This is as close to the fork as possible to avoid a race condition in case + // there are multiple threads running before the death test, and another + // thread writes to the log file. + FlushInfoLog(); + + const pid_t child_pid = fork(); + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + set_child_pid(child_pid); + if (child_pid == 0) { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); + set_write_fd(pipe_fd[1]); + // Redirects all logging to stderr in the child process to prevent + // concurrent writes to the log files. We capture stderr in the parent + // process and append the child process' output to a log. + LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); + g_in_fast_death_test_child = true; + return EXECUTE_TEST; + } else { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; + } +} + +// A concrete death test class that forks and re-executes the main +// program from the beginning, with command-line flags set that cause +// only this specific death test to be run. +class ExecDeathTest : public ForkingDeathTest { + public: + ExecDeathTest(const char* a_statement, const RE* a_regex, + const char* file, int line) : + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } + virtual TestRole AssumeRole(); + private: + static ::std::vector + GetArgvsForDeathTestChildProcess() { + ::std::vector args = GetInjectableArgvs(); + return args; + } + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + + private: + std::vector args_; +}; + +// A struct that encompasses the arguments to the child process of a +// threadsafe-style death test process. +struct ExecDeathTestArgs { + char* const* argv; // Command-line arguments for the child's call to exec + int close_fd; // File descriptor to close; the read end of a pipe +}; + +# if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +# else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +# endif // GTEST_OS_MAC + +# if !GTEST_OS_QNX +// The main function for a threadsafe-style death test child process. +// This function is called in a clone()-ed process and thus must avoid +// any potentially unsafe operations like malloc or libc functions. +static int ExecDeathTestChildMain(void* child_arg) { + ExecDeathTestArgs* const args = static_cast(child_arg); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); + + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + // We can safely call execve() as it's a direct system call. We + // cannot use execvp() as it's a libc function and thus potentially + // unsafe. Since execve() doesn't search the PATH, the user must + // invoke the test program via a valid path that contains at least + // one path separator. + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " + + original_dir + " failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; +} +# endif // !GTEST_OS_QNX + +// Two utility routines that together determine the direction the stack +// grows. +// This could be accomplished more elegantly by a single recursive +// function, but we want to guard against the unlikely possibility of +// a smart compiler optimizing the recursion away. +// +// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining +// StackLowerThanAddress into StackGrowsDown, which then doesn't give +// correct answer. +void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; +void StackLowerThanAddress(const void* ptr, bool* result) { + int dummy; + *result = (&dummy < ptr); +} + +bool StackGrowsDown() { + int dummy; + bool result; + StackLowerThanAddress(&dummy, &result); + return result; +} + +// Spawns a child process with the same executable as the current process in +// a thread-safe manner and instructs it to run the death test. The +// implementation uses fork(2) + exec. On systems where clone(2) is +// available, it is used instead, being slightly more thread-safe. On QNX, +// fork supports only single-threaded environments, so this function uses +// spawn(2) there instead. The function dies with an error message if +// anything goes wrong. +static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { + ExecDeathTestArgs args = { argv, close_fd }; + pid_t child_pid = -1; + +# if GTEST_OS_QNX + // Obtains the current directory and sets it to be closed in the child + // process. + const int cwd_fd = open(".", O_RDONLY); + GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + int fd_flags; + // Set close_fd to be closed after spawn. + GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, + fd_flags | FD_CLOEXEC)); + struct inheritance inherit = {0}; + // spawn is a system call. + child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); + // Restores the current working directory. + GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); + +# else // GTEST_OS_QNX +# if GTEST_OS_LINUX + // When a SIGPROF signal is received while fork() or clone() are executing, + // the process may hang. To avoid this, we ignore SIGPROF here and re-enable + // it after the call to fork()/clone() is complete. + struct sigaction saved_sigprof_action; + struct sigaction ignore_sigprof_action; + memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); + sigemptyset(&ignore_sigprof_action.sa_mask); + ignore_sigprof_action.sa_handler = SIG_IGN; + GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( + SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); +# endif // GTEST_OS_LINUX + +# if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + + // Maximum stack alignment in bytes: For a downward-growing stack, this + // amount is subtracted from size of the stack space to get an address + // that is within the stack space and is aligned on all systems we care + // about. As far as I know there is no ABI with stack alignment greater + // than 64. We assume stack and stack_size already have alignment of + // kMaxStackAlignment. + const size_t kMaxStackAlignment = 64; + void* const stack_top = + static_cast(stack) + + (stack_grows_down ? stack_size - kMaxStackAlignment : 0); + GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && + reinterpret_cast(stack_top) % kMaxStackAlignment == 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +# else + const bool use_fork = true; +# endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } +# endif // GTEST_OS_QNX +# if GTEST_OS_LINUX + GTEST_DEATH_TEST_CHECK_SYSCALL_( + sigaction(SIGPROF, &saved_sigprof_action, NULL)); +# endif // GTEST_OS_LINUX + + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + return child_pid; +} + +// The AssumeRole process for a fork-and-exec death test. It re-executes the +// main program from the beginning, setting the --gtest_filter +// and --gtest_internal_run_death_test flags to cause only the current +// death test to be re-run. +DeathTest::TestRole ExecDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + // Clear the close-on-exec flag on the write end of the pipe, lest + // it be closed when the child process does an exec: + GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); + + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(pipe_fd[1]); + Arguments args; + args.AddArguments(GetArgvsForDeathTestChildProcess()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // See the comment in NoExecDeathTest::AssumeRole for why the next line + // is necessary. + FlushInfoLog(); + + const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_child_pid(child_pid); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; +} + +# endif // !GTEST_OS_WINDOWS + +// Creates a concrete DeathTest-derived class that depends on the +// --gtest_death_test_style flag, and sets the pointer pointed to +// by the "test" argument to its address. If the test should be +// skipped, sets that pointer to NULL. Returns true, unless the +// flag is set to an invalid value. +bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, + const char* file, int line, + DeathTest** test) { + UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const int death_test_index = impl->current_test_info() + ->increment_death_test_count(); + + if (flag != NULL) { + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message( + "Death test count (" + StreamableToString(death_test_index) + + ") somehow exceeded expected maximum (" + + StreamableToString(flag->index()) + ")"); + return false; + } + + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { + *test = NULL; + return true; + } + } + +# if GTEST_OS_WINDOWS + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") { + *test = new ExecDeathTest(statement, regex, file, line); + } else if (GTEST_FLAG(death_test_style) == "fast") { + *test = new NoExecDeathTest(statement, regex); + } + +# endif // GTEST_OS_WINDOWS + + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message( + "Unknown death test style \"" + GTEST_FLAG(death_test_style) + + "\" encountered"); + return false; + } + + return true; +} + +// Splits a given string on a given delimiter, populating a given +// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have +// ::std::string, so we can use it here. +static void SplitString(const ::std::string& str, char delimiter, + ::std::vector< ::std::string>* dest) { + ::std::vector< ::std::string> parsed; + ::std::string::size_type pos = 0; + while (::testing::internal::AlwaysTrue()) { + const ::std::string::size_type colon = str.find(delimiter, pos); + if (colon == ::std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, colon - pos)); + pos = colon + 1; + } + } + dest->swap(parsed); +} + +# if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort("Unable to open parent process " + + StreamableToString(parent_process_id)); + } + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the pipe handle " + + StreamableToString(write_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the event handle " + + StreamableToString(event_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort("Unable to convert pipe handle " + + StreamableToString(write_handle_as_size_t) + + " to a file descriptor"); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; +} +# endif // GTEST_OS_WINDOWS + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { + if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + + // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we + // can use it here. + int line = -1; + int index = -1; + ::std::vector< ::std::string> fields; + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +# if GTEST_OS_WINDOWS + + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +# else + + if (fields.size() != 4 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + +# endif // GTEST_OS_WINDOWS + + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); +} + +} // namespace internal + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace testing +// 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. +// +// Authors: keith.ray@gmail.com (Keith Ray) + + +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include +#elif GTEST_OS_WINDOWS +# include +# include +#elif GTEST_OS_SYMBIAN +// Symbian OpenC has PATH_MAX in sys/syslimits.h +# include +#else +# include +# include // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_MAX_ _MAX_PATH +#elif defined(PATH_MAX) +# define GTEST_PATH_MAX_ PATH_MAX +#elif defined(_XOPEN_PATH_MAX) +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX +#else +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX +#endif // GTEST_OS_WINDOWS + + +namespace testing { +namespace internal { + +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. +const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; +const char kPathSeparatorString[] = "\\"; +const char kAlternatePathSeparatorString[] = "/"; +# if GTEST_OS_WINDOWS_MOBILE +// Windows CE doesn't have a current directory. You should not use +// the current directory in tests on Windows CE, but this at least +// provides a reasonable fallback. +const char kCurrentDirectoryString[] = "\\"; +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES +const DWORD kInvalidFileAttributes = 0xffffffff; +# else +const char kCurrentDirectoryString[] = ".\\"; +# endif // GTEST_OS_WINDOWS_MOBILE +#else +const char kPathSeparator = '/'; +const char kPathSeparatorString[] = "/"; +const char kCurrentDirectoryString[] = "./"; +#endif // GTEST_OS_WINDOWS + +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + +// Returns the current working directory, or "" if unsuccessful. +FilePath FilePath::GetCurrentDir() { +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. + return FilePath(kCurrentDirectoryString); +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#else + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns a copy of the FilePath with the case-insensitive extension removed. +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns +// FilePath("dir/file"). If a case-insensitive extension is not +// found, returns a copy of the original FilePath. +FilePath FilePath::RemoveExtension(const char* extension) const { + const std::string dot_extension = std::string(".") + extension; + if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { + return FilePath(pathname_.substr( + 0, pathname_.length() - dot_extension.length())); + } + return *this; +} + +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + +// Returns a copy of the FilePath with the directory part removed. +// Example: FilePath("path/to/file").RemoveDirectoryName() returns +// FilePath("file"). If there is no directory part ("just_a_file"), it returns +// the FilePath unmodified. If there is no file part ("just_a_dir/") it +// returns an empty FilePath (""). +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveDirectoryName() const { + const char* const last_sep = FindLastPathSeparator(); + return last_sep ? FilePath(last_sep + 1) : *this; +} + +// RemoveFileName returns the directory path with the filename removed. +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does +// not have a file, like "just/a/dir/", it returns the FilePath unmodified. +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveFileName() const { + const char* const last_sep = FindLastPathSeparator(); + std::string dir; + if (last_sep) { + dir = std::string(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); +} + +// Helper functions for naming files in a directory for xml output. + +// Given directory = "dir", base_name = "test", number = 0, +// extension = "xml", returns "dir/test.xml". If number is greater +// than zero (e.g., 12), returns "dir/test_12.xml". +// On Windows platform, uses \ as the separator rather than /. +FilePath FilePath::MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension) { + std::string file; + if (number == 0) { + file = base_name.string() + "." + extension; + } else { + file = base_name.string() + "_" + StreamableToString(number) + + "." + extension; + } + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(dir.string() + kPathSeparator + relative_path.string()); +} + +// Returns true if pathname describes something findable in the file-system, +// either a file, directory, or whatever. +bool FilePath::FileOrDirectoryExists() const { +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + return attributes != kInvalidFileAttributes; +#else + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns true if pathname describes a directory in the file-system +// that exists. +bool FilePath::DirectoryExists() const { + bool result = false; +#if GTEST_OS_WINDOWS + // Don't strip off trailing separator if path is a root directory on + // Windows (like "C:\\"). + const FilePath& path(IsRootDirectory() ? *this : + RemoveTrailingPathSeparator()); +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + if ((attributes != kInvalidFileAttributes) && + (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = true; + } +#else + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + + return result; +} + +// Returns true if pathname describes a root directory. (Windows has one +// root directory per disk drive.) +bool FilePath::IsRootDirectory() const { +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { + const char* const name = pathname_.c_str(); +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && + ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && + name[1] == ':' && + IsPathSeparator(name[2]); +#else + return IsPathSeparator(name[0]); +#endif +} + +// Returns a pathname for a file that does not currently exist. The pathname +// will be directory/base_name.extension or +// directory/base_name_.extension if directory/base_name.extension +// already exists. The number will be incremented until a pathname is found +// that does not already exist. +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. +// There could be a race condition if two or more processes are calling this +// function at the same time -- they could both pick the same filename. +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension) { + FilePath full_pathname; + int number = 0; + do { + full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); + } while (full_pathname.FileOrDirectoryExists()); + return full_pathname; +} + +// Returns true if FilePath ends with a path separator, which indicates that +// it is intended to represent a directory. Returns false otherwise. +// This does NOT check that a directory (or file) actually exists. +bool FilePath::IsDirectory() const { + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); +} + +// Create directories so that path exists. Returns true if successful or if +// the directories already exist; returns false if unable to create directories +// for any reason. +bool FilePath::CreateDirectoriesRecursively() const { + if (!this->IsDirectory()) { + return false; + } + + if (pathname_.length() == 0 || this->DirectoryExists()) { + return true; + } + + const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); + return parent.CreateDirectoriesRecursively() && this->CreateFolder(); +} + +// Create the directory so that path exists. Returns true if successful or +// if the directory already exists; returns false if unable to create the +// directory for any reason, including if the parent directory does not +// exist. Not named "CreateDirectory" because that's a macro on Windows. +bool FilePath::CreateFolder() const { +#if GTEST_OS_WINDOWS_MOBILE + FilePath removed_sep(this->RemoveTrailingPathSeparator()); + LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); + int result = CreateDirectory(unicode, NULL) ? 0 : -1; + delete [] unicode; +#elif GTEST_OS_WINDOWS + int result = _mkdir(pathname_.c_str()); +#else + int result = mkdir(pathname_.c_str(), 0777); +#endif // GTEST_OS_WINDOWS_MOBILE + + if (result == -1) { + return this->DirectoryExists(); // An error is OK if the directory exists. + } + return true; // No error. +} + +// If input name has a trailing separator character, remove it and return the +// name, otherwise return the name string unmodified. +// On Windows platform, uses \ as the separator, other platforms use /. +FilePath FilePath::RemoveTrailingPathSeparator() const { + return IsDirectory() + ? FilePath(pathname_.substr(0, pathname_.length() - 1)) + : *this; +} + +// Removes any redundant separators that might be in the pathname. +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other +// redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). +void FilePath::Normalize() { + if (pathname_.c_str() == NULL) { + pathname_ = ""; + return; + } + const char* src = pathname_.c_str(); + char* const dest = new char[pathname_.length() + 1]; + char* dest_ptr = dest; + memset(dest_ptr, 0, pathname_.length() + 1); + + while (*src != '\0') { + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { + src++; + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) + src++; + } + dest_ptr++; + } + *dest_ptr = '\0'; + pathname_ = dest; + delete[] dest; +} + +} // namespace internal +} // namespace testing +// 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 +#include +#include +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include // For TerminateProcess() +#elif GTEST_OS_WINDOWS +# include +# include +#else +# include +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +# include +# include +# include +#endif // GTEST_OS_MAC + +#if GTEST_OS_QNX +# include +# include +#endif // GTEST_OS_QNX + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { +namespace internal { + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast(thread_list), + sizeof(thread_t) * thread_count); + return static_cast(thread_count); + } else { + return 0; + } +} + +#elif GTEST_OS_QNX + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const int fd = open("/proc/self/as", O_RDONLY); + if (fd < 0) { + return 0; + } + procfs_info process_info; + const int status = + devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); + close(fd); + if (status == EOK) { + return static_cast(process_info.num_threads); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE + +// Implements RE. Currently only needed for death tests. + +RE::~RE() { + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } + free(const_cast(pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.full_regex_, str, 1, &match, 0) == 0; +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = posix::StrDup(regex); + + // Reserves enough bytes to hold the regular expression used for a + // full match. + const size_t full_regex_len = strlen(regex) + 10; + char* const full_pattern = new char[full_regex_len]; + + snprintf(full_pattern, full_regex_len, "^(%s)$", regex); + is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; + // We want to call regcomp(&partial_regex_, ...) even if the + // previous expression returns false. Otherwise partial_regex_ may + // not be properly initialized can may cause trouble when it's + // freed. + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } + EXPECT_TRUE(is_valid_) + << "Regular expression \"" << regex + << "\" is not a valid POSIX Extended regular expression."; + + delete[] full_pattern; +} + +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in , these aren't affected by the +// current locale. +bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsAsciiPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsAsciiWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsAsciiDigit(ch); + case 'D': return !IsAsciiDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsAsciiWhiteSpace(ch); + case 'S': return !IsAsciiWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsAsciiWordChar(ch); + case 'W': return !IsAsciiWordChar(ch); + } + return IsAsciiPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +std::string FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast(pattern_)); + free(const_cast(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. + + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + +const char kUnknownFile[] = "unknown file"; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) { + return file_name + ":"; + } +#ifdef _MSC_VER + return file_name + "(" + StreamableToString(line) + "):"; +#else + return file_name + ":" + StreamableToString(line) + ":"; +#endif // _MSC_VER +} + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +// Note that FormatCompilerIndependentFileLocation() does NOT append colon +// to the file location it produces, unlike FormatFileLocation(). +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( + const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) + return file_name; + else + return file_name + ":" + StreamableToString(line); +} + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { + const char* const marker = + severity == GTEST_INFO ? "[ INFO ]" : + severity == GTEST_WARNING ? "[WARNING]" : + severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; +} + +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4996) +#endif // _MSC_VER + +#if GTEST_HAS_STREAM_REDIRECTION + +// Object that captures an output stream (stdout/stderr). +class CapturedStream { + public: + // The ctor redirects the stream to a temporary file. + explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { +# if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +# else + // There's no guarantee that a test has write access to the current + // directory, so we create the temporary file in the /tmp directory + // instead. We use /tmp on most systems, and /sdcard on Android. + // That's because Android doesn't have /tmp. +# if GTEST_OS_LINUX_ANDROID + // Note: Android applications are expected to call the framework's + // Context.getExternalStorageDirectory() method through JNI to get + // the location of the world-writable SD Card directory. However, + // this requires a Context handle, which cannot be retrieved + // globally from native code. Doing so also precludes running the + // code as part of a regular standalone executable, which doesn't + // run in a Dalvik process (e.g. when running it through 'adb shell'). + // + // The location /sdcard is directly accessible from native code + // and is the only location (unofficially) supported by the Android + // team. It's generally a symlink to the real SD Card mount point + // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or + // other OEM-customized locations. Never rely on these, and always + // use /sdcard. + char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX"; +# else + char name_template[] = "/tmp/captured_stream.XXXXXX"; +# endif // GTEST_OS_LINUX_ANDROID + const int captured_fd = mkstemp(name_template); + filename_ = name_template; +# endif // GTEST_OS_WINDOWS + fflush(NULL); + dup2(captured_fd, fd_); + close(captured_fd); + } + + ~CapturedStream() { + remove(filename_.c_str()); + } + + std::string GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const std::string content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + // Reads the entire content of a file as an std::string. + static std::string ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; + +// Returns the size (in bytes) of a file. +size_t CapturedStream::GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + return static_cast(ftell(file)); +} + +// Reads the entire content of a file as a string. +std::string CapturedStream::ReadEntireFile(FILE* file) { + const size_t file_size = GetFileSize(file); + char* const buffer = new char[file_size]; + + size_t bytes_last_read = 0; // # of bytes read in the last fread() + size_t bytes_read = 0; // # of bytes read so far + + fseek(file, 0, SEEK_SET); + + // Keeps reading the file until we cannot read further or the + // pre-determined file size is reached. + do { + bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); + bytes_read += bytes_last_read; + } while (bytes_last_read > 0 && bytes_read < file_size); + + const std::string content(buffer, bytes_read); + delete[] buffer; + + return content; +} + +# ifdef _MSC_VER +# pragma warning(pop) +# endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +std::string GetCapturedStream(CapturedStream** captured_stream) { + const std::string content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = NULL; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +std::string GetCapturedStdout() { + return GetCapturedStream(&g_captured_stdout); +} + +// Stops capturing stderr and returns the captured string. +std::string GetCapturedStderr() { + return GetCapturedStream(&g_captured_stderr); +} + +#endif // GTEST_HAS_STREAM_REDIRECTION + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +::std::vector g_argvs; + +static const ::std::vector* g_injected_test_argvs = + NULL; // Owned. + +void SetInjectableArgvs(const ::std::vector* argvs) { + if (g_injected_test_argvs != argvs) + delete g_injected_test_argvs; + g_injected_test_argvs = argvs; +} + +const ::std::vector& GetInjectableArgvs() { + if (g_injected_test_argvs != NULL) { + return *g_injected_test_argvs; + } + return g_argvs; +} +#endif // GTEST_HAS_DEATH_TEST + +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { + DebugBreak(); + TerminateProcess(GetCurrentProcess(), 1); +} +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "GTEST_FOO" in the open-source version. +static std::string FlagToEnvVar(const char* flag) { + const std::string full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); + + Message env_var; + for (size_t i = 0; i != full_flag.length(); i++) { + env_var << ToUpper(full_flag.c_str()[i]); + } + + return env_var.GetString(); +} + +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const Message& src_text, const char* str, Int32* value) { + // Parses the environment variable as a decimal integer. + char* end = NULL; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value \"" << str << "\".\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + // Is the parsed value in the range of an Int32? + const Int32 result = static_cast(long_value); + if (long_value == LONG_MAX || long_value == LONG_MIN || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value " << str << ", which overflows.\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + *value = result; + return true; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + if (string_value == NULL) { + // The environment variable is not set. + return default_value; + } + + Int32 result = default_value; + if (!ParseInt32(Message() << "Environment variable " << env_var, + string_value, &result)) { + printf("The default value %s is used.\n", + (Message() << default_value).GetString().c_str()); + fflush(stdout); + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromGTestEnv(const char* flag, const char* default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value = posix::GetEnv(env_var.c_str()); + return value == NULL ? default_value : value; +} + +} // namespace internal +} // namespace testing +// 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 Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include // NOLINT +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) + *os << ' '; + else + *os << '-'; + } + GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Depending on the value of a char (or wchar_t), we print it in one +// of three formats: +// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), +// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a special escape sequence (e.g. '\r', '\n'). +enum CharFormat { + kAsIs, + kHexEscape, + kSpecialEscape +}; + +// Returns true if c is a printable ASCII character. We test the +// value of c directly instead of calling isprint(), which is buggy on +// Windows Mobile. +inline bool IsPrintableAscii(wchar_t c) { + return 0x20 <= c && c <= 0x7E; +} + +// Prints a wide or narrow char c as a character literal without the +// quotes, escaping it when necessary; returns how c was formatted. +// The template argument UnsignedChar is the unsigned version of Char, +// which is the type of c. +template +static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { + switch (static_cast(c)) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + if (IsPrintableAscii(c)) { + *os << static_cast(c); + return kAsIs; + } else { + *os << "\\x" + String::FormatHexInt(static_cast(c)); + return kHexEscape; + } + } + return kSpecialEscape; +} + +// Prints a wchar_t c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + return kAsIs; + case L'"': + *os << "\\\""; + return kSpecialEscape; + default: + return PrintAsCharLiteralTo(c, os); + } +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { + return PrintAsStringLiteralTo( + static_cast(static_cast(c)), os); +} + +// Prints a wide or narrow character c and its code. '\0' is printed +// as "'\\0'", other unprintable characters are also properly escaped +// using the standard C++ escape sequence. The template argument +// UnsignedChar is the unsigned version of Char, which is the type of c. +template +void PrintCharAndCodeTo(Char c, ostream* os) { + // First, print c as a literal in the most readable form we can find. + *os << ((sizeof(c) > 1) ? "L'" : "'"); + const CharFormat format = PrintAsCharLiteralTo(c, os); + *os << "'"; + + // To aid user debugging, we also print c's code in decimal, unless + // it's 0 (in which case c was printed as '\\0', making the code + // obvious). + if (c == 0) + return; + *os << " (" << static_cast(c); + + // For more convenience, we print c's code again in hexidecimal, + // unless c was already printed in the form '\x##' or the code is in + // [1, 9]. + if (format == kHexEscape || (1 <= c && c <= 9)) { + // Do nothing. + } else { + *os << ", 0x" << String::FormatHexInt(static_cast(c)); + } + *os << ")"; +} + +void PrintTo(unsigned char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} +void PrintTo(signed char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its code. L'\0' is printed as "L'\\0'". +void PrintTo(wchar_t wc, ostream* os) { + PrintCharAndCodeTo(wc, os); +} + +// Prints the given array of characters to the ostream. CharType must be either +// char or wchar_t. +// The array starts at begin, the length is len, it may include '\0' characters +// and may not be NUL-terminated. +template +static void PrintCharsAsStringTo( + const CharType* begin, size_t len, ostream* os) { + const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; + *os << kQuoteBegin; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const CharType cur = begin[index]; + if (is_previous_hex && IsXDigit(cur)) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" " << kQuoteBegin; + } + is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints a (const) char/wchar_t array of 'len' elements, starting at address +// 'begin'. CharType must be either char or wchar_t. +template +static void UniversalPrintCharArray( + const CharType* begin, size_t len, ostream* os) { + // The code + // const char kFoo[] = "foo"; + // generates an array of 4, not 3, elements, with the last one being '\0'. + // + // Therefore when printing a char array, we don't print the last element if + // it's '\0', such that the output matches the string literal as it's + // written in the source code. + if (len > 0 && begin[len - 1] == '\0') { + PrintCharsAsStringTo(begin, len - 1, os); + return; + } + + // If, however, the last element in the array is not '\0', e.g. + // const char kFoo[] = { 'f', 'o', 'o' }; + // we must print the entire array. We also print a message to indicate + // that the array is not NUL-terminated. + PrintCharsAsStringTo(begin, len, os); + *os << " (no terminating NUL)"; +} + +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints a (const) wchar_t array of 'len' elements, starting at address +// 'begin'. +void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing +// 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: mheule@google.com (Markus Heule) +// +// The Google C++ Testing Framework (Google Test) + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +using internal::GetUnitTestImpl; + +// Gets the summary of the failure message by omitting the stack trace +// in it. +std::string TestPartResult::ExtractSummary(const char* message) { + const char* const stack_trace = strstr(message, internal::kStackTraceMarker); + return stack_trace == NULL ? message : + std::string(message, stack_trace); +} + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; +} + +// Appends a TestPartResult to the array. +void TestPartResultArray::Append(const TestPartResult& result) { + array_.push_back(result); +} + +// Returns the TestPartResult at the given index (0-based). +const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { + if (index < 0 || index >= size()) { + printf("\nInvalid index (%d) into TestPartResultArray.\n", index); + internal::posix::Abort(); + } + + return array_[index]; +} + +// Returns the number of TestPartResult objects in the array. +int TestPartResultArray::size() const { + return static_cast(array_.size()); +} + +namespace internal { + +HasNewFatalFailureHelper::HasNewFatalFailureHelper() + : has_new_fatal_failure_(false), + original_reporter_(GetUnitTestImpl()-> + GetTestPartResultReporterForCurrentThread()) { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); +} + +HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( + original_reporter_); +} + +void HasNewFatalFailureHelper::ReportTestPartResult( + const TestPartResult& result) { + if (result.fatally_failed()) + has_new_fatal_failure_ = true; + original_reporter_->ReportTestPartResult(result); +} + +} // namespace internal + +} // namespace testing +// 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) + + +namespace testing { +namespace internal { + +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (IsSpace(*str)) + str++; + return str; +} + +// Verifies that registered_tests match the test names in +// defined_test_names_; returns registered_tests if successful, or +// aborts the program otherwise. +const char* TypedTestCasePState::VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests) { + typedef ::std::set::const_iterator DefinedTestIter; + registered_ = true; + + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + + Message errors; + ::std::set tests; + for (const char* names = registered_tests; names != NULL; + names = SkipComma(names)) { + const std::string name = GetPrefixUntilComma(names); + if (tests.count(name) != 0) { + errors << "Test " << name << " is listed more than once.\n"; + continue; + } + + bool found = false; + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (name == *it) { + found = true; + break; + } + } + + if (found) { + tests.insert(name); + } else { + errors << "No test named " << name + << " can be found in this test case.\n"; + } + } + + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (tests.count(*it) == 0) { + errors << "You forgot to list test " << *it << ".\n"; + } + } + + const std::string& errors_str = errors.GetString(); + if (errors_str != "") { + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors_str.c_str()); + fflush(stderr); + posix::Abort(); + } + + return registered_tests; +} + +#endif // GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing diff --git a/VihrevIB/lab2/gtest/gtest.h b/VihrevIB/lab2/gtest/gtest.h new file mode 100644 index 000000000..6e7cfc2be --- /dev/null +++ b/VihrevIB/lab2/gtest/gtest.h @@ -0,0 +1,20063 @@ +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for Google Test. It should be +// included by any test program that uses Google Test. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! +// +// Acknowledgment: Google Test borrowed the idea of automatic test +// registration from Barthelemy Dagenais' (barthelemy@prologique.com) +// easyUnit framework. + +#define _VARIADIC_MAX 10 + +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_H_ + +#include +#include +#include + +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares functions and macros used internally by +// Google Test. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ + +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan) +// +// Low-level types and utilities for porting Google Test to various +// platforms. They are subject to change without notice. DO NOT USE +// THEM IN USER CODE. +// +// This file is fundamental to Google Test. All other Google Test source +// files are expected to #include this. Therefore, it cannot #include +// any other Google Test header. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +// 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. +// +// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) +// is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. +// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::string, which is different to std::string). +// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::wstring, which is different to std::wstring). +// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular +// expressions are/aren't available. +// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that +// is/isn't available. +// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't +// enabled. +// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that +// std::wstring does/doesn't work (Google Test can +// be used where std::wstring is unavailable). +// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple +// is/isn't available. +// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the +// compiler supports Microsoft's "Structured +// Exception Handling". +// GTEST_HAS_STREAM_REDIRECTION +// - Define it to 1/0 to indicate whether the +// platform supports I/O stream redirection using +// dup() and dup2(). +// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google +// Test's own tr1 tuple implementation should be +// used. Unused when the user sets +// GTEST_HAS_TR1_TUPLE to 0. +// GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test +// is building in C++11/C++98 mode. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. + +// This header defines the following utilities: +// +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HPUX - HP-UX +// GTEST_OS_LINUX - Linux +// GTEST_OS_LINUX_ANDROID - Google Android +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_IOS - iOS +// GTEST_OS_IOS_SIMULATOR - iOS simulator +// GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_OPENBSD - OpenBSD +// GTEST_OS_QNX - QNX +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS +// +// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// most stable support. Since core members of the Google Test project +// don't have access to other platforms, support for them may be less +// stable. If you notice any problems on your platform, please notify +// googletestframework@googlegroups.com (patches for fixing them are +// even more welcome!). +// +// Note that it is possible that none of the GTEST_OS_* macros are defined. +// +// 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 +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with +// GTEST_HAS_POSIX_RE (see above) which users can +// define themselves. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// +// Macros for basic C++ coding: +// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. +// +// Synchronization: +// Mutex, MutexLock, ThreadLocal, GetThreadCount() +// - 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: +// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. +// IteratorTraits - partial implementation of std::iterator_traits, which +// is not available in libCstd when compiled with Sun C++. +// +// Smart pointers: +// scoped_ptr - as in TR2. +// +// Regular expressions: +// RE - a simple regular expression class using the POSIX +// Extended Regular Expression syntax on UNIX-like +// platforms, or a reduced regular exception syntax on +// other platforms, including Windows. +// +// Logging: +// GTEST_LOG_() - logs messages at the specified severity level. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. +// +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. +// CaptureStderr() - starts capturing stderr. +// GetCapturedStderr() - stops capturing stderr and returns the captured +// string. +// +// Integer types: +// TypeWithSize - maps an integer to a int type. +// Int32, UInt32, Int64, UInt64, TimeInMillis +// - integers of known sizes. +// BiggestInt - the biggest signed integer type. +// +// Command-line utilities: +// GTEST_FLAG() - references a flag. +// GTEST_DECLARE_*() - declares a flag. +// GTEST_DEFINE_*() - defines a flag. +// GetInjectableArgvs() - returns the command line as a vector of strings. +// +// Environment variable utilities: +// GetEnv() - gets the value of an environment variable. +// BoolFromGTestEnv() - parses a bool environment variable. +// Int32FromGTestEnv() - parses an Int32 environment variable. +// StringFromGTestEnv() - parses a string environment variable. + +#include // for isspace, etc +#include // for ptrdiff_t +#include +#include +#include +#ifndef _WIN32_WCE +# include +# include +#endif // !_WIN32_WCE + +#if defined __APPLE__ +# include +# include +#endif + +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" + +// Determines the version of gcc that is used to compile this. +#ifdef __GNUC__ +// 40302 means version 4.3.2. +# define GTEST_GCC_VER_ \ + (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + +// Determines the platform on which Google Test is compiled. +#ifdef __CYGWIN__ +# define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +# define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +# define GTEST_OS_WINDOWS 1 +# ifdef _WIN32_WCE +# define GTEST_OS_WINDOWS_MOBILE 1 +# elif defined(__MINGW__) || defined(__MINGW32__) +# define GTEST_OS_WINDOWS_MINGW 1 +# else +# define GTEST_OS_WINDOWS_DESKTOP 1 +# endif // _WIN32_WCE +#elif defined __APPLE__ +# define GTEST_OS_MAC 1 +# if TARGET_OS_IPHONE +# define GTEST_OS_IOS 1 +# if TARGET_IPHONE_SIMULATOR +# define GTEST_OS_IOS_SIMULATOR 1 +# endif +# endif +#elif defined __linux__ +# define GTEST_OS_LINUX 1 +# if defined __ANDROID__ +# define GTEST_OS_LINUX_ANDROID 1 +# endif +#elif defined __MVS__ +# define GTEST_OS_ZOS 1 +#elif defined(__sun) && defined(__SVR4) +# define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +# define GTEST_OS_AIX 1 +#elif defined(__hpux) +# define GTEST_OS_HPUX 1 +#elif defined __native_client__ +# define GTEST_OS_NACL 1 +#elif defined __OpenBSD__ +# define GTEST_OS_OPENBSD 1 +#elif defined __QNX__ +# define GTEST_OS_QNX 1 +#endif // __CYGWIN__ + +#ifndef GTEST_LANG_CXX11 +// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when +// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a +// value for __cplusplus, and recent versions of clang, gcc, and +// probably other compilers set that too in C++11 mode. +# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L +// Compiling in at least C++11 mode. +# define GTEST_LANG_CXX11 1 +# else +# define GTEST_LANG_CXX11 0 +# endif +#endif + +// Brings in definitions for functions used in the testing::internal::posix +// namespace (read, write, close, chdir, isatty, stat). We do not currently +// use them on Windows Mobile. +#if !GTEST_OS_WINDOWS +// 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 +// mentioned above. +# include +# include +#elif !GTEST_OS_WINDOWS_MOBILE +# include +# include +#endif + +#if GTEST_OS_LINUX_ANDROID +// Used to define __ANDROID_API__ matching the target NDK API level. +# include // NOLINT +#endif + +// Defines this to true iff Google Test can use POSIX regular expressions. +#ifndef GTEST_HAS_POSIX_RE +# if GTEST_OS_LINUX_ANDROID +// On Android, is only available starting with Gingerbread. +# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) +# else +# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +# endif +#endif + +#if GTEST_HAS_POSIX_RE + +// On some platforms, needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included , which is guaranteed to define size_t through +// . +# include // NOLINT + +# define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +// is not available on Windows. Use our own simple regex +// implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#else + +// may not be available on this platform. Use our own +// simple regex implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_HAS_POSIX_RE + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +# if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. +// Assumes that exceptions are enabled by default. +# ifndef _HAS_EXCEPTIONS +# define _HAS_EXCEPTIONS 1 +# endif // _HAS_EXCEPTIONS +# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS +# elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__HP_aCC) +// Exception handling is in effect by default in HP aCC compiler. It has to +// be turned of by +noeh compiler option if desired. +# define GTEST_HAS_EXCEPTIONS 1 +# else +// For other compilers, we assume exceptions are disabled to be +// conservative. +# define GTEST_HAS_EXCEPTIONS 0 +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS + +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +# define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +# error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) + +#ifndef GTEST_HAS_GLOBAL_STRING +// The user didn't tell us whether ::string is available, so we need +// to figure it out. + +# define GTEST_HAS_GLOBAL_STRING 0 + +#endif // GTEST_HAS_GLOBAL_STRING + +#ifndef GTEST_HAS_STD_WSTRING +// The user didn't tell us whether ::std::wstring is available, so we need +// to figure it out. +// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring +// is available. + +// Cygwin 1.7 and below doesn't support ::std::wstring. +// Solaris' libc++ doesn't support it either. Android has +// no support for it at least as recent as Froyo (2.2). +# define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) + +#endif // GTEST_HAS_STD_WSTRING + +#ifndef GTEST_HAS_GLOBAL_WSTRING +// The user didn't tell us whether ::wstring is available, so we need +// to figure it out. +# define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Determines whether RTTI is available. +#ifndef GTEST_HAS_RTTI +// The user didn't tell us whether RTTI is enabled, so we need to +// figure it out. + +# ifdef _MSC_VER + +# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + +# ifdef __GXX_RTTI +// When building against STLport with the Android NDK and with +// -frtti -fno-exceptions, the build fails at link time with undefined +// references to __cxa_bad_typeid. Note sure if STL or toolchain bug, +// so disable RTTI when detected. +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \ + !defined(__EXCEPTIONS) +# define GTEST_HAS_RTTI 0 +# else +# define GTEST_HAS_RTTI 1 +# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS +# else +# define GTEST_HAS_RTTI 0 +# endif // __GXX_RTTI + +// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends +// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the +// first version with C++ support. +# elif defined(__clang__) + +# define GTEST_HAS_RTTI __has_feature(cxx_rtti) + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +# ifdef __RTTI_ALL__ +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +# else + +// For all other compilers, we assume RTTI is enabled. +# define GTEST_HAS_RTTI 1 + +# endif // _MSC_VER + +#endif // GTEST_HAS_RTTI + +// It's this header's responsibility to #include when RTTI +// is enabled. +#if GTEST_HAS_RTTI +# include +#endif + +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \ + || GTEST_OS_QNX) +#endif // GTEST_HAS_PTHREAD + +#if GTEST_HAS_PTHREAD +// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is +// true. +# include // NOLINT + +// For timespec and nanosleep, used below. +# include // NOLINT +#endif + +// Determines whether Google Test can use tr1/tuple. You can define +// this macro to 0 to prevent Google Test from using tuple (any +// feature depending on tuple with be disabled in this mode). +#ifndef GTEST_HAS_TR1_TUPLE +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) +// STLport, provided with the Android NDK, has neither or . +# define GTEST_HAS_TR1_TUPLE 0 +# else +// The user didn't tell us not to do it, so we assume it's OK. +# define GTEST_HAS_TR1_TUPLE 1 +# endif +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether Google Test's own tr1 tuple implementation +// should be used. +#ifndef GTEST_USE_OWN_TR1_TUPLE +// The user didn't tell us, so we need to figure it out. + +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, libstdc++ 4.0.0+ and +// MSVC 2010 are the only mainstream standard libraries that come +// with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler +// pretends to be GCC by defining __GNUC__ and friends, but cannot +// compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1 +// tuple in a 323 MB Feature Pack download, which we cannot assume the +// user has. QNX's QCC compiler is a modified GCC but it doesn't +// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, +// and it can be used with some compilers that define __GNUC__. +# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ + && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600 +# define GTEST_ENV_HAS_TR1_TUPLE_ 1 +# endif + +// C++11 specifies that provides std::tuple. 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_ENV_HAS_STD_TUPLE_ 1 +# endif + +# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_ +# define GTEST_USE_OWN_TR1_TUPLE 0 +# else +# define GTEST_USE_OWN_TR1_TUPLE 1 +# endif + +#endif // GTEST_USE_OWN_TR1_TUPLE + +// To avoid conditional compilation everywhere, we make it +// gtest-port.h's responsibility to #include the header implementing +// tr1/tuple. +#if GTEST_HAS_TR1_TUPLE + +# if GTEST_USE_OWN_TR1_TUPLE +// This file was GENERATED by command: +// pump.py gtest-tuple.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2009 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 a subset of TR1 tuple needed by Google Test and Google Mock. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple +#define GTEST_2_TUPLE_(T) tuple +#define GTEST_3_TUPLE_(T) tuple +#define GTEST_4_TUPLE_(T) tuple +#define GTEST_5_TUPLE_(T) tuple +#define GTEST_6_TUPLE_(T) tuple +#define GTEST_7_TUPLE_(T) tuple +#define GTEST_8_TUPLE_(T) tuple +#define GTEST_9_TUPLE_(T) tuple +#define GTEST_10_TUPLE_(T) tuple + +// GTEST_n_TYPENAMES_(T) declares a list of n typenames. +#define GTEST_0_TYPENAMES_(T) +#define GTEST_1_TYPENAMES_(T) typename T##0 +#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 +#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 +#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3 +#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4 +#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5 +#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6 +#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 +#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8 +#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ + typename T##3, typename T##4, typename T##5, typename T##6, \ + typename T##7, typename T##8, typename T##9 + +// In theory, defining stuff in the ::std namespace is undefined +// behavior. We can do this as we are playing the role of a standard +// library vendor. +namespace std { +namespace tr1 { + +template +class tuple; + +// Anything in namespace gtest_internal is Google Test's INTERNAL +// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. +namespace gtest_internal { + +// ByRef::type is T if T is a reference; otherwise it's const T&. +template +struct ByRef { typedef const T& type; }; // NOLINT +template +struct ByRef { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type + +// AddRef::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference::type. +template +struct AddRef { typedef T& type; }; // NOLINT +template +struct AddRef { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type + +// A helper for implementing get(). +template class Get; + +// A helper for implementing tuple_element. kIndexValid is true +// iff k < the number of fields in tuple type T. +template +struct TupleElement; + +template +struct TupleElement { + typedef T0 type; +}; + +template +struct TupleElement { + typedef T1 type; +}; + +template +struct TupleElement { + typedef T2 type; +}; + +template +struct TupleElement { + typedef T3 type; +}; + +template +struct TupleElement { + typedef T4 type; +}; + +template +struct TupleElement { + typedef T5 type; +}; + +template +struct TupleElement { + typedef T6 type; +}; + +template +struct TupleElement { + typedef T7 type; +}; + +template +struct TupleElement { + typedef T8 type; +}; + +template +struct TupleElement { + typedef T9 type; +}; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template +class GTEST_1_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template +class GTEST_2_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), + f1_(f1) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} + + template + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template + tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template + tuple& operator=(const ::std::pair& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template +class GTEST_3_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + template + tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; +}; + +template +class GTEST_4_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} + + template + tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; +}; + +template +class GTEST_5_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, + GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_) {} + + template + tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; +}; + +template +class GTEST_6_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_) {} + + template + tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; +}; + +template +class GTEST_7_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + template + tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; +}; + +template +class GTEST_8_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, + GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + template + tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; +}; + +template +class GTEST_9_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), + f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + template + tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; +}; + +template +class tuple { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, + GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, + GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, + GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), + f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} + + tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), + f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} + + template + tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), + f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), + f9_(t.f9_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + f2_ = t.f2_; + f3_ = t.f3_; + f4_ = t.f4_; + f5_ = t.f5_; + f6_ = t.f6_; + f7_ = t.f7_; + f8_ = t.f8_; + f9_ = t.f9_; + return *this; + } + + T0 f0_; + T1 f1_; + T2 f2_; + T3 f3_; + T4 f4_; + T5 f5_; + T6 f6_; + T7 f7_; + T8 f8_; + T9 f9_; +}; + +// 6.1.3.2 Tuple creation functions. + +// Known limitations: we don't support passing an +// std::tr1::reference_wrapper to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template +inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { + return GTEST_3_TUPLE_(T)(f0, f1, f2); +} + +template +inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3) { + return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); +} + +template +inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4) { + return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); +} + +template +inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5) { + return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); +} + +template +inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6) { + return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); +} + +template +inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { + return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); +} + +template +inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8) { + return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); +} + +template +inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, + const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, + const T8& f8, const T9& f9) { + return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); +} + +// 6.1.3.3 Tuple helper classes. + +template struct tuple_size; + +template +struct tuple_size { + static const int value = 0; +}; + +template +struct tuple_size { + static const int value = 1; +}; + +template +struct tuple_size { + static const int value = 2; +}; + +template +struct tuple_size { + static const int value = 3; +}; + +template +struct tuple_size { + static const int value = 4; +}; + +template +struct tuple_size { + static const int value = 5; +}; + +template +struct tuple_size { + static const int value = 6; +}; + +template +struct tuple_size { + static const int value = 7; +}; + +template +struct tuple_size { + static const int value = 8; +}; + +template +struct tuple_size { + static const int value = 9; +}; + +template +struct tuple_size { + static const int value = 10; +}; + +template +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::Field(t); +} + +template +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::ConstField(t); +} + +// 6.1.3.5 Relational operators + +// We only implement == and !=, as we don't have a need for the rest yet. + +namespace gtest_internal { + +// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the +// first k fields of t1 equals the first k fields of t2. +// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if +// k1 != k2. +template +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template +struct SameSizeTuplePrefixComparator { + template + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator::Eq(t1, t2) && + ::std::tr1::get(t1) == ::std::tr1::get(t2); + } +}; + +} // namespace gtest_internal + +template +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size::value, + tuple_size::value>::Eq(t, u); +} + +template +inline bool operator!=(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { return !(t == u); } + +// 6.1.4 Pairs. +// Unimplemented. + +} // namespace tr1 +} // namespace std + +#undef GTEST_0_TUPLE_ +#undef GTEST_1_TUPLE_ +#undef GTEST_2_TUPLE_ +#undef GTEST_3_TUPLE_ +#undef GTEST_4_TUPLE_ +#undef GTEST_5_TUPLE_ +#undef GTEST_6_TUPLE_ +#undef GTEST_7_TUPLE_ +#undef GTEST_8_TUPLE_ +#undef GTEST_9_TUPLE_ +#undef GTEST_10_TUPLE_ + +#undef GTEST_0_TYPENAMES_ +#undef GTEST_1_TYPENAMES_ +#undef GTEST_2_TYPENAMES_ +#undef GTEST_3_TYPENAMES_ +#undef GTEST_4_TYPENAMES_ +#undef GTEST_5_TYPENAMES_ +#undef GTEST_6_TYPENAMES_ +#undef GTEST_7_TYPENAMES_ +#undef GTEST_8_TYPENAMES_ +#undef GTEST_9_TYPENAMES_ +#undef GTEST_10_TYPENAMES_ + +#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +# elif GTEST_ENV_HAS_STD_TUPLE_ +# include +// C++11 puts its tuple into the ::std namespace rather than +// ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there. +// This causes undefined behavior, but supported compilers react in +// the way we intend. +namespace std { +namespace tr1 { +using ::std::get; +using ::std::make_tuple; +using ::std::tuple; +using ::std::tuple_element; +using ::std::tuple_size; +} +} + +# elif GTEST_OS_SYMBIAN + +// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to +// use STLport's tuple implementation, which unfortunately doesn't +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +# ifdef BOOST_HAS_TR1_TUPLE +# undef BOOST_HAS_TR1_TUPLE +# endif // BOOST_HAS_TR1_TUPLE + +// This prevents , which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . +# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +# include + +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the header. This does +// not conform to the TR1 spec, which requires the header to be . + +# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes , +// which is #included by , to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// . Hence the following #define is a hack to prevent +// from being included. +# define _TR1_FUNCTIONAL 1 +# include +# undef _TR1_FUNCTIONAL // Allows the user to #include + // if he chooses to. +# else +# include // NOLINT +# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +# else +// If the compiler is not GCC 4.0+, we assume the user is using a +// spec-conforming TR1 implementation. +# include // NOLINT +# endif // GTEST_USE_OWN_TR1_TUPLE + +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether clone(2) is supported. +// Usually it will only be available on Linux, excluding +// Linux on the Itanium architecture. +// Also see http://linux.die.net/man/2/clone. +#ifndef GTEST_HAS_CLONE +// The user didn't tell us, so we need to figure it out. + +# if GTEST_OS_LINUX && !defined(__ia64__) +# if GTEST_OS_LINUX_ANDROID +// On Android, clone() is only available on ARM starting with Gingerbread. +# if defined(__arm__) && __ANDROID_API__ >= 9 +# define GTEST_HAS_CLONE 1 +# else +# define GTEST_HAS_CLONE 0 +# endif +# else +# define GTEST_HAS_CLONE 1 +# endif +# else +# define GTEST_HAS_CLONE 0 +# endif // GTEST_OS_LINUX && !defined(__ia64__) + +#endif // GTEST_HAS_CLONE + +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#ifndef GTEST_HAS_STREAM_REDIRECTION +// By default, we assume that stream redirection is supported on all +// platforms except known mobile ones. +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN +# define GTEST_HAS_STREAM_REDIRECTION 0 +# else +# define GTEST_HAS_STREAM_REDIRECTION 1 +# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ + GTEST_OS_OPENBSD || GTEST_OS_QNX) +# define GTEST_HAS_DEATH_TEST 1 +# include // NOLINT +#endif + +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 + +// Determines whether to support type-driven tests. + +// Typed tests need and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, IBM Visual Age, and HP aCC support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) || defined(__HP_aCC) +# define GTEST_HAS_TYPED_TEST 1 +# define GTEST_HAS_TYPED_TEST_P 1 +#endif + +// Determines whether to support Combine(). This only makes sense when +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +# define GTEST_HAS_COMBINE 1 +#endif + +// Determines whether the system compiler uses UTF-16 for encoding wide strings. +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + +// Determines whether test results can be streamed to a socket. +#if GTEST_OS_LINUX +# define GTEST_CAN_STREAM_RESULTS_ 1 +#endif + +// Defines some utility macros. + +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#ifdef __INTEL_COMPILER +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ +#else +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT +#endif + +// Use this annotation at the end of a struct/class definition to +// prevent the compiler from optimizing away instances that are never +// used. This is useful when all interesting logic happens inside the +// c'tor and / or d'tor. Example: +// +// struct Foo { +// Foo() { ... } +// } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. +#if defined(__GNUC__) && !defined(COMPILER_ICC) +# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) +#else +# define GTEST_ATTRIBUTE_UNUSED_ +#endif + +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; +#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) +#else +# define GTEST_MUST_USE_RESULT_ +#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC + +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +# if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +# define GTEST_HAS_SEH 1 +# else +// Assume no SEH. +# define GTEST_HAS_SEH 0 +# endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +# if GTEST_LINKED_AS_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllimport) +# elif GTEST_CREATE_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllexport) +# endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +# define GTEST_API_ +#endif + +#ifdef __GNUC__ +// Ask the compiler to never inline a given function. +# define GTEST_NO_INLINE_ __attribute__((noinline)) +#else +# define GTEST_NO_INLINE_ +#endif + +// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. +#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) +# define GTEST_HAS_CXXABI_H_ 1 +#else +# define GTEST_HAS_CXXABI_H_ 0 +#endif + +namespace testing { + +class Message; + +namespace internal { + +// A secret type that Google Test users don't know about. It has no +// definition on purpose. Therefore it's impossible to create a +// Secret object, which is what we want. +class Secret; + +// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template +struct CompileAssert { +}; + +#define GTEST_COMPILE_ASSERT_(expr, msg) \ + typedef ::testing::internal::CompileAssert<(static_cast(expr))> \ + msg[static_cast(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_ + +// Implementation details of GTEST_COMPILE_ASSERT_: +// +// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// GTEST_COMPILE_ASSERT_(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. +// +// This template is declared, but intentionally undefined. +template +struct StaticAssertTypeEqHelper; + +template +struct StaticAssertTypeEqHelper {}; + +#if GTEST_HAS_GLOBAL_STRING +typedef ::string string; +#else +typedef ::std::string string; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_GLOBAL_WSTRING +typedef ::wstring wstring; +#elif GTEST_HAS_STD_WSTRING +typedef ::std::wstring wstring; +#endif // GTEST_HAS_GLOBAL_WSTRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); + +// Defines scoped_ptr. + +// This implementation of scoped_ptr is PARTIAL - it only contains +// enough stuff to satisfy Google Test's need. +template +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} + ~scoped_ptr() { reset(); } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + T* get() const { return ptr_; } + + T* release() { + T* const ptr = ptr_; + ptr_ = NULL; + return ptr; + } + + void reset(T* p = NULL) { + if (p != ptr_) { + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. + delete ptr_; + } + ptr_ = p; + } + } + + private: + T* ptr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); +}; + +// Defines RE. + +// A simple C++ wrapper for . It uses the POSIX Extended +// Regular Expression syntax. +class GTEST_API_ RE { + public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + + // Constructs an RE from a string. + RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + + RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT + +#endif // GTEST_HAS_GLOBAL_STRING + + RE(const char* regex) { Init(regex); } // NOLINT + ~RE(); + + // Returns the string representation of the regex. + const char* pattern() const { return pattern_; } + + // FullMatch(str, re) returns true iff regular expression re matches + // the entire str. + // PartialMatch(str, re) returns true iff regular expression re + // matches a substring of str (including str itself). + // + // TODO(wan@google.com): make FullMatch() and PartialMatch() work + // when str contains NUL characters. + static bool FullMatch(const ::std::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::std::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#if GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const ::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#endif // GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const char* str, const RE& re); + static bool PartialMatch(const char* str, const RE& re); + + private: + void Init(const char* regex); + + // We use a const char* instead of an std::string, as Google Test used to be + // used where std::string is not available. TODO(wan@google.com): change to + // std::string. + const char* pattern_; + bool is_valid_; + +#if GTEST_USES_POSIX_RE + + regex_t full_regex_; // For FullMatch(). + regex_t partial_regex_; // For PartialMatch(). + +#else // GTEST_USES_SIMPLE_RE + + const char* full_pattern_; // For FullMatch(); + +#endif + + GTEST_DISALLOW_ASSIGN_(RE); +}; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, + int line); + +// Defines logging utilities: +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. + +enum GTestLogSeverity { + GTEST_INFO, + GTEST_WARNING, + GTEST_ERROR, + GTEST_FATAL +}; + +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); + + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() + +inline void LogToStderr() {} +inline void FlushInfoLog() { fflush(NULL); } + +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Use ImplicitCast_ as a safe version of static_cast for upcasting in +// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a +// const Foo*). When you use ImplicitCast_, the compiler checks that +// the cast is safe. Such explicit ImplicitCast_s are necessary in +// surprisingly many situations where C++ demands an exact type match +// instead of an argument type convertable to a target type. +// +// The syntax for using ImplicitCast_ is the same as for static_cast: +// +// ImplicitCast_(expr) +// +// ImplicitCast_ would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., implicit_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template +inline To ImplicitCast_(To x) { return x; } + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., down_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template // use like this: DownCast_(foo); +inline To DownCast_(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + const To to = NULL; + ::testing::internal::ImplicitCast_(to); + } + +#if GTEST_HAS_RTTI + // RTTI: debug mode only! + GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast(base); // NOLINT +#else + return static_cast(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION + +// Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. +// CaptureStderr - starts capturing stderr. +// GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ std::string GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ std::string GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION + + +#if GTEST_HAS_DEATH_TEST + +const ::std::vector& GetInjectableArgvs(); +void SetInjectableArgvs(const ::std::vector* + new_argvs); + +// A copy of all command line arguments. Set by InitGoogleTest(). +extern ::std::vector g_argvs; + +#endif // GTEST_HAS_DEATH_TEST + +// Defines synchronization primitives. + +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// 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 Notification { + public: + Notification() : notified_(false) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + } + ~Notification() { + pthread_mutex_destroy(&mutex_); + } + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { + pthread_mutex_lock(&mutex_); + notified_ = true; + pthread_mutex_unlock(&mutex_); + } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + for (;;) { + pthread_mutex_lock(&mutex_); + const bool notified = notified_; + pthread_mutex_unlock(&mutex_); + if (notified) + break; + SleepMilliseconds(10); + } + } + + private: + pthread_mutex_t mutex_; + bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // 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: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + has_owner_ = true; + } + + // Releases this mutex. + void Unlock() { + // Since the lock is being released the owner_ field should no longer be + // considered valid. We don't protect writing to has_owner_ here, as it's + // the caller's responsibility to ensure that the current thread holds the + // mutex when this is called. + has_owner_ = false; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self())) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + // has_owner_ indicates whether the owner_ field below contains a valid thread + // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All + // accesses to the owner_ field should be protected by a check of this field. + // An alternative might be to memset() owner_ to all zeros, but there's no + // guarantee that a zero'd pthread_t is necessarily invalid or even different + // from pthread_self(). + bool has_owner_; + pthread_t owner_; // The thread holding the mutex. +}; + +// Forward-declares a static mutex. +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +// The initialization list here does not explicitly initialize each field, +// instead relying on default initialization for the unspecified fields. In +// particular, the owner_ field (a pthread_t) is not explicitly initialized. +// 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. +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + has_owner_ = false; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal 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 +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + 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 type 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); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +# define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + +// A dummy implementation of synchronization primitives (mutex, lock, +// and thread-local variable). Necessary for compiling Google Test where +// mutex is not supported - using Google Test in multiple threads is not +// supported on such platforms. + +class Mutex { + public: + Mutex() {} + void Lock() {} + void Unlock() {} + void AssertHeld() const {} +}; + +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + +class GTestMutexLock { + public: + explicit GTestMutexLock(Mutex*) {} // NOLINT +}; + +typedef GTestMutexLock MutexLock; + +template +class ThreadLocal { + public: + ThreadLocal() : value_() {} + explicit ThreadLocal(const T& value) : value_(value) {} + T* pointer() { return &value_; } + const T* pointer() const { return &value_; } + const T& get() const { return value_; } + void set(const T& value) { value_ = value; } + private: + T value_; +}; + +// 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 +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); + +// Passing non-POD classes through ellipsis (...) crashes the ARM +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +# define GTEST_CAN_COMPARE_NULL 1 +#endif + +// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between +// const T& and const T* in a function template. These compilers +// _can_ decide between class template specializations for T and T*, +// so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +# define GTEST_NEEDS_IS_POINTER_ 1 +#endif + +template +struct bool_constant { + typedef bool_constant type; + static const bool value = bool_value; +}; +template const bool bool_constant::value; + +typedef bool_constant false_type; +typedef bool_constant true_type; + +template +struct is_pointer : public false_type {}; + +template +struct is_pointer : public true_type {}; + +template +struct IteratorTraits { + typedef typename Iterator::value_type value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_SEP_ "\\" +# define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. +typedef __int64 BiggestInt; +#else +# define GTEST_PATH_SEP_ "/" +# define GTEST_HAS_ALT_PATH_SEP_ 0 +typedef long long BiggestInt; // NOLINT +#endif // GTEST_OS_WINDOWS + +// Utilities for char. + +// isspace(int ch) and friends accept an unsigned char or EOF. char +// may be signed, depending on the compiler (or compiler flags). +// Therefore we need to cast a char to unsigned char before calling +// isspace(), etc. + +inline bool IsAlpha(char ch) { + return isalpha(static_cast(ch)) != 0; +} +inline bool IsAlNum(char ch) { + return isalnum(static_cast(ch)) != 0; +} +inline bool IsDigit(char ch) { + return isdigit(static_cast(ch)) != 0; +} +inline bool IsLower(char ch) { + return islower(static_cast(ch)) != 0; +} +inline bool IsSpace(char ch) { + return isspace(static_cast(ch)) != 0; +} +inline bool IsUpper(char ch) { + return isupper(static_cast(ch)) != 0; +} +inline bool IsXDigit(char ch) { + return isxdigit(static_cast(ch)) != 0; +} +inline bool IsXDigit(wchar_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} + +inline char ToLower(char ch) { + return static_cast(tolower(static_cast(ch))); +} +inline char ToUpper(char ch) { + return static_cast(toupper(static_cast(ch))); +} + +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +# ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +# else // !__BORLANDC__ +# if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +# else +inline int IsATTY(int fd) { return _isatty(fd); } +# endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +# endif // __BORLANDC__ + +# if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +# else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +# endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#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) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + +// MSVC "deprecates" snprintf and issues warnings wherever it is used. In +// order to avoid these warnings, we need to use _snprintf or _snprintf_s on +// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate +// function in order to achieve that. We use macro definition here because +// snprintf is a variadic function. +#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE +// MSVC 2005 and above support variadic macros. +# define GTEST_SNPRINTF_(buffer, size, format, ...) \ + _snprintf_s(buffer, size, size, format, __VA_ARGS__) +#elif defined(_MSC_VER) +// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't +// complain about _snprintf. +# define GTEST_SNPRINTF_ _snprintf +#else +# define GTEST_SNPRINTF_ snprintf +#endif + +// The maximum number a BiggestInt can represent. This definition +// works no matter BiggestInt is represented in one's complement or +// two's complement. +// +// We cannot rely on numeric_limits in STL, as __int64 and long long +// are not part of standard C++ and numeric_limits doesn't need to be +// defined for them. +const BiggestInt kMaxBiggestInt = + ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); + +// This template class serves as a compile-time function from size to +// type. It maps a size in bytes to a primitive type with that +// size. e.g. +// +// TypeWithSize<4>::UInt +// +// is typedef-ed to be unsigned int (unsigned integer made up of 4 +// bytes). +// +// Such functionality should belong to STL, but I cannot find it +// there. +// +// Google Test uses this class in the implementation of floating-point +// comparison. +// +// For now it only handles UInt (unsigned int) as that's all Google Test +// needs. Other types can be easily added in the future if need +// arises. +template +class TypeWithSize { + public: + // This prevents the user from using TypeWithSize with incorrect + // values of N. + typedef void UInt; +}; + +// The specialization for size 4. +template <> +class TypeWithSize<4> { + public: + // unsigned int has size 4 in both gcc and MSVC. + // + // As base/basictypes.h doesn't compile on Windows, we cannot use + // uint32, uint64, and etc here. + typedef int Int; + typedef unsigned int UInt; +}; + +// The specialization for size 8. +template <> +class TypeWithSize<8> { + public: +#if GTEST_OS_WINDOWS + typedef __int64 Int; + typedef unsigned __int64 UInt; +#else + typedef long long Int; // NOLINT + typedef unsigned long long UInt; // NOLINT +#endif // GTEST_OS_WINDOWS +}; + +// Integer types of known sizes. +typedef TypeWithSize<4>::Int Int32; +typedef TypeWithSize<4>::UInt UInt32; +typedef TypeWithSize<8>::Int Int64; +typedef TypeWithSize<8>::UInt UInt64; +typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. + +// Utilities for command line flags and environment variables. + +// Macro for referencing flags. +#define GTEST_FLAG(name) FLAGS_gtest_##name + +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_int32_(name) \ + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) +#define GTEST_DECLARE_string_(name) \ + GTEST_API_ extern ::std::string GTEST_FLAG(name) + +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + GTEST_API_ bool GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) + +// Thread annotations +#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) +#define GTEST_LOCK_EXCLUDED_(locks) + +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +// TODO(chandlerc): Find a better way to refactor flag and environment parsing +// out of both gtest-port.cc and gtest.cc to avoid exporting this utility +// function. +bool ParseInt32(const Message& src_text, const char* str, Int32* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromGTestEnv(const char* flag, bool default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +const char* StringFromGTestEnv(const char* flag, const char* default_val); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +#if GTEST_OS_LINUX +# include +# include +# include +# include +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#include +#include +#include +#include +#include +#include + +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the Message class. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ + +#include + + +// Ensures that there is at least one operator<< in the global namespace. +// See Message& operator<<(...) below for why. +void operator<<(const testing::internal::Secret&, int); + +namespace testing { + +// The Message class works like an ostream repeater. +// +// Typical usage: +// +// 1. You stream a bunch of values to a Message object. +// It will remember the text in a stringstream. +// 2. Then you stream the Message object to an ostream. +// This causes the text in the Message to be streamed +// to the ostream. +// +// For example; +// +// testing::Message foo; +// foo << 1 << " != " << 2; +// std::cout << foo; +// +// will print "1 != 2". +// +// Message is not intended to be inherited from. In particular, its +// destructor is not virtual. +// +// Note that stringstream behaves differently in gcc and in MSVC. You +// can stream a NULL char pointer to it in the former, but not in the +// latter (it causes an access violation if you do). The Message +// class hides this difference by treating a NULL char pointer as +// "(null)". +class GTEST_API_ Message { + private: + // The type of basic IO manipulators (endl, ends, and flush) for + // narrow streams. + typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); + + public: + // Constructs an empty Message. + Message(); + + // Copy constructor. + Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT + *ss_ << msg.GetString(); + } + + // Constructs a Message from a C-string. + explicit Message(const char* str) : ss_(new ::std::stringstream) { + *ss_ << str; + } + +#if GTEST_OS_SYMBIAN + // Streams a value (either a pointer or not) to this object. + template + inline Message& operator <<(const T& value) { + StreamHelper(typename internal::is_pointer::type(), value); + return *this; + } +#else + // Streams a non-pointer value to this object. + template + inline Message& operator <<(const T& val) { + // Some libraries overload << for STL containers. These + // overloads are defined in the global namespace instead of ::std. + // + // C++'s symbol lookup rule (i.e. Koenig lookup) says that these + // overloads are visible in either the std namespace or the global + // namespace, but not other namespaces, including the testing + // namespace which Google Test's Message class is in. + // + // To allow STL containers (and other types that has a << operator + // defined in the global namespace) to be used in Google Test + // assertions, testing::Message must access the custom << operator + // from the global namespace. With this using declaration, + // overloads of << defined in the global namespace and those + // visible via Koenig lookup are both exposed in this function. + using ::operator <<; + *ss_ << val; + return *this; + } + + // Streams a pointer value to this object. + // + // This function is an overload of the previous one. When you + // stream a pointer to a Message, this definition will be used as it + // is more specialized. (The C++ Standard, section + // [temp.func.order].) If you stream a non-pointer, then the + // previous definition will be used. + // + // The reason for this overload is that streaming a NULL pointer to + // ostream is undefined behavior. Depending on the compiler, you + // may get "0", "(nil)", "(null)", or an access violation. To + // ensure consistent result across compilers, we always treat NULL + // as "(null)". + template + inline Message& operator <<(T* const& pointer) { // NOLINT + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + return *this; + } +#endif // GTEST_OS_SYMBIAN + + // Since the basic IO manipulators are overloaded for both narrow + // and wide streams, we have to provide this specialized definition + // of operator <<, even though its body is the same as the + // templatized version above. Without this definition, streaming + // endl or other basic IO manipulators to Message will confuse the + // compiler. + Message& operator <<(BasicNarrowIoManip val) { + *ss_ << val; + return *this; + } + + // Instead of 1/0, we want to see true/false for bool values. + Message& operator <<(bool b) { + return *this << (b ? "true" : "false"); + } + + // These two overloads allow streaming a wide C string to a Message + // using the UTF-8 encoding. + Message& operator <<(const wchar_t* wide_c_str); + Message& operator <<(wchar_t* wide_c_str); + +#if GTEST_HAS_STD_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::std::wstring& wstr); +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::wstring& wstr); +#endif // GTEST_HAS_GLOBAL_WSTRING + + // Gets the text streamed to this object so far as an std::string. + // Each '\0' character in the buffer is replaced with "\\0". + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + std::string GetString() const; + + private: + +#if GTEST_OS_SYMBIAN + // These are needed as the Nokia Symbian Compiler cannot decide between + // const T& and const T* in a function template. The Nokia compiler _can_ + // decide between class template specializations for T and T*, so a + // tr1::type_traits-like is_pointer works, and we can overload on that. + template + inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + } + template + inline void StreamHelper(internal::false_type /*is_pointer*/, + const T& value) { + // See the comments in Message& operator <<(const T&) above for why + // we need this using statement. + using ::operator <<; + *ss_ << value; + } +#endif // GTEST_OS_SYMBIAN + + // We'll hold the text streamed to this object here. + const internal::scoped_ptr< ::std::stringstream> ss_; + + // We declare (but don't implement) this to prevent the compiler + // from implementing the assignment operator. + void operator=(const Message&); +}; + +// Streams a Message to an ostream. +inline std::ostream& operator <<(std::ostream& os, const Message& sb) { + return os << sb.GetString(); +} + +namespace internal { + +// Converts a streamable value to an std::string. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +template +std::string StreamableToString(const T& streamable) { + return (Message() << streamable).GetString(); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares the String class and functions used internally by +// Google Test. They are subject to change without notice. They should not used +// by code external to Google Test. +// +// This header file is #included by . +// It should not be #included by other files. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ + +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +# include +#endif + +#include +#include + + +namespace testing { +namespace internal { + +// String - an abstract class holding static string utilities. +class GTEST_API_ String { + public: + // Static utility methods + + // Clones a 0-terminated C string, allocating memory using new. The + // caller is responsible for deleting the return value using + // delete[]. Returns the cloned string, or NULL if the input is + // NULL. + // + // This is different from strdup() in string.h, which allocates + // memory using malloc(). + static const char* CloneCString(const char* c_str); + +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be + // able to pass strings to Win32 APIs on CE we need to convert them + // to 'Unicode', UTF-16. + + // Creates a UTF-16 wide string from the given ANSI string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the wide string, or NULL if the + // input is NULL. + // + // The wide string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static LPCWSTR AnsiToUtf16(const char* c_str); + + // Creates an ANSI string from the given wide string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the ANSI string, or NULL if the + // input is NULL. + // + // The returned string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static const char* Utf16ToAnsi(LPCWSTR utf16_str); +#endif + + // Compares two C strings. Returns true iff they have the same content. + // + // Unlike strcmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CStringEquals(const char* lhs, const char* rhs); + + // Converts a wide C string to a String using the UTF-8 encoding. + // NULL will be converted to "(null)". If an error occurred during + // the conversion, "(failed to convert from wide string)" is + // returned. + static std::string ShowWideCString(const wchar_t* wide_c_str); + + // Compares two wide C strings. Returns true iff they have the same + // content. + // + // Unlike wcscmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); + + // Compares two C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike strcasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CaseInsensitiveCStringEquals(const char* lhs, + const char* rhs); + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. + static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs); + + // Returns true iff the given string ends with the given suffix, ignoring + // case. Any string is considered to end with an empty suffix. + static bool EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix); + + // Formats an int value as "%02d". + static std::string FormatIntWidth2(int value); // "%02d" for width == 2 + + // Formats an int value as "%X". + static std::string FormatHexInt(int value); + + // Formats a byte as "%02X". + static std::string FormatByte(unsigned char value); + + private: + String(); // Not meant to be instantiated. +}; // class String + +// Gets the content of the stringstream's buffer as an std::string. Each '\0' +// character in the buffer is replaced with "\\0". +GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +// 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: keith.ray@gmail.com (Keith Ray) +// +// Google Test filepath utilities +// +// This header file declares classes and functions used internally by +// Google Test. They are subject to change without notice. +// +// This file is #included in . +// Do not include this header file separately! + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ + + +namespace testing { +namespace internal { + +// FilePath - a class for file and directory pathname manipulation which +// handles platform-specific conventions (like the pathname separator). +// Used for helper functions for naming files in a directory for xml output. +// Except for Set methods, all methods are const or static, which provides an +// "immutable value object" -- useful for peace of mind. +// A FilePath with a value ending in a path separator ("like/this/") represents +// a directory, otherwise it is assumed to represent a file. In either case, +// it may or may not represent an actual file or directory in the file system. +// Names are NOT checked for syntax correctness -- no checking for illegal +// characters, malformed paths, etc. + +class GTEST_API_ FilePath { + public: + FilePath() : pathname_("") { } + FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } + + explicit FilePath(const std::string& pathname) : pathname_(pathname) { + Normalize(); + } + + FilePath& operator=(const FilePath& rhs) { + Set(rhs); + return *this; + } + + void Set(const FilePath& rhs) { + pathname_ = rhs.pathname_; + } + + const std::string& string() const { return pathname_; } + const char* c_str() const { return pathname_.c_str(); } + + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + + // Given directory = "dir", base_name = "test", number = 0, + // extension = "xml", returns "dir/test.xml". If number is greater + // than zero (e.g., 12), returns "dir/test_12.xml". + // On Windows platform, uses \ as the separator rather than /. + static FilePath MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension); + + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + + // Returns a pathname for a file that does not currently exist. The pathname + // will be directory/base_name.extension or + // directory/base_name_.extension if directory/base_name.extension + // already exists. The number will be incremented until a pathname is found + // that does not already exist. + // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. + // There could be a race condition if two or more processes are calling this + // function at the same time -- they could both pick the same filename. + static FilePath GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension); + + // Returns true iff the path is "". + bool IsEmpty() const { return pathname_.empty(); } + + // If input name has a trailing separator character, removes it and returns + // the name, otherwise return the name string unmodified. + // On Windows platform, uses \ as the separator, other platforms use /. + FilePath RemoveTrailingPathSeparator() const; + + // Returns a copy of the FilePath with the directory part removed. + // Example: FilePath("path/to/file").RemoveDirectoryName() returns + // FilePath("file"). If there is no directory part ("just_a_file"), it returns + // the FilePath unmodified. If there is no file part ("just_a_dir/") it + // returns an empty FilePath (""). + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveDirectoryName() const; + + // RemoveFileName returns the directory path with the filename removed. + // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". + // If the FilePath is "a_file" or "/a_file", RemoveFileName returns + // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does + // not have a file, like "just/a/dir/", it returns the FilePath unmodified. + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveFileName() const; + + // Returns a copy of the FilePath with the case-insensitive extension removed. + // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns + // FilePath("dir/file"). If a case-insensitive extension is not + // found, returns a copy of the original FilePath. + FilePath RemoveExtension(const char* extension) const; + + // Creates directories so that path exists. Returns true if successful or if + // the directories already exist; returns false if unable to create + // directories for any reason. Will also return false if the FilePath does + // not represent a directory (that is, it doesn't end with a path separator). + bool CreateDirectoriesRecursively() const; + + // Create the directory so that path exists. Returns true if successful or + // if the directory already exists; returns false if unable to create the + // directory for any reason, including if the parent directory does not + // exist. Not named "CreateDirectory" because that's a macro on Windows. + bool CreateFolder() const; + + // Returns true if FilePath describes something in the file-system, + // either a file, directory, or whatever, and that something exists. + bool FileOrDirectoryExists() const; + + // Returns true if pathname describes a directory in the file-system + // that exists. + bool DirectoryExists() const; + + // Returns true if FilePath ends with a path separator, which indicates that + // it is intended to represent a directory. Returns false otherwise. + // This does NOT check that a directory (or file) actually exists. + bool IsDirectory() const; + + // Returns true if pathname describes a root directory. (Windows has one + // root directory per disk drive.) + bool IsRootDirectory() const; + + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + + private: + // Replaces multiple consecutive separators with a single separator. + // For example, "bar///foo" becomes "bar/foo". Does not eliminate other + // redundancies that might be in a pathname involving "." or "..". + // + // A pathname with multiple consecutive separators may occur either through + // user error or as a result of some scripts or APIs that generate a pathname + // with a trailing separator. On other platforms the same API or script + // may NOT generate a pathname with a trailing "/". Then elsewhere that + // pathname may have another "/" and pathname components added to it, + // without checking for the separator already being there. + // The script language and operating system may allow paths like "foo//bar" + // but some of the functions in FilePath will not handle that correctly. In + // particular, RemoveTrailingPathSeparator() only removes one separator, and + // it is called in CreateDirectoriesRecursively() assuming that it will change + // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". + + void Normalize(); + + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + + std::string pathname_; +}; // class FilePath + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +// This file was GENERATED by command: +// pump.py gtest-type-util.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) + +// Type utilities needed for implementing typed and type-parameterized +// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently we support at most 50 types in a list, and at most 50 +// type-parameterized tests in one type-parameterized test case. +// Please contact googletestframework@googlegroups.com if you need +// more. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + + +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +# if GTEST_HAS_CXXABI_H_ +# include +# elif defined(__HP_aCC) +# include +# endif // GTEST_HASH_CXXABI_H_ + +namespace testing { +namespace internal { + +// GetTypeName() returns a human-readable name of type T. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +std::string GetTypeName() { +# if GTEST_HAS_RTTI + + const char* const name = typeid(T).name(); +# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) + int status = 0; + // gcc's implementation of typeid(T).name() mangles the type name, + // so we have to demangle it. +# if GTEST_HAS_CXXABI_H_ + using abi::__cxa_demangle; +# endif // GTEST_HAS_CXXABI_H_ + char* const readable_name = __cxa_demangle(name, 0, 0, &status); + const std::string name_str(status == 0 ? readable_name : name); + free(readable_name); + return name_str; +# else + return name; +# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC + +# else + + return ""; + +# endif // GTEST_HAS_RTTI +} + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// AssertyTypeEq::type is defined iff T1 and T2 are the same +// type. This can be used as a compile-time assertion to ensure that +// two types are equal. + +template +struct AssertTypeEq; + +template +struct AssertTypeEq { + typedef bool type; +}; + +// A unique type used as the default value for the arguments of class +// template Types. This allows us to simulate variadic templates +// (e.g. Types, Type, and etc), which C++ doesn't +// support directly. +struct None {}; + +// The following family of struct and struct templates are used to +// represent type lists. In particular, TypesN +// represents a type list with N types (T1, T2, ..., and TN) in it. +// Except for Types0, every struct in the family has two member types: +// Head for the first type in the list, and Tail for the rest of the +// list. + +// The empty type list. +struct Types0 {}; + +// Type lists of length 1, 2, 3, and so on. + +template +struct Types1 { + typedef T1 Head; + typedef Types0 Tail; +}; +template +struct Types2 { + typedef T1 Head; + typedef Types1 Tail; +}; + +template +struct Types3 { + typedef T1 Head; + typedef Types2 Tail; +}; + +template +struct Types4 { + typedef T1 Head; + typedef Types3 Tail; +}; + +template +struct Types5 { + typedef T1 Head; + typedef Types4 Tail; +}; + +template +struct Types6 { + typedef T1 Head; + typedef Types5 Tail; +}; + +template +struct Types7 { + typedef T1 Head; + typedef Types6 Tail; +}; + +template +struct Types8 { + typedef T1 Head; + typedef Types7 Tail; +}; + +template +struct Types9 { + typedef T1 Head; + typedef Types8 Tail; +}; + +template +struct Types10 { + typedef T1 Head; + typedef Types9 Tail; +}; + +template +struct Types11 { + typedef T1 Head; + typedef Types10 Tail; +}; + +template +struct Types12 { + typedef T1 Head; + typedef Types11 Tail; +}; + +template +struct Types13 { + typedef T1 Head; + typedef Types12 Tail; +}; + +template +struct Types14 { + typedef T1 Head; + typedef Types13 Tail; +}; + +template +struct Types15 { + typedef T1 Head; + typedef Types14 Tail; +}; + +template +struct Types16 { + typedef T1 Head; + typedef Types15 Tail; +}; + +template +struct Types17 { + typedef T1 Head; + typedef Types16 Tail; +}; + +template +struct Types18 { + typedef T1 Head; + typedef Types17 Tail; +}; + +template +struct Types19 { + typedef T1 Head; + typedef Types18 Tail; +}; + +template +struct Types20 { + typedef T1 Head; + typedef Types19 Tail; +}; + +template +struct Types21 { + typedef T1 Head; + typedef Types20 Tail; +}; + +template +struct Types22 { + typedef T1 Head; + typedef Types21 Tail; +}; + +template +struct Types23 { + typedef T1 Head; + typedef Types22 Tail; +}; + +template +struct Types24 { + typedef T1 Head; + typedef Types23 Tail; +}; + +template +struct Types25 { + typedef T1 Head; + typedef Types24 Tail; +}; + +template +struct Types26 { + typedef T1 Head; + typedef Types25 Tail; +}; + +template +struct Types27 { + typedef T1 Head; + typedef Types26 Tail; +}; + +template +struct Types28 { + typedef T1 Head; + typedef Types27 Tail; +}; + +template +struct Types29 { + typedef T1 Head; + typedef Types28 Tail; +}; + +template +struct Types30 { + typedef T1 Head; + typedef Types29 Tail; +}; + +template +struct Types31 { + typedef T1 Head; + typedef Types30 Tail; +}; + +template +struct Types32 { + typedef T1 Head; + typedef Types31 Tail; +}; + +template +struct Types33 { + typedef T1 Head; + typedef Types32 Tail; +}; + +template +struct Types34 { + typedef T1 Head; + typedef Types33 Tail; +}; + +template +struct Types35 { + typedef T1 Head; + typedef Types34 Tail; +}; + +template +struct Types36 { + typedef T1 Head; + typedef Types35 Tail; +}; + +template +struct Types37 { + typedef T1 Head; + typedef Types36 Tail; +}; + +template +struct Types38 { + typedef T1 Head; + typedef Types37 Tail; +}; + +template +struct Types39 { + typedef T1 Head; + typedef Types38 Tail; +}; + +template +struct Types40 { + typedef T1 Head; + typedef Types39 Tail; +}; + +template +struct Types41 { + typedef T1 Head; + typedef Types40 Tail; +}; + +template +struct Types42 { + typedef T1 Head; + typedef Types41 Tail; +}; + +template +struct Types43 { + typedef T1 Head; + typedef Types42 Tail; +}; + +template +struct Types44 { + typedef T1 Head; + typedef Types43 Tail; +}; + +template +struct Types45 { + typedef T1 Head; + typedef Types44 Tail; +}; + +template +struct Types46 { + typedef T1 Head; + typedef Types45 Tail; +}; + +template +struct Types47 { + typedef T1 Head; + typedef Types46 Tail; +}; + +template +struct Types48 { + typedef T1 Head; + typedef Types47 Tail; +}; + +template +struct Types49 { + typedef T1 Head; + typedef Types48 Tail; +}; + +template +struct Types50 { + typedef T1 Head; + typedef Types49 Tail; +}; + + +} // namespace internal + +// We don't want to require the users to write TypesN<...> directly, +// as that would require them to count the length. Types<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Types +// will appear as Types in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Types, and Google Test will translate +// that to TypesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Types template. +template +struct Types { + typedef internal::Types50 type; +}; + +template <> +struct Types { + typedef internal::Types0 type; +}; +template +struct Types { + typedef internal::Types1 type; +}; +template +struct Types { + typedef internal::Types2 type; +}; +template +struct Types { + typedef internal::Types3 type; +}; +template +struct Types { + typedef internal::Types4 type; +}; +template +struct Types { + typedef internal::Types5 type; +}; +template +struct Types { + typedef internal::Types6 type; +}; +template +struct Types { + typedef internal::Types7 type; +}; +template +struct Types { + typedef internal::Types8 type; +}; +template +struct Types { + typedef internal::Types9 type; +}; +template +struct Types { + typedef internal::Types10 type; +}; +template +struct Types { + typedef internal::Types11 type; +}; +template +struct Types { + typedef internal::Types12 type; +}; +template +struct Types { + typedef internal::Types13 type; +}; +template +struct Types { + typedef internal::Types14 type; +}; +template +struct Types { + typedef internal::Types15 type; +}; +template +struct Types { + typedef internal::Types16 type; +}; +template +struct Types { + typedef internal::Types17 type; +}; +template +struct Types { + typedef internal::Types18 type; +}; +template +struct Types { + typedef internal::Types19 type; +}; +template +struct Types { + typedef internal::Types20 type; +}; +template +struct Types { + typedef internal::Types21 type; +}; +template +struct Types { + typedef internal::Types22 type; +}; +template +struct Types { + typedef internal::Types23 type; +}; +template +struct Types { + typedef internal::Types24 type; +}; +template +struct Types { + typedef internal::Types25 type; +}; +template +struct Types { + typedef internal::Types26 type; +}; +template +struct Types { + typedef internal::Types27 type; +}; +template +struct Types { + typedef internal::Types28 type; +}; +template +struct Types { + typedef internal::Types29 type; +}; +template +struct Types { + typedef internal::Types30 type; +}; +template +struct Types { + typedef internal::Types31 type; +}; +template +struct Types { + typedef internal::Types32 type; +}; +template +struct Types { + typedef internal::Types33 type; +}; +template +struct Types { + typedef internal::Types34 type; +}; +template +struct Types { + typedef internal::Types35 type; +}; +template +struct Types { + typedef internal::Types36 type; +}; +template +struct Types { + typedef internal::Types37 type; +}; +template +struct Types { + typedef internal::Types38 type; +}; +template +struct Types { + typedef internal::Types39 type; +}; +template +struct Types { + typedef internal::Types40 type; +}; +template +struct Types { + typedef internal::Types41 type; +}; +template +struct Types { + typedef internal::Types42 type; +}; +template +struct Types { + typedef internal::Types43 type; +}; +template +struct Types { + typedef internal::Types44 type; +}; +template +struct Types { + typedef internal::Types45 type; +}; +template +struct Types { + typedef internal::Types46 type; +}; +template +struct Types { + typedef internal::Types47 type; +}; +template +struct Types { + typedef internal::Types48 type; +}; +template +struct Types { + typedef internal::Types49 type; +}; + +namespace internal { + +# define GTEST_TEMPLATE_ template class + +// The template "selector" struct TemplateSel is used to +// represent Tmpl, which must be a class template with one type +// parameter, as a type. TemplateSel::Bind::type is defined +// as the type Tmpl. This allows us to actually instantiate the +// template "selected" by TemplateSel. +// +// This trick is necessary for simulating typedef for class templates, +// which C++ doesn't support directly. +template +struct TemplateSel { + template + struct Bind { + typedef Tmpl type; + }; +}; + +# define GTEST_BIND_(TmplSel, T) \ + TmplSel::template Bind::type + +// A unique struct template used as the default value for the +// arguments of class template Templates. This allows us to simulate +// variadic templates (e.g. Templates, Templates, +// and etc), which C++ doesn't support directly. +template +struct NoneT {}; + +// The following family of struct and struct templates are used to +// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except +// for Templates0, every struct in the family has two member types: +// Head for the selector of the first template in the list, and Tail +// for the rest of the list. + +// The empty template list. +struct Templates0 {}; + +// Template lists of length 1, 2, 3, and so on. + +template +struct Templates1 { + typedef TemplateSel Head; + typedef Templates0 Tail; +}; +template +struct Templates2 { + typedef TemplateSel Head; + typedef Templates1 Tail; +}; + +template +struct Templates3 { + typedef TemplateSel Head; + typedef Templates2 Tail; +}; + +template +struct Templates4 { + typedef TemplateSel Head; + typedef Templates3 Tail; +}; + +template +struct Templates5 { + typedef TemplateSel Head; + typedef Templates4 Tail; +}; + +template +struct Templates6 { + typedef TemplateSel Head; + typedef Templates5 Tail; +}; + +template +struct Templates7 { + typedef TemplateSel Head; + typedef Templates6 Tail; +}; + +template +struct Templates8 { + typedef TemplateSel Head; + typedef Templates7 Tail; +}; + +template +struct Templates9 { + typedef TemplateSel Head; + typedef Templates8 Tail; +}; + +template +struct Templates10 { + typedef TemplateSel Head; + typedef Templates9 Tail; +}; + +template +struct Templates11 { + typedef TemplateSel Head; + typedef Templates10 Tail; +}; + +template +struct Templates12 { + typedef TemplateSel Head; + typedef Templates11 Tail; +}; + +template +struct Templates13 { + typedef TemplateSel Head; + typedef Templates12 Tail; +}; + +template +struct Templates14 { + typedef TemplateSel Head; + typedef Templates13 Tail; +}; + +template +struct Templates15 { + typedef TemplateSel Head; + typedef Templates14 Tail; +}; + +template +struct Templates16 { + typedef TemplateSel Head; + typedef Templates15 Tail; +}; + +template +struct Templates17 { + typedef TemplateSel Head; + typedef Templates16 Tail; +}; + +template +struct Templates18 { + typedef TemplateSel Head; + typedef Templates17 Tail; +}; + +template +struct Templates19 { + typedef TemplateSel Head; + typedef Templates18 Tail; +}; + +template +struct Templates20 { + typedef TemplateSel Head; + typedef Templates19 Tail; +}; + +template +struct Templates21 { + typedef TemplateSel Head; + typedef Templates20 Tail; +}; + +template +struct Templates22 { + typedef TemplateSel Head; + typedef Templates21 Tail; +}; + +template +struct Templates23 { + typedef TemplateSel Head; + typedef Templates22 Tail; +}; + +template +struct Templates24 { + typedef TemplateSel Head; + typedef Templates23 Tail; +}; + +template +struct Templates25 { + typedef TemplateSel Head; + typedef Templates24 Tail; +}; + +template +struct Templates26 { + typedef TemplateSel Head; + typedef Templates25 Tail; +}; + +template +struct Templates27 { + typedef TemplateSel Head; + typedef Templates26 Tail; +}; + +template +struct Templates28 { + typedef TemplateSel Head; + typedef Templates27 Tail; +}; + +template +struct Templates29 { + typedef TemplateSel Head; + typedef Templates28 Tail; +}; + +template +struct Templates30 { + typedef TemplateSel Head; + typedef Templates29 Tail; +}; + +template +struct Templates31 { + typedef TemplateSel Head; + typedef Templates30 Tail; +}; + +template +struct Templates32 { + typedef TemplateSel Head; + typedef Templates31 Tail; +}; + +template +struct Templates33 { + typedef TemplateSel Head; + typedef Templates32 Tail; +}; + +template +struct Templates34 { + typedef TemplateSel Head; + typedef Templates33 Tail; +}; + +template +struct Templates35 { + typedef TemplateSel Head; + typedef Templates34 Tail; +}; + +template +struct Templates36 { + typedef TemplateSel Head; + typedef Templates35 Tail; +}; + +template +struct Templates37 { + typedef TemplateSel Head; + typedef Templates36 Tail; +}; + +template +struct Templates38 { + typedef TemplateSel Head; + typedef Templates37 Tail; +}; + +template +struct Templates39 { + typedef TemplateSel Head; + typedef Templates38 Tail; +}; + +template +struct Templates40 { + typedef TemplateSel Head; + typedef Templates39 Tail; +}; + +template +struct Templates41 { + typedef TemplateSel Head; + typedef Templates40 Tail; +}; + +template +struct Templates42 { + typedef TemplateSel Head; + typedef Templates41 Tail; +}; + +template +struct Templates43 { + typedef TemplateSel Head; + typedef Templates42 Tail; +}; + +template +struct Templates44 { + typedef TemplateSel Head; + typedef Templates43 Tail; +}; + +template +struct Templates45 { + typedef TemplateSel Head; + typedef Templates44 Tail; +}; + +template +struct Templates46 { + typedef TemplateSel Head; + typedef Templates45 Tail; +}; + +template +struct Templates47 { + typedef TemplateSel Head; + typedef Templates46 Tail; +}; + +template +struct Templates48 { + typedef TemplateSel Head; + typedef Templates47 Tail; +}; + +template +struct Templates49 { + typedef TemplateSel Head; + typedef Templates48 Tail; +}; + +template +struct Templates50 { + typedef TemplateSel Head; + typedef Templates49 Tail; +}; + + +// We don't want to require the users to write TemplatesN<...> directly, +// as that would require them to count the length. Templates<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Templates +// will appear as Templates in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Templates, and Google Test will translate +// that to TemplatesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Templates template. +template +struct Templates { + typedef Templates50 type; +}; + +template <> +struct Templates { + typedef Templates0 type; +}; +template +struct Templates { + typedef Templates1 type; +}; +template +struct Templates { + typedef Templates2 type; +}; +template +struct Templates { + typedef Templates3 type; +}; +template +struct Templates { + typedef Templates4 type; +}; +template +struct Templates { + typedef Templates5 type; +}; +template +struct Templates { + typedef Templates6 type; +}; +template +struct Templates { + typedef Templates7 type; +}; +template +struct Templates { + typedef Templates8 type; +}; +template +struct Templates { + typedef Templates9 type; +}; +template +struct Templates { + typedef Templates10 type; +}; +template +struct Templates { + typedef Templates11 type; +}; +template +struct Templates { + typedef Templates12 type; +}; +template +struct Templates { + typedef Templates13 type; +}; +template +struct Templates { + typedef Templates14 type; +}; +template +struct Templates { + typedef Templates15 type; +}; +template +struct Templates { + typedef Templates16 type; +}; +template +struct Templates { + typedef Templates17 type; +}; +template +struct Templates { + typedef Templates18 type; +}; +template +struct Templates { + typedef Templates19 type; +}; +template +struct Templates { + typedef Templates20 type; +}; +template +struct Templates { + typedef Templates21 type; +}; +template +struct Templates { + typedef Templates22 type; +}; +template +struct Templates { + typedef Templates23 type; +}; +template +struct Templates { + typedef Templates24 type; +}; +template +struct Templates { + typedef Templates25 type; +}; +template +struct Templates { + typedef Templates26 type; +}; +template +struct Templates { + typedef Templates27 type; +}; +template +struct Templates { + typedef Templates28 type; +}; +template +struct Templates { + typedef Templates29 type; +}; +template +struct Templates { + typedef Templates30 type; +}; +template +struct Templates { + typedef Templates31 type; +}; +template +struct Templates { + typedef Templates32 type; +}; +template +struct Templates { + typedef Templates33 type; +}; +template +struct Templates { + typedef Templates34 type; +}; +template +struct Templates { + typedef Templates35 type; +}; +template +struct Templates { + typedef Templates36 type; +}; +template +struct Templates { + typedef Templates37 type; +}; +template +struct Templates { + typedef Templates38 type; +}; +template +struct Templates { + typedef Templates39 type; +}; +template +struct Templates { + typedef Templates40 type; +}; +template +struct Templates { + typedef Templates41 type; +}; +template +struct Templates { + typedef Templates42 type; +}; +template +struct Templates { + typedef Templates43 type; +}; +template +struct Templates { + typedef Templates44 type; +}; +template +struct Templates { + typedef Templates45 type; +}; +template +struct Templates { + typedef Templates46 type; +}; +template +struct Templates { + typedef Templates47 type; +}; +template +struct Templates { + typedef Templates48 type; +}; +template +struct Templates { + typedef Templates49 type; +}; + +// The TypeList template makes it possible to use either a single type +// or a Types<...> list in TYPED_TEST_CASE() and +// INSTANTIATE_TYPED_TEST_CASE_P(). + +template +struct TypeList { + typedef Types1 type; +}; + +template +struct TypeList > { + typedef typename Types::type type; +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + +// Due to C++ preprocessor weirdness, we need double indirection to +// concatenate two tokens when one of them is __LINE__. Writing +// +// foo ## __LINE__ +// +// will result in the token foo__LINE__, instead of foo followed by +// the current line number. For more details, see +// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 +#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) +#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar + +class ProtocolMessage; +namespace proto2 { class Message; } + +namespace testing { + +// Forward declarations. + +class AssertionResult; // Result of an assertion. +class Message; // Represents a failure message. +class Test; // Represents a test. +class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. +class UnitTest; // A collection of test cases. + +template +::std::string PrintToString(const T& value); + +namespace internal { + +struct TraceInfo; // Information about a trace point. +class ScopedTrace; // Implements scoped trace. +class TestInfoImpl; // Opaque implementation of TestInfo +class UnitTestImpl; // Opaque implementation of UnitTest + +// How many times InitGoogleTest() has been called. +GTEST_API_ extern int g_init_gtest_count; + +// The text used in failure messages to indicate the start of the +// stack trace. +GTEST_API_ extern const char kStackTraceMarker[]; + +// Two overloaded helpers for checking at compile time whether an +// expression is a null pointer literal (i.e. NULL or any 0-valued +// compile-time integral constant). Their return values have +// different sizes, so we can use sizeof() to test which version is +// picked by the compiler. These helpers have no implementations, as +// we only need their signatures. +// +// Given IsNullLiteralHelper(x), the compiler will pick the first +// version if x can be implicitly converted to Secret*, and pick the +// second version otherwise. Since Secret is a secret and incomplete +// type, the only expression a user can write that has type Secret* is +// a null pointer literal. Therefore, we know that x is a null +// pointer literal if and only if the first version is picked by the +// compiler. +char IsNullLiteralHelper(Secret* p); +char (&IsNullLiteralHelper(...))[2]; // NOLINT + +// A compile-time bool constant that is true if and only if x is a +// null pointer literal (i.e. NULL or any 0-valued compile-time +// integral constant). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_IS_NULL_LITERAL_(x) false +#else +# define GTEST_IS_NULL_LITERAL_(x) \ + (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) +#endif // GTEST_ELLIPSIS_NEEDS_POD_ + +// Appends the user-supplied message to the Google-Test-generated message. +GTEST_API_ std::string AppendUserMessage( + const std::string& gtest_msg, const Message& user_msg); + +#if GTEST_HAS_EXCEPTIONS + +// This exception is thrown by (and only by) a failed Google Test +// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions +// are enabled). We derive it from std::runtime_error, which is for +// errors presumably detectable only at run time. Since +// std::runtime_error inherits from std::exception, many testing +// frameworks know how to extract and print the message inside it. +class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure); +}; + +#endif // GTEST_HAS_EXCEPTIONS + +// A helper class for creating scoped traces in user programs. +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + ScopedTrace(const char* file, int line, const Message& message); + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +// This template class represents an IEEE floating-point number +// (either single-precision or double-precision, depending on the +// template parameters). +// +// The purpose of this class is to do more sophisticated number +// comparison. (Due to round-off error, etc, it's very unlikely that +// two floating-points will be equal exactly. Hence a naive +// comparison by the == operation often doesn't work.) +// +// Format of IEEE floating-point: +// +// The most-significant bit being the leftmost, an IEEE +// floating-point looks like +// +// sign_bit exponent_bits fraction_bits +// +// Here, sign_bit is a single bit that designates the sign of the +// number. +// +// For float, there are 8 exponent bits and 23 fraction bits. +// +// For double, there are 11 exponent bits and 52 fraction bits. +// +// More details can be found at +// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +template +class FloatingPoint { + public: + // Defines the unsigned integer type that has the same size as the + // floating point number. + typedef typename TypeWithSize::UInt Bits; + + // Constants. + + // # of bits in a number. + static const size_t kBitCount = 8*sizeof(RawType); + + // # of fraction bits in a number. + static const size_t kFractionBitCount = + std::numeric_limits::digits - 1; + + // # of exponent bits in a number. + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; + + // The mask for the sign bit. + static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); + + // The mask for the fraction bits. + static const Bits kFractionBitMask = + ~static_cast(0) >> (kExponentBitCount + 1); + + // The mask for the exponent bits. + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); + + // How many ULP's (Units in the Last Place) we want to tolerate when + // comparing two numbers. The larger the value, the more error we + // allow. A 0 value means that two numbers must be exactly the same + // to be considered equal. + // + // The maximum error of a single floating-point operation is 0.5 + // units in the last place. On Intel CPU's, all floating-point + // calculations are done with 80-bit precision, while double has 64 + // bits. Therefore, 4 should be enough for ordinary use. + // + // See the following article for more details on ULP: + // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + static const size_t kMaxUlps = 4; + + // Constructs a FloatingPoint from a raw floating-point number. + // + // On an Intel CPU, passing a non-normalized NAN (Not a Number) + // around may change its bits, although the new value is guaranteed + // to be also a NAN. Therefore, don't expect this constructor to + // preserve the bits in x when x is a NAN. + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } + + // Static methods + + // Reinterprets a bit pattern as a floating-point number. + // + // This function is needed to test the AlmostEquals() method. + static RawType ReinterpretBits(const Bits bits) { + FloatingPoint fp(0); + fp.u_.bits_ = bits; + return fp.u_.value_; + } + + // Returns the floating-point number that represent positive infinity. + static RawType Infinity() { + return ReinterpretBits(kExponentBitMask); + } + + // Returns the maximum representable finite floating-point number. + static RawType Max(); + + // Non-static methods + + // Returns the bits that represents this number. + const Bits &bits() const { return u_.bits_; } + + // Returns the exponent bits of this number. + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } + + // Returns the fraction bits of this number. + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } + + // Returns the sign bit of this number. + Bits sign_bit() const { return kSignBitMask & u_.bits_; } + + // Returns true iff this is NAN (not a number). + bool is_nan() const { + // It's a NAN if the exponent bits are all ones and the fraction + // bits are not entirely zeros. + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); + } + + // Returns true iff this number is at most kMaxUlps ULP's away from + // rhs. In particular, this function: + // + // - returns false if either number is (or both are) NAN. + // - treats really large numbers as almost equal to infinity. + // - thinks +0.0 and -0.0 are 0 DLP's apart. + bool AlmostEquals(const FloatingPoint& rhs) const { + // The IEEE standard says that any comparison operation involving + // a NAN must return false. + if (is_nan() || rhs.is_nan()) return false; + + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; + } + + private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + + // Converts an integer from the sign-and-magnitude representation to + // the biased representation. More precisely, let N be 2 to the + // power of (kBitCount - 1), an integer x is represented by the + // unsigned number x + N. + // + // For instance, + // + // -N + 1 (the most negative number representable using + // sign-and-magnitude) is represented by 1; + // 0 is represented by N; and + // N - 1 (the biggest number representable using + // sign-and-magnitude) is represented by 2N - 1. + // + // Read http://en.wikipedia.org/wiki/Signed_number_representations + // for more details on signed number representations. + static Bits SignAndMagnitudeToBiased(const Bits &sam) { + if (kSignBitMask & sam) { + // sam represents a negative number. + return ~sam + 1; + } else { + // sam represents a positive number. + return kSignBitMask | sam; + } + } + + // Given two numbers in the sign-and-magnitude representation, + // returns the distance between them as an unsigned number. + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, + const Bits &sam2) { + const Bits biased1 = SignAndMagnitudeToBiased(sam1); + const Bits biased2 = SignAndMagnitudeToBiased(sam2); + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); + } + + FloatingPointUnion u_; +}; + +// We cannot use std::numeric_limits::max() as it clashes with the max() +// macro defined by . +template <> +inline float FloatingPoint::Max() { return FLT_MAX; } +template <> +inline double FloatingPoint::Max() { return DBL_MAX; } + +// Typedefs the instances of the FloatingPoint template class that we +// care to use. +typedef FloatingPoint Float; +typedef FloatingPoint Double; + +// In order to catch the mistake of putting tests that use different +// test fixture classes in the same test case, we need to assign +// unique IDs to fixture classes and compare them. The TypeId type is +// used to hold such IDs. The user should treat TypeId as an opaque +// type: the only operation allowed on TypeId values is to compare +// them for equality using the == operator. +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; + +// GetTypeId() returns the ID of type T. Different values will be +// returned for different types. Calling the function twice with the +// same type argument is guaranteed to return the same ID. +template +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); +} + +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +GTEST_API_ TypeId GetTestTypeId(); + +// Defines the abstract factory interface that creates instances +// of a Test object. +class TestFactoryBase { + public: + virtual ~TestFactoryBase() {} + + // Creates a test instance to run. The instance is both created and destroyed + // within TestInfoImpl::Run() + virtual Test* CreateTest() = 0; + + protected: + TestFactoryBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); +}; + +// This class provides implementation of TeastFactoryBase interface. +// It is used in TEST and TEST_F macros. +template +class TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + +#if GTEST_OS_WINDOWS + +// Predicate-formatters for implementing the HRESULT checking macros +// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} +// We pass a long instead of HRESULT to avoid causing an +// include dependency for the HRESULT type. +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT + +#endif // GTEST_OS_WINDOWS + +// Types of SetUpTestCase() and TearDownTestCase() functions. +typedef void (*SetUpTestCaseFunc)(); +typedef void (*TearDownTestCaseFunc)(); + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param text representation of the test's value parameter, +// or NULL if this is not a type-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory); + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// State of the definition of a type-parameterized test case. +class GTEST_API_ TypedTestCasePState { + public: + TypedTestCasePState() : registered_(false) {} + + // Adds the given test name to defined_test_names_ and return true + // if the test case hasn't been registered; otherwise aborts the + // program. + bool AddTestName(const char* file, int line, const char* case_name, + const char* test_name) { + if (registered_) { + fprintf(stderr, "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + FormatFileLocation(file, line).c_str(), test_name, case_name); + fflush(stderr); + posix::Abort(); + } + defined_test_names_.insert(test_name); + return true; + } + + // Verifies that registered_tests match the test names in + // defined_test_names_; returns registered_tests if successful, or + // aborts the program otherwise. + const char* VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests); + + private: + bool registered_; + ::std::set defined_test_names_; +}; + +// Skips to the first non-space char after the first comma in 'str'; +// returns NULL if no comma is found in 'str'. +inline const char* SkipComma(const char* str) { + const char* comma = strchr(str, ','); + if (comma == NULL) { + return NULL; + } + while (IsSpace(*(++comma))) {} + return comma; +} + +// Returns the prefix of 'str' before the first comma in it; returns +// the entire string if it contains no comma. +inline std::string GetPrefixUntilComma(const char* str) { + const char* comma = strchr(str, ','); + return comma == NULL ? str : std::string(str, comma); +} + +// TypeParameterizedTest::Register() +// registers a list of type-parameterized tests with Google Test. The +// return value is insignificant - we just need to return something +// such that we can call this function in a namespace scope. +// +// Implementation note: The GTEST_TEMPLATE_ macro declares a template +// template parameter. It's defined in gtest-type-util.h. +template +class TypeParameterizedTest { + public: + // 'index' is the index of the test in the type list 'Types' + // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // Types). Valid values for 'index' are [0, N - 1] where N is the + // length of Types. + static bool Register(const char* prefix, const char* case_name, + const char* test_names, int index) { + typedef typename Types::Head Type; + typedef Fixture FixtureClass; + typedef typename GTEST_BIND_(TestSel, Type) TestClass; + + // First, registers the first type-parameterized test in the type + // list. + MakeAndRegisterTestInfo( + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" + + StreamableToString(index)).c_str(), + GetPrefixUntilComma(test_names).c_str(), + GetTypeName().c_str(), + NULL, // No value parameter. + GetTypeId(), + TestClass::SetUpTestCase, + TestClass::TearDownTestCase, + new TestFactoryImpl); + + // Next, recurses (at compile time) with the tail of the type list. + return TypeParameterizedTest + ::Register(prefix, case_name, test_names, index + 1); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTest { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/, int /*index*/) { + return true; + } +}; + +// TypeParameterizedTestCase::Register() +// registers *all combinations* of 'Tests' and 'Types' with Google +// Test. The return value is insignificant - we just need to return +// something such that we can call this function in a namespace scope. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* prefix, const char* case_name, + const char* test_names) { + typedef typename Tests::Head Head; + + // First, register the first test in 'Test' for each type in 'Types'. + TypeParameterizedTest::Register( + prefix, case_name, test_names, 0); + + // Next, recurses (at compile time) with the tail of the test list. + return TypeParameterizedTestCase + ::Register(prefix, case_name, SkipComma(test_names)); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { + return true; + } +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +GTEST_API_ std::string GetCurrentOsStackTraceExceptTop( + UnitTest* unit_test, int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// Helper for suppressing false warning from Clang on a const char* +// variable declared in a conditional expression always being NULL in +// the else branch. +struct GTEST_API_ ConstCharPtr { + ConstCharPtr(const char* str) : value(str) {} + operator bool() const { return true; } + const char* value; +}; + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} + + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; + +// Defining a variable of type CompileAssertTypesEqual will cause a +// compiler error iff T1 and T2 are different types. +template +struct CompileAssertTypesEqual; + +template +struct CompileAssertTypesEqual { +}; + +// Removes the reference from a type if it is a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::remove_reference, which is not widely available yet. +template +struct RemoveReference { typedef T type; }; // NOLINT +template +struct RemoveReference { typedef T type; }; // NOLINT + +// A handy wrapper around RemoveReference that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_REFERENCE_(T) \ + typename ::testing::internal::RemoveReference::type + +// Removes const from a type if it is a const type, otherwise leaves +// it unchanged. This is the same as tr1::remove_const, which is not +// widely available yet. +template +struct RemoveConst { typedef T type; }; // NOLINT +template +struct RemoveConst { typedef T type; }; // NOLINT + +// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above +// definition to fail to remove the const in 'const int[3]' and 'const +// char[3][4]'. The following specialization works around the bug. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; + +#if defined(_MSC_VER) && _MSC_VER < 1400 +// This is the only specialization that allows VC++ 7.1 to remove const in +// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC +// and thus needs to be conditionally compiled. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; +#endif + +// A handy wrapper around RemoveConst that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_CONST_(T) \ + typename ::testing::internal::RemoveConst::type + +// Turns const U&, U&, const U, and U all into U. +#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ + GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) + +// Adds reference to a type if it is not a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::add_reference, which is not widely available yet. +template +struct AddReference { typedef T& type; }; // NOLINT +template +struct AddReference { typedef T& type; }; // NOLINT + +// A handy wrapper around AddReference that works when the argument T +// depends on template parameters. +#define GTEST_ADD_REFERENCE_(T) \ + typename ::testing::internal::AddReference::type + +// Adds a reference to const on top of T as necessary. For example, +// it transforms +// +// char ==> const char& +// const char ==> const char& +// char& ==> const char& +// const char& ==> const char& +// +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) + +// ImplicitlyConvertible::value is a compile-time bool +// constant that's true iff type From can be implicitly converted to +// type To. +template +class ImplicitlyConvertible { + private: + // We need the following helper functions only for their types. + // They have no implementations. + + // MakeFrom() is an expression whose type is From. We cannot simply + // use From(), as the type From may not have a public default + // constructor. + static From MakeFrom(); + + // These two functions are overloaded. Given an expression + // Helper(x), the compiler will pick the first version if x can be + // implicitly converted to type To; otherwise it will pick the + // second version. + // + // The first version returns a value of size 1, and the second + // version returns a value of size 2. Therefore, by checking the + // size of Helper(x), which can be done at compile time, we can tell + // which version of Helper() is used, and hence whether x can be + // implicitly converted to type To. + static char Helper(To); + static char (&Helper(...))[2]; // NOLINT + + // We have to put the 'public' section after the 'private' section, + // or MSVC refuses to compile the code. + public: + // 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 + // instantiation. The simplest workaround is to use its C++0x type traits + // functions (C++Builder 2009 and above only). + static const bool value = __is_convertible(From, To); +#else + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +#endif // _MSV_VER +}; +template +const bool ImplicitlyConvertible::value; + +// IsAProtocolMessage::value is a compile-time bool constant that's +// true iff T is type ProtocolMessage, proto2::Message, or a subclass +// of those. +template +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible::value || + ImplicitlyConvertible::value> { +}; + +// When the compiler sees expression IsContainerTest(0), if C is an +// STL-style container class, the first overload of IsContainerTest +// will be viable (since both C::iterator* and C::const_iterator* are +// valid types and NULL can be implicitly converted to them). It will +// be picked over the second overload as 'int' is a perfect match for +// the type of argument 0. If C::iterator or C::const_iterator is not +// a valid type, the first overload is not viable, and the second +// overload will be picked. Therefore, we can determine whether C is +// a container class by checking the type of IsContainerTest(0). +// The value of the expression is insignificant. +// +// Note that we look for both C::iterator and C::const_iterator. The +// reason is that C++ injects the name of a class as a member of the +// class itself (e.g. you can refer to class iterator as either +// 'iterator' or 'iterator::iterator'). If we look for C::iterator +// only, for example, we would mistakenly think that a class named +// iterator is an STL container. +// +// Also note that the simpler approach of overloading +// IsContainerTest(typename C::const_iterator*) and +// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. +typedef int IsContainer; +template +IsContainer IsContainerTest(int /* dummy */, + typename C::iterator* /* it */ = NULL, + typename C::const_iterator* /* const_it */ = NULL) { + return 0; +} + +typedef char IsNotContainer; +template +IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } + +// EnableIf::type is void when 'Cond' is true, and +// undefined when 'Cond' is false. To use SFINAE to make a function +// overload only apply when a particular expression is true, add +// "typename EnableIf::type* = 0" as the last parameter. +template struct EnableIf; +template<> struct EnableIf { typedef void type; }; // NOLINT + +// Utilities for native arrays. + +// ArrayEq() compares two k-dimensional native arrays using the +// elements' operator==, where k can be any integer >= 0. When k is +// 0, ArrayEq() degenerates into comparing a single pair of values. + +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs); + +// This generic version is used when k is 0. +template +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } + +// This overload is used when k >= 1. +template +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { + return internal::ArrayEq(lhs, N, rhs); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous ArrayEq() function, arrays with different sizes would +// lead to different copies of the template code. +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs) { + for (size_t i = 0; i != size; i++) { + if (!internal::ArrayEq(lhs[i], rhs[i])) + return false; + } + return true; +} + +// Finds the first element in the iterator range [begin, end) that +// equals elem. Element may be a native array type itself. +template +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { + for (Iter it = begin; it != end; ++it) { + if (internal::ArrayEq(*it, elem)) + return it; + } + return end; +} + +// CopyArray() copies a k-dimensional native array using the elements' +// operator=, where k can be any integer >= 0. When k is 0, +// CopyArray() degenerates into copying a single value. + +template +void CopyArray(const T* from, size_t size, U* to); + +// This generic version is used when k is 0. +template +inline void CopyArray(const T& from, U* to) { *to = from; } + +// This overload is used when k >= 1. +template +inline void CopyArray(const T(&from)[N], U(*to)[N]) { + internal::CopyArray(from, N, *to); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous CopyArray() function, arrays with different sizes +// would lead to different copies of the template code. +template +void CopyArray(const T* from, size_t size, U* to) { + for (size_t i = 0; i != size; i++) { + internal::CopyArray(from[i], to + i); + } +} + +// The relation between an NativeArray object (see below) and the +// native array it represents. +enum RelationToSource { + kReference, // The NativeArray references the native array. + kCopy // The NativeArray makes a copy of the native array and + // owns the copy. +}; + +// Adapts a native array to a read-only STL-style container. Instead +// of the complete STL container concept, this adaptor only implements +// members useful for Google Mock's container matchers. New members +// should be added as needed. To simplify the implementation, we only +// support Element being a raw type (i.e. having no top-level const or +// reference modifier). It's the client's responsibility to satisfy +// this requirement. Element can be an array type itself (hence +// multi-dimensional arrays are supported). +template +class NativeArray { + public: + // STL-style container typedefs. + typedef Element value_type; + typedef Element* iterator; + typedef const Element* const_iterator; + + // Constructs from a native array. + NativeArray(const Element* array, size_t count, RelationToSource relation) { + Init(array, count, relation); + } + + // Copy constructor. + NativeArray(const NativeArray& rhs) { + Init(rhs.array_, rhs.size_, rhs.relation_to_source_); + } + + ~NativeArray() { + // Ensures that the user doesn't instantiate NativeArray with a + // const or reference type. + static_cast(StaticAssertTypeEqHelper()); + if (relation_to_source_ == kCopy) + delete[] array_; + } + + // STL-style container methods. + size_t size() const { return size_; } + const_iterator begin() const { return array_; } + const_iterator end() const { return array_ + size_; } + bool operator==(const NativeArray& rhs) const { + return size() == rhs.size() && + ArrayEq(begin(), size(), rhs.begin()); + } + + private: + // Initializes this object; makes a copy of the input array if + // 'relation' is kCopy. + void Init(const Element* array, size_t a_size, RelationToSource relation) { + if (relation == kReference) { + array_ = array; + } else { + Element* const copy = new Element[a_size]; + CopyArray(array, a_size, copy); + array_ = copy; + } + size_ = a_size; + relation_to_source_ = relation; + } + + const Element* array_; + size_t size_; + RelationToSource relation_to_source_; + + GTEST_DISALLOW_ASSIGN_(NativeArray); +}; + +} // namespace internal +} // namespace testing + +#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ + ::testing::internal::AssertHelper(result_type, file, line, message) \ + = ::testing::Message() + +#define GTEST_MESSAGE_(message, result_type) \ + GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) + +#define GTEST_FATAL_FAILURE_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) + +#define GTEST_NONFATAL_FAILURE_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) + +#define GTEST_SUCCESS_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::ConstCharPtr gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ + fail(gtest_msg.value) + +#define GTEST_TEST_NO_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ + fail("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws.") + +#define GTEST_TEST_ANY_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + bool gtest_caught_any = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ + fail("Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't.") + + +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ + ; \ + else \ + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) + +#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ + fail("Expected: " #statement " doesn't generate new fatal " \ + "failures in the current thread.\n" \ + " Actual: it does.") + +// Expands to the name of the class that implements the given test. +#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + test_case_name##_##test_name##_Test + +// Helper macro for defining tests. +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ +class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ + public:\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ + private:\ + virtual void TestBody();\ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ +};\ +\ +::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ + ::test_info_ =\ + ::testing::internal::MakeAndRegisterTestInfo(\ + #test_case_name, #test_name, NULL, NULL, \ + (parent_id), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ +void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +// Copyright 2005, 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for death tests. It is +// #included by gtest.h so a user doesn't need to include this +// directly. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ + +// Copyright 2005, 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines internal utilities needed for implementing +// death tests. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + + +#include + +namespace testing { +namespace internal { + +GTEST_DECLARE_string_(internal_run_death_test); + +// Names of the flags (needed for parsing Google Test flags). +const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; +const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; + +#if GTEST_HAS_DEATH_TEST + +// DeathTest is a class that hides much of the complexity of the +// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method +// returns a concrete class that depends on the prevailing death test +// style, as defined by the --gtest_death_test_style and/or +// --gtest_internal_run_death_test flags. + +// In describing the results of death tests, these terms are used with +// the corresponding definitions: +// +// exit status: The integer exit information in the format specified +// by wait(2) +// exit code: The integer code passed to exit(3), _exit(2), or +// returned from main() +class GTEST_API_ DeathTest { + public: + // Create returns false if there was an error determining the + // appropriate action to take for the current death test; for example, + // if the gtest_death_test_style flag is set to an invalid value. + // The LastMessage method will return a more detailed message in that + // case. Otherwise, the DeathTest pointer pointed to by the "test" + // argument is set. If the death test should be skipped, the pointer + // is set to NULL; otherwise, it is set to the address of a new concrete + // DeathTest object that controls the execution of the current test. + static bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); + DeathTest(); + virtual ~DeathTest() { } + + // A helper class that aborts a death test when it's deleted. + class ReturnSentinel { + public: + explicit ReturnSentinel(DeathTest* test) : test_(test) { } + ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } + private: + DeathTest* const test_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); + } GTEST_ATTRIBUTE_UNUSED_; + + // An enumeration of possible roles that may be taken when a death + // test is encountered. EXECUTE means that the death test logic should + // be executed immediately. OVERSEE means that the program should prepare + // the appropriate environment for a child process to execute the death + // test, then wait for it to complete. + enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; + + // An enumeration of the three reasons that a test might be aborted. + enum AbortReason { + TEST_ENCOUNTERED_RETURN_STATEMENT, + TEST_THREW_EXCEPTION, + TEST_DID_NOT_DIE + }; + + // Assumes one of the above roles. + virtual TestRole AssumeRole() = 0; + + // Waits for the death test to finish and returns its status. + virtual int Wait() = 0; + + // Returns true if the death test passed; that is, the test process + // exited during the test, its exit status matches a user-supplied + // predicate, and its stderr output matches a user-supplied regular + // expression. + // The user-supplied predicate may be a macro expression rather + // than a function pointer or functor, or else Wait and Passed could + // be combined. + virtual bool Passed(bool exit_status_ok) = 0; + + // Signals that the death test did not die as expected. + virtual void Abort(AbortReason reason) = 0; + + // Returns a human-readable outcome message regarding the outcome of + // the last death test. + static const char* LastMessage(); + + static void set_last_death_test_message(const std::string& message); + + private: + // A string containing a description of the outcome of the last death test. + static std::string last_death_test_message_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); +}; + +// Factory interface for death tests. May be mocked out for testing. +class DeathTestFactory { + public: + virtual ~DeathTestFactory() { } + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) = 0; +}; + +// A concrete DeathTestFactory implementation for normal use. +class DefaultDeathTestFactory : public DeathTestFactory { + public: + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); +}; + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); + +// Traps C++ exceptions escaping statement and reports them as test +// failures. Note that trapping SEH exceptions is not implemented here. +# if GTEST_HAS_EXCEPTIONS +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (const ::std::exception& gtest_exception) { \ + fprintf(\ + stderr, \ + "\n%s: Caught std::exception-derived exception escaping the " \ + "death test statement. Exception message: %s\n", \ + ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ + gtest_exception.what()); \ + fflush(stderr); \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } catch (...) { \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } + +# else +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) + +# endif + +// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, +// ASSERT_EXIT*, and EXPECT_EXIT*. +# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const ::testing::internal::RE& gtest_regex = (regex); \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != NULL) { \ + ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ + gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel \ + gtest_sentinel(gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ + fail(::testing::internal::DeathTest::LastMessage()) +// The symbol "fail" here expands to something into which a message +// can be streamed. + +// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in +// NDEBUG mode. In this case we need the statements to be executed, the regex is +// ignored, and the macro must accept a streamed message even though the message +// is never printed. +# define GTEST_EXECUTE_STATEMENT_(statement, regex) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } else \ + ::testing::Message() + +// A class representing the parsed contents of the +// --gtest_internal_run_death_test flag, as it existed when +// RUN_ALL_TESTS was called. +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const std::string& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + const std::string& file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + std::string file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); +}; + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); + +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + +namespace testing { + +// This flag controls the style of death tests. Valid values are "threadsafe", +// meaning that the death test child process will re-execute the test binary +// from the start, running only a single death test, or "fast", +// meaning that the child process will execute the test logic immediately +// after forking. +GTEST_DECLARE_string_(death_test_style); + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +GTEST_API_ bool InDeathTestChild(); + +} // namespace internal + +// The following macros are useful for writing death tests. + +// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is +// executed: +// +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. +// +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. +// +// 3. The parent process waits for the sub-process to terminate. +// +// 4. The parent process checks the exit code and error message of +// the sub-process. +// +// Examples: +// +// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); +// for (int i = 0; i < 5; i++) { +// EXPECT_DEATH(server.ProcessRequest(i), +// "Invalid request .* in ProcessRequest()") +// << "Failed to die on request " << i; +// } +// +// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); +// +// bool KilledBySIGHUP(int exit_code) { +// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; +// } +// +// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. + +// Asserts that a given statement causes the program to exit, with an +// integer exit status that satisfies predicate, and emitting error output +// that matches regex. +# define ASSERT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) + +// Like ASSERT_EXIT, but continues on to successive tests in the +// test case, if any: +# define EXPECT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) + +// Asserts that a given statement causes the program to exit, either by +// explicitly exiting with a nonzero exit code or being killed by a +// signal, and emitting error output that matches regex. +# define ASSERT_DEATH(statement, regex) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Like ASSERT_DEATH, but continues on to successive tests in the +// test case, if any: +# define EXPECT_DEATH(statement, regex) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: + +// Tests that an exit code describes a normal exit with a given exit code. +class GTEST_API_ ExitedWithCode { + public: + explicit ExitedWithCode(int exit_code); + bool operator()(int exit_status) const; + private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + + const int exit_code_; +}; + +# if !GTEST_OS_WINDOWS +// Tests that an exit code describes an exit due to termination by a +// given signal. +class GTEST_API_ KilledBySignal { + public: + explicit KilledBySignal(int signum); + bool operator()(int exit_status) const; + private: + const int signum_; +}; +# endif // !GTEST_OS_WINDOWS + +// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. +// The death testing framework causes this to have interesting semantics, +// since the sideeffects of the call are only visible in opt mode, and not +// in debug mode. +// +// In practice, this can be used to test functions that utilize the +// LOG(DFATAL) macro using the following style: +// +// int DieInDebugOr12(int* sideeffect) { +// if (sideeffect) { +// *sideeffect = 12; +// } +// LOG(DFATAL) << "death"; +// return 12; +// } +// +// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// int sideeffect = 0; +// // Only asserts in dbg. +// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); +// +// #ifdef NDEBUG +// // opt-mode has sideeffect visible. +// EXPECT_EQ(12, sideeffect); +// #else +// // dbg-mode no visible sideeffect. +// EXPECT_EQ(0, sideeffect); +// #endif +// } +// +// This will assert that DieInDebugReturn12InOpt() crashes in debug +// mode, usually due to a DCHECK or LOG(DFATAL), but returns the +// appropriate fallback value (12 in this case) in opt mode. If you +// need to test that a function has appropriate side-effects in opt +// mode, include assertions against the side-effects. A general +// pattern for this is: +// +// EXPECT_DEBUG_DEATH({ +// // Side-effects here will have an effect after this statement in +// // opt mode, but none in debug mode. +// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); +// }, "death"); +// +# ifdef NDEBUG + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# else + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + EXPECT_DEATH(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + ASSERT_DEATH(statement, regex) + +# endif // NDEBUG for EXPECT_DEBUG_DEATH +#endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +// This file was GENERATED by command: +// pump.py gtest-param-test.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. +// +// Authors: vladl@google.com (Vlad Losev) +// +// Macros and functions for implementing parameterized tests +// in Google C++ Testing Framework (Google Test) +// +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ + + +// Value-parameterized tests allow you to test your code with different +// parameters without writing multiple copies of the same test. +// +// Here is how you use value-parameterized tests: + +#if 0 + +// To write value-parameterized tests, first you should define a fixture +// class. It is usually derived from testing::TestWithParam (see below for +// another inheritance scheme that's sometimes useful in more complicated +// class hierarchies), where the type of your parameter values. +// TestWithParam is itself derived from testing::Test. T can be any +// copyable type. If it's a raw pointer, you are responsible for managing the +// lifespan of the pointed values. + +class FooTest : public ::testing::TestWithParam { + // You can implement all the usual class fixture members here. +}; + +// Then, use the TEST_P macro to define as many parameterized tests +// for this fixture as you want. The _P suffix is for "parameterized" +// or "pattern", whichever you prefer to think. + +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} + +// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// case with any set of parameters you want. Google Test defines a number +// of functions for generating test parameters. They return what we call +// (surprise!) parameter generators. Here is a summary of them, which +// are all in the testing namespace: +// +// +// Range(begin, end [, step]) - Yields values {begin, begin+step, +// begin+step+step, ...}. The values do not +// include end. step defaults to 1. +// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. +// ValuesIn(container) - Yields values from a C-style array, an STL +// ValuesIn(begin,end) container, or an iterator range [begin, end). +// Bool() - Yields sequence {false, true}. +// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product +// for the math savvy) of the values generated +// by the N generators. +// +// For more details, see comments at the definitions of these functions below +// in this file. +// +// The following statement will instantiate tests from the FooTest test case +// each with parameter values "meeny", "miny", and "moe". + +INSTANTIATE_TEST_CASE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); + +// To distinguish different instances of the pattern, (yes, you +// can instantiate it more then once) the first argument to the +// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the +// actual test case name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: +// +// * InstantiationName/FooTest.DoesBlah/0 for "meeny" +// * InstantiationName/FooTest.DoesBlah/1 for "miny" +// * InstantiationName/FooTest.DoesBlah/2 for "moe" +// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" +// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" +// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" +// +// You can use these names in --gtest_filter. +// +// This statement will instantiate all tests from FooTest again, each +// with parameter values "cat" and "dog": + +const char* pets[] = {"cat", "dog"}; +INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); + +// The tests from the instantiation above will have these names: +// +// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" +// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" +// +// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests +// in the given test case, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_CASE_P statement. +// +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. +// +// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc +// for more examples. +// +// In the future, we plan to publish the API for defining new parameter +// generators. But for now this interface remains part of the internal +// implementation and is subject to change. +// +// +// A parameterized test fixture must be derived from testing::Test and from +// testing::WithParamInterface, where T is the type of the parameter +// values. Inheriting from TestWithParam satisfies that requirement because +// TestWithParam inherits from both Test and WithParamInterface. In more +// complicated hierarchies, however, it is occasionally useful to inherit +// separately from Test and WithParamInterface. For example: + +class BaseTest : public ::testing::Test { + // You can inherit all the usual members for a non-parameterized test + // fixture here. +}; + +class DerivedTest : public BaseTest, public ::testing::WithParamInterface { + // The usual test fixture members go here too. +}; + +TEST_F(BaseTest, HasFoo) { + // This is an ordinary non-parameterized test. +} + +TEST_P(DerivedTest, DoesBlah) { + // GetParam works just the same here as if you inherit from TestWithParam. + EXPECT_TRUE(foo.Blah(GetParam())); +} + +#endif // 0 + + +#if !GTEST_OS_SYMBIAN +# include +#endif + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// 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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ + +#include +#include +#include + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2003 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. +// +// Authors: Dan Egnor (egnor@google.com) +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// TODO(wan@google.com): rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include +#include + + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr, linked_ptr, and + // linked_ptr). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +// 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 Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// A user can teach this function how to print a class type T by +// defining either operator<<() or PrintTo() in the namespace that +// defines T. More specifically, the FIRST defined function in the +// following list will be used (assuming T is defined in namespace +// foo): +// +// 1. foo::PrintTo(const T&, ostream*) +// 2. operator<<(ostream&, const T&) defined in either foo or the +// global namespace. +// +// If none of the above is defined, it will print the debug string of +// the value if it is a protocol buffer, or print the raw bytes in the +// value otherwise. +// +// To aid debugging: when T is a reference type, the address of the +// value is also printed; when T is a (const) char pointer, both the +// pointer value and the NUL-terminated string it points to are +// printed. +// +// We also provide some convenient wrappers: +// +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); +// +// // Prints a value tersely: for a reference type, the referenced +// // value (but not the address) is printed; for a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); +// +// // Prints value using the type inferred by the compiler. The difference +// // from UniversalTersePrint() is that this function prints both the +// // pointer and the NUL-terminated string for a (const or not) char pointer. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); +// +// // Prints the fields of a tuple tersely to a string vector, one +// // element for each field. Tuple support must be enabled in +// // gtest-port.h. +// std::vector UniversalTersePrintTupleFieldsToStrings( +// const Tuple& value); +// +// Known limitation: +// +// The print primitives print the elements of an STL-style container +// using the compiler-inferred type of *iter where iter is a +// const_iterator of the container. When const_iterator is an input +// iterator but not a forward iterator, this inferred type may not +// match value_type, and the print output may be incorrect. In +// practice, this is rarely a problem as for most containers +// const_iterator is a forward iterator. We'll fix this if there's an +// actual need for it. Note that this fix cannot rely on value_type +// being defined as many user-defined container types don't have +// value_type. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +// Definitions in the 'internal' and 'internal2' name spaces are +// subject to change without notice. DO NOT USE THEM IN USER CODE! +namespace internal2 { + +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); + +// For selecting which printer to use when a given type has neither << +// nor PrintTo(). +enum TypeKind { + kProtobuf, // a protobuf type + kConvertibleToInteger, // a type implicitly convertible to BiggestInt + // (e.g. a named or unnamed enum type) + kOtherType // anything else +}; + +// TypeWithoutFormatter::PrintValue(value, os) is called +// by the universal printer to print a value of type T when neither +// operator<< nor PrintTo() is defined for T, where kTypeKind is the +// "kind" of T as defined by enum TypeKind. +template +class TypeWithoutFormatter { + public: + // This default version is called when kTypeKind is kOtherType. + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo(reinterpret_cast(&value), + sizeof(value), os); + } +}; + +// We print a protobuf using its ShortDebugString() when the string +// doesn't exceed this many characters; otherwise we print it using +// DebugString() for better readability. +const size_t kProtobufOneLinerMaxLength = 50; + +template +class TypeWithoutFormatter { + public: + static void PrintValue(const T& value, ::std::ostream* os) { + const ::testing::internal::string short_str = value.ShortDebugString(); + const ::testing::internal::string pretty_str = + short_str.length() <= kProtobufOneLinerMaxLength ? + short_str : ("\n" + value.DebugString()); + *os << ("<" + pretty_str + ">"); + } +}; + +template +class TypeWithoutFormatter { + public: + // Since T has no << operator or PrintTo() but can be implicitly + // converted to BiggestInt, we print it as a BiggestInt. + // + // Most likely T is an enum type (either named or unnamed), in which + // case printing it as an integer is the desired behavior. In case + // T is not an enum, printing it as an integer is the best we can do + // given that it has no user-defined printer. + static void PrintValue(const T& value, ::std::ostream* os) { + const internal::BiggestInt kBigInt = value; + *os << kBigInt; + } +}; + +// Prints the given value to the given ostream. If the value is a +// protocol message, its debug string is printed; if it's an enum or +// of a type implicitly convertible to BiggestInt, it's printed as an +// integer; otherwise the bytes in the value are printed. This is +// what UniversalPrinter::Print() does when it knows nothing about +// type T and T has neither << operator nor PrintTo(). +// +// A user can override this behavior for a class type Foo by defining +// a << operator in the namespace where Foo is defined. +// +// We put this operator in namespace 'internal2' instead of 'internal' +// to simplify the implementation, as much code in 'internal' needs to +// use << in STL, which would conflict with our own << were it defined +// in 'internal'. +// +// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If +// we define it to take an std::ostream instead, we'll get an +// "ambiguous overloads" compiler error when trying to print a type +// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether +// operator<<(std::ostream&, const T&) or +// operator<<(std::basic_stream, const Foo&) is more +// specific. +template +::std::basic_ostream& operator<<( + ::std::basic_ostream& os, const T& x) { + TypeWithoutFormatter::value ? kProtobuf : + internal::ImplicitlyConvertible::value ? + kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + return os; +} + +} // namespace internal2 +} // namespace testing + +// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up +// magic needed for implementing UniversalPrinter won't work. +namespace testing_internal { + +// Used to print a value that is not an STL-style container when the +// user doesn't define PrintTo() for it. +template +void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { + // With the following statement, during unqualified name lookup, + // testing::internal2::operator<< appears as if it was declared in + // the nearest enclosing namespace that contains both + // ::testing_internal and ::testing::internal2, i.e. the global + // namespace. For more details, refer to the C++ Standard section + // 7.3.4-1 [namespace.udir]. This allows us to fall back onto + // testing::internal2::operator<< in case T doesn't come with a << + // operator. + // + // We cannot write 'using ::testing::internal2::operator<<;', which + // gcc 3.3 fails to compile due to a compiler bug. + using namespace ::testing::internal2; // NOLINT + + // Assuming T is defined in namespace foo, in the next statement, + // the compiler will consider all of: + // + // 1. foo::operator<< (thanks to Koenig look-up), + // 2. ::operator<< (as the current namespace is enclosed in ::), + // 3. testing::internal2::operator<< (thanks to the using statement above). + // + // The operator<< whose type matches T best will be picked. + // + // We deliberately allow #2 to be a candidate, as sometimes it's + // impossible to define #1 (e.g. when foo is ::std, defining + // anything in it is undefined behavior unless you are a compiler + // vendor.). + *os << value; +} + +} // namespace testing_internal + +namespace testing { +namespace internal { + +// UniversalPrinter::Print(value, ostream_ptr) prints the given +// value to the given ostream. The caller must ensure that +// 'ostream_ptr' is not NULL, or the behavior is undefined. +// +// We define UniversalPrinter as a class template (as opposed to a +// function template), as we need to partially specialize it for +// reference types, which cannot be done with function templates. +template +class UniversalPrinter; + +template +void UniversalPrint(const T& value, ::std::ostream* os); + +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +template +void DefaultPrintTo(IsContainer /* dummy */, + false_type /* is not a pointer */, + const C& container, ::std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (typename C::const_iterator it = container.begin(); + it != container.end(); ++it, ++count) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(*it, os) here as PrintTo() doesn't + // handle *it being a native array. + internal::UniversalPrint(*it, os); + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; +} + +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +template +void DefaultPrintTo(IsNotContainer /* dummy */, + true_type /* is a pointer */, + T* p, ::std::ostream* os) { + if (p == NULL) { + *os << "NULL"; + } else { + // C++ doesn't allow casting from a function pointer to any object + // pointer. + // + // IsTrue() silences warnings: "Condition is always true", + // "unreachable code". + if (IsTrue(ImplicitlyConvertible::value)) { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. However, we cannot cast it to const void* directly, + // even using reinterpret_cast, as earlier versions of gcc + // (e.g. 3.4.5) cannot compile the cast when p is a function + // pointer. Casting to UInt64 first solves the problem. + *os << reinterpret_cast( + reinterpret_cast(p)); + } + } +} + +// Used to print a non-container, non-pointer value when the user +// doesn't define PrintTo() for it. +template +void DefaultPrintTo(IsNotContainer /* dummy */, + false_type /* is not a pointer */, + const T& value, ::std::ostream* os) { + ::testing_internal::DefaultPrintNonContainerTo(value, os); +} + +// Prints the given value using the << operator if it has one; +// otherwise prints the bytes in it. This is what +// UniversalPrinter::Print() does when PrintTo() is not specialized +// or overloaded for type T. +// +// A user can override this behavior for a class type Foo by defining +// an overload of PrintTo() in the namespace where Foo is defined. We +// give the user this option as sometimes defining a << operator for +// Foo is not desirable (e.g. the coding style may prevent doing it, +// or there is already a << operator but it doesn't do what the user +// wants). +template +void PrintTo(const T& value, ::std::ostream* os) { + // DefaultPrintTo() is overloaded. The type of its first two + // arguments determine which version will be picked. If T is an + // STL-style container, the version for container will be called; if + // T is a pointer, the pointer version will be called; otherwise the + // generic version will be called. + // + // Note that we check for container types here, prior to we check + // for protocol message types in our operator<<. The rationale is: + // + // For protocol messages, we want to give people a chance to + // override Google Mock's format by defining a PrintTo() or + // operator<<. For STL containers, other formats can be + // incompatible with Google Mock's format for the container + // elements; therefore we check for container types here to ensure + // that our format is used. + // + // The second argument of DefaultPrintTo() is needed to bypass a bug + // in Symbian's C++ compiler that prevents it from picking the right + // overload between: + // + // PrintTo(const T& x, ...); + // PrintTo(T* x, ...); + DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); +} + +// The following list of PrintTo() overloads tells +// UniversalPrinter::Print() how to print standard types (built-in +// types, strings, plain arrays, and pointers). + +// Overloads for various char types. +GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); +GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); +inline void PrintTo(char c, ::std::ostream* os) { + // When printing a plain char, we always treat it as unsigned. This + // way, the output won't be affected by whether the compiler thinks + // char is signed or not. + PrintTo(static_cast(c), os); +} + +// Overloads for other simple built-in types. +inline void PrintTo(bool x, ::std::ostream* os) { + *os << (x ? "true" : "false"); +} + +// Overload for wchar_t type. +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); + +// Overloads for C strings. +GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); +inline void PrintTo(char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// signed/unsigned char is often used for representing binary data, so +// we print pointers to it as void* to be safe. +inline void PrintTo(const signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(const unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Overloads for wide C strings +GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); +inline void PrintTo(wchar_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif + +// Overload for C arrays. Multi-dimensional arrays are printed +// properly. + +// Prints the given number of elements in an array, without printing +// the curly braces. +template +void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { + UniversalPrint(a[0], os); + for (size_t i = 1; i != count; i++) { + *os << ", "; + UniversalPrint(a[i], os); + } +} + +// Overloads for ::string and ::std::string. +#if GTEST_HAS_GLOBAL_STRING +GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); +inline void PrintTo(const ::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +inline void PrintTo(const ::std::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} + +// Overloads for ::wstring and ::std::wstring. +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_STD_WSTRING + +#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 +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os); + +// Overloaded PrintTo() for tuples of various arities. We support +// tuples of up-to 10 fields. The following implementation works +// regardless of whether tr1::tuple is implemented using the +// non-standard variadic template feature or not. + +inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo( + const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} +#endif // GTEST_HAS_TR1_TUPLE + +// Overload for std::pair. +template +void PrintTo(const ::std::pair& value, ::std::ostream* os) { + *os << '('; + // We cannot use UniversalPrint(value.first, os) here, as T1 may be + // a reference type. The same for printing value.second. + UniversalPrinter::Print(value.first, os); + *os << ", "; + UniversalPrinter::Print(value.second, os); + *os << ')'; +} + +// Implements printing a non-reference type T by letting the compiler +// pick the right overload of PrintTo() for T. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#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 + // conflicts with ::testing::internal::PrintTo in the body of the + // function. + static void Print(const T& value, ::std::ostream* os) { + // By default, ::testing::internal::PrintTo() is used for printing + // the value. + // + // Thanks to Koenig look-up, if T is a class and has its own + // PrintTo() function defined in its namespace, that function will + // be visible here. Since it is more specific than the generic ones + // in ::testing::internal, it will be picked by the compiler in the + // following statement - exactly what we want. + PrintTo(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// UniversalPrintArray(begin, len, os) prints an array of 'len' +// elements, starting at address 'begin'. +template +void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { + if (len == 0) { + *os << "{}"; + } else { + *os << "{ "; + const size_t kThreshold = 18; + const size_t kChunkSize = 8; + // If the array has more than kThreshold elements, we'll have to + // omit some details by printing only the first and the last + // kChunkSize elements. + // TODO(wan@google.com): let the user control the threshold using a flag. + if (len <= kThreshold) { + PrintRawArrayTo(begin, len, os); + } else { + PrintRawArrayTo(begin, kChunkSize, os); + *os << ", ..., "; + PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); + } + *os << " }"; + } +} +// This overload prints a (const) char array compactly. +GTEST_API_ void UniversalPrintArray( + const char* begin, size_t len, ::std::ostream* os); + +// This overload prints a (const) wchar_t array compactly. +GTEST_API_ void UniversalPrintArray( + const wchar_t* begin, size_t len, ::std::ostream* os); + +// Implements printing an array type T[N]. +template +class UniversalPrinter { + public: + // Prints the given array, omitting some elements when there are too + // many. + static void Print(const T (&a)[N], ::std::ostream* os) { + UniversalPrintArray(a, N, os); + } +}; + +// Implements printing a reference type T&. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#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) { + // Prints the address of the value. We use reinterpret_cast here + // as static_cast doesn't compile when T is a function type. + *os << "@" << reinterpret_cast(&value) << " "; + + // Then prints the value itself. + UniversalPrint(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// Prints a value tersely: for a reference type, the referenced value +// (but not the address) is printed; for a (const) char pointer, the +// NUL-terminated string (but not the pointer) is printed. + +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T (&value)[N], ::std::ostream* os) { + UniversalPrinter::Print(value, os); + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(const char* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(string(str), os); + } + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(char* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +#if GTEST_HAS_STD_WSTRING +template <> +class UniversalTersePrinter { + public: + static void Print(const wchar_t* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(::std::wstring(str), os); + } + } +}; +#endif + +template <> +class UniversalTersePrinter { + public: + static void Print(wchar_t* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +template +void UniversalTersePrint(const T& value, ::std::ostream* os) { + UniversalTersePrinter::Print(value, os); +} + +// Prints a value using the type inferred by the compiler. The +// difference between this and UniversalTersePrint() is that for a +// (const) char pointer, this prints both the pointer and the +// NUL-terminated string. +template +void UniversalPrint(const T& value, ::std::ostream* os) { + // A workarond for the bug in VC++ 7.1 that prevents us from instantiating + // UniversalPrinter with T directly. + typedef T T1; + UniversalPrinter::Print(value, os); +} + +#if GTEST_HAS_TR1_TUPLE +typedef ::std::vector Strings; + +// This helper template allows PrintTo() for tuples and +// UniversalTersePrintTupleFieldsToStrings() to be defined by +// induction on the number of tuple fields. The idea is that +// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N +// fields in tuple t, and can be defined in terms of +// TuplePrefixPrinter. + +// The inductive case. +template +struct TuplePrefixPrinter { + // Prints the first N fields of a tuple. + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + TuplePrefixPrinter::PrintPrefixTo(t, os); + *os << ", "; + UniversalPrinter::type> + ::Print(::std::tr1::get(t), os); + } + + // Tersely prints the first N fields of a tuple to a string vector, + // one element for each field. + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Base cases. +template <> +struct TuplePrefixPrinter<0> { + template + static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} + + template + 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 + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + UniversalPrinter::type>:: + Print(::std::tr1::get<0>(t), os); + } + + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + ::std::stringstream ss; + 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 +void PrintTupleTo(const T& t, ::std::ostream* os) { + *os << "("; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + PrintPrefixTo(t, os); + *os << ")"; +} + +// Prints the fields of a tuple tersely to a string vector, one +// element for each field. See the comment before +// UniversalTersePrint() for how we define "tersely". +template +Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { + Strings result; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + TersePrintPrefixToStrings(value, &result); + return result; +} +#endif // GTEST_HAS_TR1_TUPLE + +} // namespace internal + +template +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrinter::Print(value, &ss); + return ss.str(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { +namespace internal { + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Outputs a message explaining invalid registration of different +// fixture class for the same test case. This may happen when +// TEST_P macro is used to define two tests with the same name +// but in different namespaces. +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); + +template class ParamGeneratorInterface; +template class ParamGenerator; + +// Interface for iterating over elements provided by an implementation +// of ParamGeneratorInterface. +template +class ParamIteratorInterface { + public: + virtual ~ParamIteratorInterface() {} + // A pointer to the base generator instance. + // Used only for the purposes of iterator comparison + // to make sure that two iterators belong to the same generator. + virtual const ParamGeneratorInterface* BaseGenerator() const = 0; + // Advances iterator to point to the next element + // provided by the generator. The caller is responsible + // for not calling Advance() on an iterator equal to + // BaseGenerator()->End(). + virtual void Advance() = 0; + // Clones the iterator object. Used for implementing copy semantics + // of ParamIterator. + virtual ParamIteratorInterface* Clone() const = 0; + // Dereferences the current iterator and provides (read-only) access + // to the pointed value. It is the caller's responsibility not to call + // Current() on an iterator equal to BaseGenerator()->End(). + // Used for implementing ParamGenerator::operator*(). + virtual const T* Current() const = 0; + // Determines whether the given iterator and other point to the same + // element in the sequence generated by the generator. + // Used for implementing ParamGenerator::operator==(). + virtual bool Equals(const ParamIteratorInterface& other) const = 0; +}; + +// Class iterating over elements provided by an implementation of +// ParamGeneratorInterface. It wraps ParamIteratorInterface +// and implements the const forward iterator concept. +template +class ParamIterator { + public: + typedef T value_type; + typedef const T& reference; + typedef ptrdiff_t difference_type; + + // ParamIterator assumes ownership of the impl_ pointer. + ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} + ParamIterator& operator=(const ParamIterator& other) { + if (this != &other) + impl_.reset(other.impl_->Clone()); + return *this; + } + + const T& operator*() const { return *impl_->Current(); } + const T* operator->() const { return impl_->Current(); } + // Prefix version of operator++. + ParamIterator& operator++() { + impl_->Advance(); + return *this; + } + // Postfix version of operator++. + ParamIterator operator++(int /*unused*/) { + ParamIteratorInterface* clone = impl_->Clone(); + impl_->Advance(); + return ParamIterator(clone); + } + bool operator==(const ParamIterator& other) const { + return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); + } + bool operator!=(const ParamIterator& other) const { + return !(*this == other); + } + + private: + friend class ParamGenerator; + explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} + scoped_ptr > impl_; +}; + +// ParamGeneratorInterface is the binary interface to access generators +// defined in other translation units. +template +class ParamGeneratorInterface { + public: + typedef T ParamType; + + virtual ~ParamGeneratorInterface() {} + + // Generator interface definition + virtual ParamIteratorInterface* Begin() const = 0; + virtual ParamIteratorInterface* End() const = 0; +}; + +// Wraps ParamGeneratorInterface and provides general generator syntax +// compatible with the STL Container concept. +// This class implements copy initialization semantics and the contained +// ParamGeneratorInterface instance is shared among all copies +// of the original object. This is possible because that instance is immutable. +template +class ParamGenerator { + public: + typedef ParamIterator iterator; + + explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} + ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} + + ParamGenerator& operator=(const ParamGenerator& other) { + impl_ = other.impl_; + return *this; + } + + iterator begin() const { return iterator(impl_->Begin()); } + iterator end() const { return iterator(impl_->End()); } + + private: + linked_ptr > impl_; +}; + +// Generates values from a range of two comparable values. Can be used to +// generate sequences of user-defined types that implement operator+() and +// operator<(). +// This class is used in the Range() function. +template +class RangeGenerator : public ParamGeneratorInterface { + public: + RangeGenerator(T begin, T end, IncrementT step) + : begin_(begin), end_(end), + step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} + virtual ~RangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, begin_, 0, step_); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, end_, end_index_, step_); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, T value, int index, + IncrementT step) + : base_(base), value_(value), index_(index), step_(step) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + value_ = value_ + step_; + index_++; + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const T* Current() const { return &value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const int other_index = + CheckedDowncastToActualType(&other)->index_; + return index_ == other_index; + } + + private: + Iterator(const Iterator& other) + : ParamIteratorInterface(), + base_(other.base_), value_(other.value_), index_(other.index_), + step_(other.step_) {} + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + T value_; + int index_; + const IncrementT step_; + }; // class RangeGenerator::Iterator + + static int CalculateEndIndex(const T& begin, + const T& end, + const IncrementT& step) { + int end_index = 0; + for (T i = begin; i < end; i = i + step) + end_index++; + return end_index; + } + + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + + const T begin_; + const T end_; + const IncrementT step_; + // The index for the end() iterator. All the elements in the generated + // sequence are indexed (0-based) to aid iterator comparison. + const int end_index_; +}; // class RangeGenerator + + +// Generates values from a pair of STL-style iterators. Used in the +// ValuesIn() function. The elements are copied from the source range +// since the source can be located on the stack, and the generator +// is likely to persist beyond that stack frame. +template +class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { + public: + template + ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) + : container_(begin, end) {} + virtual ~ValuesInIteratorRangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, container_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, container_.end()); + } + + private: + typedef typename ::std::vector ContainerType; + + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + typename ContainerType::const_iterator iterator) + : base_(base), iterator_(iterator) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + ++iterator_; + value_.reset(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + // We need to use cached value referenced by iterator_ because *iterator_ + // can return a temporary object (and of type other then T), so just + // having "return &*iterator_;" doesn't work. + // value_ is updated here and not in Advance() because Advance() + // can advance iterator_ beyond the end of the range, and we cannot + // detect that fact. The client code, on the other hand, is + // responsible for not calling Current() on an out-of-range iterator. + virtual const T* Current() const { + if (value_.get() == NULL) + value_.reset(new T(*iterator_)); + return value_.get(); + } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + return iterator_ == + CheckedDowncastToActualType(&other)->iterator_; + } + + private: + Iterator(const Iterator& other) + // The explicit constructor call suppresses a false warning + // emitted by gcc when supplied with the -Wextra option. + : ParamIteratorInterface(), + base_(other.base_), + iterator_(other.iterator_) {} + + const ParamGeneratorInterface* const base_; + typename ContainerType::const_iterator iterator_; + // A cached value of *iterator_. We keep it here to allow access by + // pointer in the wrapping iterator's operator->(). + // value_ needs to be mutable to be accessed in Current(). + // Use of scoped_ptr helps manage cached value's lifetime, + // which is bound by the lifespan of the iterator itself. + mutable scoped_ptr value_; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); + + const ContainerType container_; +}; // class ValuesInIteratorRangeGenerator + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Stores a parameter value and later creates tests parameterized with that +// value. +template +class ParameterizedTestFactory : public TestFactoryBase { + public: + typedef typename TestClass::ParamType ParamType; + explicit ParameterizedTestFactory(ParamType parameter) : + parameter_(parameter) {} + virtual Test* CreateTest() { + TestClass::SetParam(¶meter_); + return new TestClass(); + } + + private: + const ParamType parameter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactoryBase is a base class for meta-factories that create +// test factories for passing into MakeAndRegisterTestInfo function. +template +class TestMetaFactoryBase { + public: + virtual ~TestMetaFactoryBase() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactory creates test factories for passing into +// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives +// ownership of test factory pointer, same factory object cannot be passed +// into that method twice. But ParameterizedTestCaseInfo is going to call +// it for each Test/Parameter value combination. Thus it needs meta factory +// creator class. +template +class TestMetaFactory + : public TestMetaFactoryBase { + public: + typedef typename TestCase::ParamType ParamType; + + TestMetaFactory() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { + return new ParameterizedTestFactory(parameter); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfoBase is a generic interface +// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// accumulates test information provided by TEST_P macro invocations +// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and uses that information to register all resulting test instances +// in RegisterTests method. The ParameterizeTestCaseRegistry class holds +// a collection of pointers to the ParameterizedTestCaseInfo objects +// and calls RegisterTests() on each of them when asked. +class ParameterizedTestCaseInfoBase { + public: + virtual ~ParameterizedTestCaseInfoBase() {} + + // Base part of test case name for display purposes. + virtual const string& GetTestCaseName() const = 0; + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const = 0; + // UnitTest class invokes this method to register tests in this + // test case right before running them in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + virtual void RegisterTests() = 0; + + protected: + ParameterizedTestCaseInfoBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test case and generators +// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that +// test case. It registers tests with all values generated by all +// generators when asked. +template +class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { + public: + // ParamType and GeneratorCreationFunc are private types but are required + // for declarations of public methods AddTestPattern() and + // AddTestCaseInstantiation(). + typedef typename TestCase::ParamType ParamType; + // A function that returns an instance of appropriate generator type. + typedef ParamGenerator(GeneratorCreationFunc)(); + + explicit ParameterizedTestCaseInfo(const char* name) + : test_case_name_(name) {} + + // Test case base name for display purposes. + virtual const string& GetTestCaseName() const { return test_case_name_; } + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + // TEST_P macro uses AddTestPattern() to record information + // about a single test in a LocalTestInfo structure. + // test_case_name is the base name of the test case (without invocation + // prefix). test_base_name is the name of an individual test without + // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is + // test case base name and DoBar is test base name. + void AddTestPattern(const char* test_case_name, + const char* test_base_name, + TestMetaFactoryBase* meta_factory) { + tests_.push_back(linked_ptr(new TestInfo(test_case_name, + test_base_name, + meta_factory))); + } + // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // about a generator. + int AddTestCaseInstantiation(const string& instantiation_name, + GeneratorCreationFunc* func, + const char* /* file */, + int /* line */) { + instantiations_.push_back(::std::make_pair(instantiation_name, func)); + return 0; // Return value used only to run this method in namespace scope. + } + // UnitTest class invokes this method to register tests in this test case + // test cases right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more then once. + virtual void RegisterTests() { + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + linked_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); gen_it != instantiations_.end(); + ++gen_it) { + const string& instantiation_name = gen_it->first; + ParamGenerator generator((*gen_it->second)()); + + string test_case_name; + if ( !instantiation_name.empty() ) + test_case_name = instantiation_name + "/"; + test_case_name += test_info->test_case_base_name; + + int i = 0; + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { + Message test_name_stream; + test_name_stream << test_info->test_base_name << "/" << i; + MakeAndRegisterTestInfo( + test_case_name.c_str(), + test_name_stream.GetString().c_str(), + NULL, // No type parameter. + PrintToString(*param_it).c_str(), + GetTestCaseTypeId(), + TestCase::SetUpTestCase, + TestCase::TearDownTestCase, + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it + } // RegisterTests + + private: + // LocalTestInfo structure keeps information about a single test registered + // with TEST_P macro. + struct TestInfo { + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const string test_case_base_name; + const string test_base_name; + const scoped_ptr > test_meta_factory; + }; + typedef ::std::vector > TestInfoContainer; + // Keeps pairs of + // received from INSTANTIATE_TEST_CASE_P macros. + typedef ::std::vector > + InstantiationContainer; + + const string test_case_name_; + TestInfoContainer tests_; + InstantiationContainer instantiations_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); +}; // class ParameterizedTestCaseInfo + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase +// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P +// macros use it to locate their corresponding ParameterizedTestCaseInfo +// descriptors. +class ParameterizedTestCaseRegistry { + public: + ParameterizedTestCaseRegistry() {} + ~ParameterizedTestCaseRegistry() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + delete *it; + } + } + + // Looks up or creates and returns a structure containing information about + // tests and instantiations of a particular test case. + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, + const char* file, + int line) { + ParameterizedTestCaseInfo* typed_test_info = NULL; + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + if ((*it)->GetTestCaseName() == test_case_name) { + if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test case setup and tear-down in this case. + ReportInvalidTestCaseType(test_case_name, file, line); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestCaseInfo >(*it); + } + break; + } + } + if (typed_test_info == NULL) { + typed_test_info = new ParameterizedTestCaseInfo(test_case_name); + test_case_infos_.push_back(typed_test_info); + } + return typed_test_info; + } + void RegisterTests() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + (*it)->RegisterTests(); + } + } + + private: + typedef ::std::vector TestCaseInfoContainer; + + TestCaseInfoContainer test_case_infos_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +// This file was GENERATED by command: +// pump.py gtest-param-util-generated.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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently Google Test supports at most 50 arguments in Values, +// and at most 10 arguments in Combine. Please contact +// googletestframework@googlegroups.com if you need more. +// Please note that the number of arguments to Combine is limited +// by the maximum arity of the implementation of tr1::tuple which is +// currently set at 10. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end); + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]); + +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { + +// Used in the Values() function to provide polymorphic capabilities. +template +class ValueArray1 { + public: + explicit ValueArray1(T1 v1) : v1_(v1) {} + + template + operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + + const T1 v1_; +}; + +template +class ValueArray2 { + public: + ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + + const T1 v1_; + const T2 v2_; +}; + +template +class ValueArray3 { + public: + ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; +}; + +template +class ValueArray4 { + public: + ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; +}; + +template +class ValueArray5 { + public: + ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; +}; + +template +class ValueArray6 { + public: + ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; +}; + +template +class ValueArray7 { + public: + ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; +}; + +template +class ValueArray8 { + public: + ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; +}; + +template +class ValueArray9 { + public: + ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; +}; + +template +class ValueArray10 { + public: + ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; +}; + +template +class ValueArray11 { + public: + ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; +}; + +template +class ValueArray12 { + public: + ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; +}; + +template +class ValueArray13 { + public: + ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; +}; + +template +class ValueArray14 { + public: + ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; +}; + +template +class ValueArray15 { + public: + ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; +}; + +template +class ValueArray16 { + public: + ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; +}; + +template +class ValueArray17 { + public: + ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; +}; + +template +class ValueArray18 { + public: + ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; +}; + +template +class ValueArray19 { + public: + ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; +}; + +template +class ValueArray20 { + public: + ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; +}; + +template +class ValueArray21 { + public: + ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; +}; + +template +class ValueArray22 { + public: + ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; +}; + +template +class ValueArray23 { + public: + ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; +}; + +template +class ValueArray24 { + public: + ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; +}; + +template +class ValueArray25 { + public: + ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; +}; + +template +class ValueArray26 { + public: + ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; +}; + +template +class ValueArray27 { + public: + ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; +}; + +template +class ValueArray28 { + public: + ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; +}; + +template +class ValueArray29 { + public: + ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; +}; + +template +class ValueArray30 { + public: + ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; +}; + +template +class ValueArray31 { + public: + ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; +}; + +template +class ValueArray32 { + public: + ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; +}; + +template +class ValueArray33 { + public: + ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; +}; + +template +class ValueArray34 { + public: + ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; +}; + +template +class ValueArray35 { + public: + ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; +}; + +template +class ValueArray36 { + public: + ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; +}; + +template +class ValueArray37 { + public: + ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; +}; + +template +class ValueArray38 { + public: + ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; +}; + +template +class ValueArray39 { + public: + ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; +}; + +template +class ValueArray40 { + public: + ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; +}; + +template +class ValueArray41 { + public: + ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; +}; + +template +class ValueArray42 { + public: + ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; +}; + +template +class ValueArray43 { + public: + ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), + v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; +}; + +template +class ValueArray44 { + public: + ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), + v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), + v43_(v43), v44_(v44) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; +}; + +template +class ValueArray45 { + public: + ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), + v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; +}; + +template +class ValueArray46 { + public: + ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; +}; + +template +class ValueArray47 { + public: + ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), + v47_(v47) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; +}; + +template +class ValueArray48 { + public: + ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), + v46_(v46), v47_(v47), v48_(v48) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; +}; + +template +class ValueArray49 { + public: + ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, + T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; +}; + +template +class ValueArray50 { + public: + ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, + T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_), static_cast(v50_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; + const T50 v50_; +}; + +# if GTEST_HAS_COMBINE +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Generates values from the Cartesian product of values produced +// by the argument generators. +// +template +class CartesianProductGenerator2 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator2(const ParamGenerator& g1, + const ParamGenerator& g2) + : g1_(g1), g2_(g2) {} + virtual ~CartesianProductGenerator2() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current2_; + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + ParamType current_value_; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; +}; // class CartesianProductGenerator2 + + +template +class CartesianProductGenerator3 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator3(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + virtual ~CartesianProductGenerator3() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current3_; + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + ParamType current_value_; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; +}; // class CartesianProductGenerator3 + + +template +class CartesianProductGenerator4 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator4(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + virtual ~CartesianProductGenerator4() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current4_; + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + ParamType current_value_; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; +}; // class CartesianProductGenerator4 + + +template +class CartesianProductGenerator5 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator5(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + virtual ~CartesianProductGenerator5() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current5_; + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + ParamType current_value_; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; +}; // class CartesianProductGenerator5 + + +template +class CartesianProductGenerator6 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator6(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + virtual ~CartesianProductGenerator6() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current6_; + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + ParamType current_value_; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; +}; // class CartesianProductGenerator6 + + +template +class CartesianProductGenerator7 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator7(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + virtual ~CartesianProductGenerator7() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current7_; + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + ParamType current_value_; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; +}; // class CartesianProductGenerator7 + + +template +class CartesianProductGenerator8 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator8(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + virtual ~CartesianProductGenerator8() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current8_; + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + ParamType current_value_; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; +}; // class CartesianProductGenerator8 + + +template +class CartesianProductGenerator9 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator9(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + virtual ~CartesianProductGenerator9() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current9_; + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + ParamType current_value_; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; +}; // class CartesianProductGenerator9 + + +template +class CartesianProductGenerator10 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator10(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9, + const ParamGenerator& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + virtual ~CartesianProductGenerator10() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end(), g10_, g10_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9, + const ParamGenerator& g10, + const typename ParamGenerator::iterator& current10) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9), + begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current10_; + if (current10_ == end10_) { + current10_ = begin10_; + ++current9_; + } + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_ && + current10_ == typed_other->current10_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_), + begin10_(other.begin10_), + end10_(other.end10_), + current10_(other.current10_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_, *current10_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_ || + current10_ == end10_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + const typename ParamGenerator::iterator begin10_; + const typename ParamGenerator::iterator end10_; + typename ParamGenerator::iterator current10_; + ParamType current_value_; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; + const ParamGenerator g10_; +}; // class CartesianProductGenerator10 + + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Helper classes providing Combine() with polymorphic features. They allow +// casting CartesianProductGeneratorN to ParamGenerator if T is +// convertible to U. +// +template +class CartesianProductHolder2 { + public: +CartesianProductHolder2(const Generator1& g1, const Generator2& g2) + : g1_(g1), g2_(g2) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator2( + static_cast >(g1_), + static_cast >(g2_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + + const Generator1 g1_; + const Generator2 g2_; +}; // class CartesianProductHolder2 + +template +class CartesianProductHolder3 { + public: +CartesianProductHolder3(const Generator1& g1, const Generator2& g2, + const Generator3& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator3( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; +}; // class CartesianProductHolder3 + +template +class CartesianProductHolder4 { + public: +CartesianProductHolder4(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator4( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; +}; // class CartesianProductHolder4 + +template +class CartesianProductHolder5 { + public: +CartesianProductHolder5(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator5( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; +}; // class CartesianProductHolder5 + +template +class CartesianProductHolder6 { + public: +CartesianProductHolder6(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator6( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; +}; // class CartesianProductHolder6 + +template +class CartesianProductHolder7 { + public: +CartesianProductHolder7(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator7( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; +}; // class CartesianProductHolder7 + +template +class CartesianProductHolder8 { + public: +CartesianProductHolder8(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator8( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; +}; // class CartesianProductHolder8 + +template +class CartesianProductHolder9 { + public: +CartesianProductHolder9(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator9( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; +}; // class CartesianProductHolder9 + +template +class CartesianProductHolder10 { + public: +CartesianProductHolder10(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9, const Generator10& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator10( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_), + static_cast >(g10_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; + const Generator10 g10_; +}; // class CartesianProductHolder10 + +# endif // GTEST_HAS_COMBINE + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Functions producing parameter generators. +// +// Google Test uses these generators to produce parameters for value- +// parameterized tests. When a parameterized test case is instantiated +// with a particular generator, Google Test creates and runs tests +// for each element in the sequence produced by the generator. +// +// In the following sample, tests from test case FooTest are instantiated +// each three times with parameter values 3, 5, and 8: +// +// class FooTest : public TestWithParam { ... }; +// +// TEST_P(FooTest, TestThis) { +// } +// TEST_P(FooTest, TestThat) { +// } +// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// + +// Range() returns generators providing sequences of values in a range. +// +// Synopsis: +// Range(start, end) +// - returns a generator producing a sequence of values {start, start+1, +// start+2, ..., }. +// Range(start, end, step) +// - returns a generator producing a sequence of values {start, start+step, +// start+step+step, ..., }. +// Notes: +// * The generated sequences never include end. For example, Range(1, 5) +// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) +// returns a generator producing {1, 3, 5, 7}. +// * start and end must have the same type. That type may be any integral or +// floating-point type or a user defined type satisfying these conditions: +// * It must be assignable (have operator=() defined). +// * It must have operator+() (operator+(int-compatible type) for +// two-operand version). +// * It must have operator<() defined. +// Elements in the resulting sequences will also have that type. +// * Condition start < end must be satisfied in order for resulting sequences +// to contain any elements. +// +template +internal::ParamGenerator Range(T start, T end, IncrementT step) { + return internal::ParamGenerator( + new internal::RangeGenerator(start, end, step)); +} + +template +internal::ParamGenerator Range(T start, T end) { + return Range(start, end, 1); +} + +// ValuesIn() function allows generation of tests with parameters coming from +// a container. +// +// Synopsis: +// ValuesIn(const T (&array)[N]) +// - returns a generator producing sequences with elements from +// a C-style array. +// ValuesIn(const Container& container) +// - returns a generator producing sequences with elements from +// an STL-style container. +// ValuesIn(Iterator begin, Iterator end) +// - returns a generator producing sequences with elements from +// a range [begin, end) defined by a pair of STL-style iterators. These +// iterators can also be plain C pointers. +// +// Please note that ValuesIn copies the values from the containers +// passed in and keeps them to generate tests in RUN_ALL_TESTS(). +// +// Examples: +// +// This instantiates tests from test case StringTest +// each with C-string values of "foo", "bar", and "baz": +// +// const char* strings[] = {"foo", "bar", "baz"}; +// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// +// This instantiates tests from test case StlStringTest +// each with STL strings with values "a" and "b": +// +// ::std::vector< ::std::string> GetParameterStrings() { +// ::std::vector< ::std::string> v; +// v.push_back("a"); +// v.push_back("b"); +// return v; +// } +// +// INSTANTIATE_TEST_CASE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); +// +// +// This will also instantiate tests from CharTest +// each with parameter values 'a' and 'b': +// +// ::std::list GetParameterChars() { +// ::std::list list; +// list.push_back('a'); +// list.push_back('b'); +// return list; +// } +// ::std::list l = GetParameterChars(); +// INSTANTIATE_TEST_CASE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); +// +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end) { + typedef typename ::testing::internal::IteratorTraits + ::value_type ParamType; + return internal::ParamGenerator( + new internal::ValuesInIteratorRangeGenerator(begin, end)); +} + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]) { + return ValuesIn(array, array + N); +} + +template +internal::ParamGenerator ValuesIn( + const Container& container) { + return ValuesIn(container.begin(), container.end()); +} + +// Values() allows generating tests from explicitly specified list of +// parameters. +// +// Synopsis: +// Values(T v1, T v2, ..., T vN) +// - returns a generator producing sequences with elements v1, v2, ..., vN. +// +// For example, this instantiates tests from test case BarTest each +// with values "one", "two", and "three": +// +// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// +// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// The exact type of values will depend on the type of parameter in BazTest. +// +// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// +// Currently, Values() supports from 1 to 50 parameters. +// +template +internal::ValueArray1 Values(T1 v1) { + return internal::ValueArray1(v1); +} + +template +internal::ValueArray2 Values(T1 v1, T2 v2) { + return internal::ValueArray2(v1, v2); +} + +template +internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { + return internal::ValueArray3(v1, v2, v3); +} + +template +internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { + return internal::ValueArray4(v1, v2, v3, v4); +} + +template +internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5) { + return internal::ValueArray5(v1, v2, v3, v4, v5); +} + +template +internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6) { + return internal::ValueArray6(v1, v2, v3, v4, v5, v6); +} + +template +internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7) { + return internal::ValueArray7(v1, v2, v3, v4, v5, + v6, v7); +} + +template +internal::ValueArray8 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { + return internal::ValueArray8(v1, v2, v3, v4, + v5, v6, v7, v8); +} + +template +internal::ValueArray9 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { + return internal::ValueArray9(v1, v2, v3, + v4, v5, v6, v7, v8, v9); +} + +template +internal::ValueArray10 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { + return internal::ValueArray10(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10); +} + +template +internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) { + return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); +} + +template +internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) { + return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); +} + +template +internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) { + return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); +} + +template +internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { + return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14); +} + +template +internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { + return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15); +} + +template +internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16) { + return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16); +} + +template +internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17) { + return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17); +} + +template +internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18) { + return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18); +} + +template +internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { + return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); +} + +template +internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { + return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); +} + +template +internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { + return internal::ValueArray21(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); +} + +template +internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22) { + return internal::ValueArray22(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22); +} + +template +internal::ValueArray23 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23) { + return internal::ValueArray23(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23); +} + +template +internal::ValueArray24 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24) { + return internal::ValueArray24(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24); +} + +template +internal::ValueArray25 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { + return internal::ValueArray25(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25); +} + +template +internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) { + return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); +} + +template +internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) { + return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); +} + +template +internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) { + return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28); +} + +template +internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) { + return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29); +} + +template +internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { + return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30); +} + +template +internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { + return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31); +} + +template +internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32) { + return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32); +} + +template +internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33) { + return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); +} + +template +internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34) { + return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); +} + +template +internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { + return internal::ValueArray35(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); +} + +template +internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { + return internal::ValueArray36(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36); +} + +template +internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37) { + return internal::ValueArray37(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37); +} + +template +internal::ValueArray38 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38) { + return internal::ValueArray38(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, + v33, v34, v35, v36, v37, v38); +} + +template +internal::ValueArray39 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38, T39 v39) { + return internal::ValueArray39(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + v32, v33, v34, v35, v36, v37, v38, v39); +} + +template +internal::ValueArray40 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, + T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, + T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { + return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, + v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); +} + +template +internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { + return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); +} + +template +internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) { + return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, + v42); +} + +template +internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) { + return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, + v41, v42, v43); +} + +template +internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) { + return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, + v40, v41, v42, v43, v44); +} + +template +internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { + return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, + v39, v40, v41, v42, v43, v44, v45); +} + +template +internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { + return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46); +} + +template +internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { + return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); +} + +template +internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, + T48 v48) { + return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, + v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); +} + +template +internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, + T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, + T47 v47, T48 v48, T49 v49) { + return internal::ValueArray49(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, + v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); +} + +template +internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, + T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, + T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { + return internal::ValueArray50(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, + v48, v49, v50); +} + +// Bool() allows generating tests with parameters in a set of (false, true). +// +// Synopsis: +// Bool() +// - returns a generator producing sequences with elements {false, true}. +// +// It is useful when testing code that depends on Boolean flags. Combinations +// of multiple flags can be tested when several Bool()'s are combined using +// Combine() function. +// +// In the following example all tests in the test case FlagDependentTest +// will be instantiated twice with parameters false and true. +// +// class FlagDependentTest : public testing::TestWithParam { +// virtual void SetUp() { +// external_flag = GetParam(); +// } +// } +// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); +// +inline internal::ParamGenerator Bool() { + return Values(false, true); +} + +# if GTEST_HAS_COMBINE +// Combine() allows the user to combine two or more sequences to produce +// values of a Cartesian product of those sequences' elements. +// +// Synopsis: +// Combine(gen1, gen2, ..., genN) +// - returns a generator producing sequences with elements coming from +// the Cartesian product of elements from the sequences generated by +// gen1, gen2, ..., genN. The sequence elements will have a type of +// tuple where T1, T2, ..., TN are the types +// of elements from sequences produces by gen1, gen2, ..., genN. +// +// Combine can have up to 10 arguments. This number is currently limited +// by the maximum number of elements in the tuple implementation used by Google +// Test. +// +// Example: +// +// This will instantiate tests in test case AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// class AnimalTest +// : public testing::TestWithParam > {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); +// +// This will instantiate tests in FlagDependentTest with all variations of two +// Boolean flags: +// +// class FlagDependentTest +// : public testing::TestWithParam > { +// virtual void SetUp() { +// // Assigns external_flag_1 and external_flag_2 values from the tuple. +// tie(external_flag_1, external_flag_2) = GetParam(); +// } +// }; +// +// TEST_P(FlagDependentTest, TestFeature1) { +// // Test your code using external_flag_1 and external_flag_2 here. +// } +// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder2 Combine( + const Generator1& g1, const Generator2& g2) { + return internal::CartesianProductHolder2( + g1, g2); +} + +template +internal::CartesianProductHolder3 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3) { + return internal::CartesianProductHolder3( + g1, g2, g3); +} + +template +internal::CartesianProductHolder4 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4) { + return internal::CartesianProductHolder4( + g1, g2, g3, g4); +} + +template +internal::CartesianProductHolder5 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5) { + return internal::CartesianProductHolder5( + g1, g2, g3, g4, g5); +} + +template +internal::CartesianProductHolder6 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6) { + return internal::CartesianProductHolder6( + g1, g2, g3, g4, g5, g6); +} + +template +internal::CartesianProductHolder7 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7) { + return internal::CartesianProductHolder7( + g1, g2, g3, g4, g5, g6, g7); +} + +template +internal::CartesianProductHolder8 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8) { + return internal::CartesianProductHolder8( + g1, g2, g3, g4, g5, g6, g7, g8); +} + +template +internal::CartesianProductHolder9 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9) { + return internal::CartesianProductHolder9( + g1, g2, g3, g4, g5, g6, g7, g8, g9); +} + +template +internal::CartesianProductHolder10 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9, + const Generator10& g10) { + return internal::CartesianProductHolder10( + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); +} +# endif // GTEST_HAS_COMBINE + + + +# define TEST_P(test_case_name, test_name) \ + class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + : public test_case_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ + virtual void TestBody(); \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ + #test_case_name, \ + #test_name, \ + new ::testing::internal::TestMetaFactory< \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ + return 0; \ + } \ + static int gtest_registering_dummy_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_case_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + ::testing::internal::ParamGenerator \ + gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ + int gtest_##prefix##test_case_name##_dummy_ = \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ + #prefix, \ + >est_##prefix##test_case_name##_EvalGenerator_, \ + __FILE__, __LINE__) + +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +// Copyright 2006, 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++ Testing Framework definitions useful in production code. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// When you need to test the private or protected members of a class, +// use the FRIEND_TEST macro to declare your tests as friends of the +// class. For example: +// +// class MyClass { +// private: +// void MyMethod(); +// FRIEND_TEST(MyClassTest, MyMethod); +// }; +// +// class MyClassTest : public testing::Test { +// // ... +// }; +// +// TEST_F(MyClassTest, MyMethod) { +// // Can call MyClass::MyMethod() here. +// } + +#define FRIEND_TEST(test_case_name, test_name)\ +friend class test_case_name##_##test_name##_Test + +#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +// 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: mheule@google.com (Markus Heule) +// + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ + +#include +#include + +namespace testing { + +// A copyable object representing the result of a test part (i.e. an +// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). +// +// Don't inherit from TestPartResult as its destructor is not virtual. +class GTEST_API_ TestPartResult { + public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + + // C'tor. TestPartResult does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestPartResult object. + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name == NULL ? "" : a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { + } + + // Gets the outcome of the test part. + Type type() const { return type_; } + + // Gets the name of the source file where the test part took place, or + // NULL if it's unknown. + const char* file_name() const { + return file_name_.empty() ? NULL : file_name_.c_str(); + } + + // Gets the line in the source file where the test part took place, + // or -1 if it's unknown. + int line_number() const { return line_number_; } + + // Gets the summary of the failure message. + const char* summary() const { return summary_.c_str(); } + + // Gets the message associated with the test part. + const char* message() const { return message_.c_str(); } + + // Returns true iff the test part passed. + bool passed() const { return type_ == kSuccess; } + + // Returns true iff the test part failed. + bool failed() const { return type_ != kSuccess; } + + // Returns true iff the test part non-fatally failed. + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } + + // Returns true iff the test part fatally failed. + bool fatally_failed() const { return type_ == kFatalFailure; } + + private: + Type type_; + + // Gets the summary of the failure message by omitting the stack + // trace in it. + static std::string ExtractSummary(const char* message); + + // The name of the source file where the test part took place, or + // "" if the source file is unknown. + std::string file_name_; + // The line in the source file where the test part took place, or -1 + // if the line number is unknown. + int line_number_; + std::string summary_; // The test failure summary. + std::string message_; // The test failure message. +}; + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result); + +// An array of TestPartResult objects. +// +// Don't inherit from TestPartResultArray as its destructor is not +// virtual. +class GTEST_API_ TestPartResultArray { + public: + TestPartResultArray() {} + + // Appends the given TestPartResult to the array. + void Append(const TestPartResult& result); + + // Returns the TestPartResult at the given index (0-based). + const TestPartResult& GetTestPartResult(int index) const; + + // Returns the number of TestPartResult objects in the array. + int size() const; + + private: + std::vector array_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); +}; + +// This interface knows how to report a test part result. +class TestPartResultReporterInterface { + public: + virtual ~TestPartResultReporterInterface() {} + + virtual void ReportTestPartResult(const TestPartResult& result) = 0; +}; + +namespace internal { + +// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a +// statement generates new fatal failures. To do so it registers itself as the +// current test part result reporter. Besides checking if fatal failures were +// reported, it only delegates the reporting to the former result reporter. +// The original result reporter is restored in the destructor. +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { + public: + HasNewFatalFailureHelper(); + virtual ~HasNewFatalFailureHelper(); + virtual void ReportTestPartResult(const TestPartResult& result); + bool has_new_fatal_failure() const { return has_new_fatal_failure_; } + private: + bool has_new_fatal_failure_; + TestPartResultReporterInterface* original_reporter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); +}; + +} // namespace internal + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +// 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) + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// This header implements typed tests and type-parameterized tests. + +// Typed (aka type-driven) tests repeat the same test for types in a +// list. You must know which types you want to test with when writing +// typed tests. Here's how you do it: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + public: + ... + typedef std::list List; + static T shared_; + T value_; +}; + +// Next, associate a list of types with the test case, which will be +// repeated for each type in the list. The typedef is necessary for +// the macro to parse correctly. +typedef testing::Types MyTypes; +TYPED_TEST_CASE(FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// TYPED_TEST_CASE(FooTest, int); + +// Then, use TYPED_TEST() instead of TEST_F() to define as many typed +// tests for this test case as you want. +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + // Since we are inside a derived class template, C++ requires use to + // visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the TestFixture:: + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the "typename + // TestFixture::" prefix. + typename TestFixture::List values; + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } + +#endif // 0 + +// Type-parameterized tests are abstract test patterns parameterized +// by a type. Compared with typed tests, type-parameterized tests +// allow you to define the test pattern without knowing what the type +// parameters are. The defined pattern can be instantiated with +// different types any number of times, in any number of translation +// units. +// +// If you are designing an interface or concept, you can define a +// suite of type-parameterized tests to verify properties that any +// valid implementation of the interface/concept should have. Then, +// each implementation can easily instantiate the test suite to verify +// that it conforms to the requirements, without having to write +// similar tests repeatedly. Here's an example: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + ... +}; + +// Next, declare that you will define a type-parameterized test case +// (the _P suffix is for "parameterized" or "pattern", whichever you +// prefer): +TYPED_TEST_CASE_P(FooTest); + +// Then, use TYPED_TEST_P() to define as many type-parameterized tests +// for this type-parameterized test case as you want. +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } + +// Now the tricky part: you need to register all test patterns before +// you can instantiate them. The first argument of the macro is the +// test case name; the rest are the names of the tests in this test +// case. +REGISTER_TYPED_TEST_CASE_P(FooTest, + DoesBlah, HasPropertyA); + +// Finally, you are free to instantiate the pattern with the types you +// want. If you put the above code in a header file, you can #include +// it in multiple C++ source files and instantiate it multiple times. +// +// To distinguish different instances of the pattern, the first +// argument to the INSTANTIATE_* macro is a prefix that will be added +// to the actual test case name. Remember to pick unique prefixes for +// different instances. +typedef testing::Types MyTypes; +INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); + +#endif // 0 + + +// Implements typed tests. + +#if GTEST_HAS_TYPED_TEST + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the typedef for the type parameters of the +// given test case. +# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define TYPED_TEST_CASE(CaseName, Types) \ + typedef ::testing::internal::TypeList< Types >::type \ + GTEST_TYPE_PARAMS_(CaseName) + +# define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel< \ + GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ + GTEST_TYPE_PARAMS_(CaseName)>::Register(\ + "", #CaseName, #TestName, 0); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() + +#endif // GTEST_HAS_TYPED_TEST + +// Implements type-parameterized tests. + +#if GTEST_HAS_TYPED_TEST_P + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the namespace name that the type-parameterized tests for +// the given type-parameterized test case are defined in. The exact +// name of the namespace is subject to change without notice. +# define GTEST_CASE_NAMESPACE_(TestCaseName) \ + gtest_case_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the variable used to remember the names of +// the defined tests in the given test case. +# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ + gtest_typed_test_case_p_state_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. +// +// Expands to the name of the variable used to remember the names of +// the registered tests in the given test case. +# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ + gtest_registered_test_names_##TestCaseName##_ + +// The variables defined in the type-parameterized test macros are +// static as typically these macros are used in a .h file that can be +// #included in multiple translation units linked together. +# define TYPED_TEST_CASE_P(CaseName) \ + static ::testing::internal::TypedTestCasePState \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) + +# define TYPED_TEST_P(CaseName, TestName) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + template \ + class TestName : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ + __FILE__, __LINE__, #CaseName, #TestName); \ + } \ + template \ + void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() + +# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ + __FILE__, __LINE__, #__VA_ARGS__) + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ + bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestCase::type>::Register(\ + #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) + +#endif // GTEST_HAS_TYPED_TEST_P + +#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// Depending on the platform, different string classes are available. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. +// +// If the user's ::std::string and ::string are the same class due to +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. +// +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. + +namespace testing { + +// Declares the flags. + +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); + +// This flag controls whether Google Test includes Google Test internal +// stack frames in failure stack traces. +GTEST_DECLARE_bool_(show_internal_stack_frames); + +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// When this flag is set with a "host:port" string, on supported +// platforms test results are streamed to the specified port on +// the specified host machine. +GTEST_DECLARE_string_(stream_result_to); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + +namespace internal { + +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; +class GTestFlagSaver; +class StreamingListenerTest; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class UnitTestRecordPropertyTestHelper; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message); + +} // namespace internal + +// The friend relationship of some of these classes is cyclic. +// If we don't forward declare them the compiler might confuse the classes +// in friendship clauses with same named classes on the scope. +class Test; +class TestCase; +class TestInfo; +class UnitTest; + +// A class for indicating whether an assertion was successful. When +// the assertion wasn't successful, the AssertionResult object +// remembers a non-empty message that describes how it failed. +// +// To create an instance of this class, use one of the factory functions +// (AssertionSuccess() and AssertionFailure()). +// +// This class is useful for two purposes: +// 1. Defining predicate functions to be used with Boolean test assertions +// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts +// 2. Defining predicate-format functions to be +// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). +// +// For example, if you define IsEven predicate: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) +// will print the message +// +// Value of: IsEven(Fib(5)) +// Actual: false (5 is odd) +// Expected: true +// +// instead of a more opaque +// +// Value of: IsEven(Fib(5)) +// Actual: false +// Expected: true +// +// in case IsEven is a simple Boolean predicate. +// +// If you expect your predicate to be reused and want to support informative +// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up +// about half as often as positive ones in our tests), supply messages for +// both success and failure cases: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess() << n << " is even"; +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print +// +// Value of: IsEven(Fib(6)) +// Actual: true (8 is even) +// Expected: false +// +// NB: Predicates that support negative Boolean assertions have reduced +// performance in positive ones so be careful not to use them in tests +// that have lots (tens of thousands) of positive Boolean assertions. +// +// To use this class with EXPECT_PRED_FORMAT assertions such as: +// +// // Verifies that Foo() returns an even number. +// EXPECT_PRED_FORMAT1(IsEven, Foo()); +// +// you need to define: +// +// testing::AssertionResult IsEven(const char* expr, int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() +// << "Expected: " << expr << " is even\n Actual: it's " << n; +// } +// +// If Foo() returns 5, you will see the following message: +// +// Expected: Foo() is even +// Actual: it's 5 +// +class GTEST_API_ AssertionResult { + public: + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} + + // Returns true iff the assertion succeeded. + operator bool() const { return success_; } // NOLINT + + // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. + AssertionResult operator!() const; + + // Returns the text streamed into this AssertionResult. Test assertions + // use it when they fail (i.e., the predicate's outcome doesn't match the + // assertion's expectation). When nothing has been streamed into the + // object, returns an empty string. + const char* message() const { + return message_.get() != NULL ? message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } + + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value) { + AppendMessage(Message() << value); + return *this; + } + + // Allows streaming basic output manipulators such as endl or flush into + // this object. + AssertionResult& operator<<( + ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { + AppendMessage(Message() << basic_manipulator); + return *this; + } + + private: + // Appends the contents of message to message_. + void AppendMessage(const Message& a_message) { + if (message_.get() == NULL) + message_.reset(new ::std::string); + message_->append(a_message.GetString().c_str()); + } + + // Stores result of the assertion predicate. + bool success_; + // Stores the message describing the condition in case the expectation + // construct is not satisfied with the predicate's outcome. + // Referenced via a pointer to avoid taking too much stack frame space + // with test assertions. + internal::scoped_ptr< ::std::string> message_; + + GTEST_DISALLOW_ASSIGN_(AssertionResult); +}; + +// Makes a successful assertion result. +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); + +// The abstract class that all tests inherit from. +// +// In Google Test, a unit test program contains one or many TestCases, and +// each TestCase contains one or many Tests. +// +// When you define a test using the TEST macro, you don't need to +// explicitly derive from Test - the TEST macro automatically does +// this for you. +// +// The only time you derive from Test is when defining a test fixture +// to be used a TEST_F. For example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { ... } +// virtual void TearDown() { ... } +// ... +// }; +// +// TEST_F(FooTest, Bar) { ... } +// TEST_F(FooTest, Baz) { ... } +// +// Test is not copyable. +class GTEST_API_ Test { + public: + friend class TestInfo; + + // Defines types for pointers to functions that set up and tear down + // a test case. + typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; + typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; + + // The d'tor is virtual as we intend to inherit from Test. + virtual ~Test(); + + // Sets up the stuff shared by all tests in this test case. + // + // Google Test will call Foo::SetUpTestCase() before running the first + // test in test case Foo. Hence a sub-class can define its own + // SetUpTestCase() method to shadow the one defined in the super + // class. + static void SetUpTestCase() {} + + // Tears down the stuff shared by all tests in this test case. + // + // Google Test will call Foo::TearDownTestCase() after running the last + // test in test case Foo. Hence a sub-class can define its own + // TearDownTestCase() method to shadow the one defined in the super + // class. + static void TearDownTestCase() {} + + // Returns true iff the current test has a fatal failure. + static bool HasFatalFailure(); + + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + + // Logs a property for the current test, test case, or for the entire + // invocation of the test program when used outside of the context of a + // test case. Only the last value for a given key is remembered. These + // are public static so they can be called from utility functions that are + // not members of the test fixture. Calls to RecordProperty made during + // lifespan of the test (from the moment its constructor starts to the + // moment its destructor finishes) will be output in XML as attributes of + // the element. Properties recorded from fixture's + // SetUpTestCase or TearDownTestCase are logged as attributes of the + // corresponding element. Calls to RecordProperty made in the + // global context (before or after invocation of RUN_ALL_TESTS and from + // SetUp/TearDown method of Environment objects registered with Google + // Test) will be output as attributes of the element. + static void RecordProperty(const std::string& key, const std::string& value); + static void RecordProperty(const std::string& key, int value); + + protected: + // Creates a Test object. + Test(); + + // Sets up the test fixture. + virtual void SetUp(); + + // Tears down the test fixture. + virtual void TearDown(); + + private: + // Returns true iff the current test has the same fixture class as + // the first test in the current test case. + static bool HasSameFixtureClass(); + + // Runs the test after the test fixture has been set up. + // + // A sub-class must implement this to define the test logic. + // + // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. + // Instead, use the TEST or TEST_F macro. + virtual void TestBody() = 0; + + // Sets up, executes, and tears down the test. + void Run(); + + // Deletes self. We deliberately pick an unusual name for this + // internal method to avoid clashing with names used in user TESTs. + void DeleteSelf_() { delete this; } + + // Uses a GTestFlagSaver to save and restore all Google Test flags. + const internal::GTestFlagSaver* const gtest_flag_saver_; + + // Often a user mis-spells SetUp() as Setup() and spends a long time + // wondering why it is never called by Google Test. The declaration of + // the following method is solely for catching such an error at + // compile time: + // + // - The return type is deliberately chosen to be not void, so it + // will be a conflict if a user declares void Setup() in his test + // fixture. + // + // - This method is private, so it will be another compiler error + // if a user calls it from his test fixture. + // + // DO NOT OVERRIDE THIS FUNCTION. + // + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + + // We disallow copying Tests. + GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); +}; + +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const std::string& a_key, const std::string& a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const std::string& new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + std::string key_; + // The value supplied by the user. + std::string value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class TestCase; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. xml_element specifies the element for which the property is being + // recorded and is used for validation. + void RecordProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector test_part_results_; + // The vector of TestProperties + std::vector test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult + +// A TestInfo object stores the following information about a test: +// +// Test case name +// Test name +// Whether the test should be run +// A function pointer that creates the test object when invoked +// Test result +// +// The constructor of TestInfo registers itself with the UnitTest +// singleton such that the RUN_ALL_TESTS() macro knows which tests to +// run. +class GTEST_API_ TestInfo { + public: + // Destructs a TestInfo object. This function is not virtual, so + // don't inherit from TestInfo. + ~TestInfo(); + + // Returns the test case name. + const char* test_case_name() const { return test_case_name_.c_str(); } + + // Returns the test name. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a typed + // or a type-parameterized test. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns the text representation of the value parameter, or NULL if this + // is not a value-parameterized test. + const char* value_param() const { + if (value_param_.get() != NULL) + return value_param_->c_str(); + return NULL; + } + + // Returns true if this test should run, that is if the test is not + // disabled (or it is disabled but the also_run_disabled_tests flag has + // been specified) and its full name matches the user-specified filter. + // + // Google Test allows the user to filter the tests by their full names. + // The full name of a test Bar in test case Foo is defined as + // "Foo.Bar". Only the tests that match the filter will run. + // + // A filter is a colon-separated list of glob (not regex) patterns, + // optionally followed by a '-' and a colon-separated list of + // negative patterns (tests to exclude). A test is run if it + // matches one of the positive patterns and does not match any of + // the negative patterns. + // + // For example, *A*:Foo.* is a filter that matches any string that + // contains the character 'A' or starts with "Foo.". + bool should_run() const { return should_run_; } + + // Returns true iff this test will appear in the XML report. + bool is_reportable() const { + // For now, the XML report includes all tests matching the filter. + // In the future, we may trim tests that are excluded because of + // sharding. + return matches_filter_; + } + + // Returns the result of the test. + const TestResult* result() const { return &result_; } + + private: +#if GTEST_HAS_DEATH_TEST + friend class internal::DefaultDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + friend class Test; + friend class TestCase; + friend class internal::UnitTestImpl; + friend class internal::StreamingListenerTest; + friend TestInfo* internal::MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + internal::TypeId fixture_class_id, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + internal::TestFactoryBase* factory); + + // Constructs a TestInfo object. The newly constructed instance assumes + // ownership of the factory object. + TestInfo(const std::string& test_case_name, + const std::string& name, + const char* a_type_param, // NULL if not a type-parameterized test + const char* a_value_param, // NULL if not a value-parameterized test + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); + + // Increments the number of death tests encountered in this test so + // far. + int increment_death_test_count() { + return result_.increment_death_test_count(); + } + + // Creates the test object, runs it, records its result, and then + // deletes it. + void Run(); + + static void ClearTestResult(TestInfo* test_info) { + test_info->result_.Clear(); + } + + // These fields are immutable properties of the test. + const std::string test_case_name_; // Test case name + const std::string name_; // Test name + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // Text representation of the value parameter, or NULL if this is not a + // value-parameterized test. + const internal::scoped_ptr value_param_; + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True iff this test should run + bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + internal::TestFactoryBase* const factory_; // The factory that creates + // the test object + + // This field is mutable and needs to be reset before running the + // test for the second time. + TestResult result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); +}; + +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // a_type_param: the name of the test's type parameter, or NULL if + // this is not a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a + // type-parameterized test case. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + // Returns the TestResult that holds test properties recorded during + // execution of SetUpTestCase and TearDownTestCase. + const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Runs SetUpTestCase() for this TestCase. This wrapper is needed + // for catching exceptions thrown from SetUpTestCase(). + void RunSetUpTestCase() { (*set_up_tc_)(); } + + // Runs TearDownTestCase() for this TestCase. This wrapper is + // needed for catching exceptions thrown from TearDownTestCase(). + void RunTearDownTestCase() { (*tear_down_tc_)(); } + + // Returns true iff test passed. + static bool TestPassed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Passed(); + } + + // Returns true iff test failed. + static bool TestFailed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Failed(); + } + + // Returns true iff the test is disabled and will be reported in the XML + // report. + static bool TestReportableDisabled(const TestInfo* test_info) { + return test_info->is_reportable() && test_info->is_disabled_; + } + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo* test_info) { + return test_info->is_disabled_; + } + + // Returns true iff this test will appear in the XML report. + static bool TestReportable(const TestInfo* test_info) { + return test_info->is_reportable(); + } + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo* test_info) { + return test_info->should_run(); + } + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + std::string name_; + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + // Holds test properties recorded during execution of SetUpTestCase and + // TearDownTestCase. + TestResult ad_hoc_test_result_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + +// An Environment object is capable of setting up and tearing down an +// environment. The user should subclass this to define his own +// environment(s). +// +// An Environment object does the set-up and tear-down in virtual +// methods SetUp() and TearDown() instead of the constructor and the +// destructor, as: +// +// 1. You cannot safely throw from a destructor. This is a problem +// as in some cases Google Test is used where exceptions are enabled, and +// we may want to implement ASSERT_* using exceptions where they are +// available. +// 2. You cannot use ASSERT_* directly in a constructor or +// destructor. +class Environment { + public: + // The d'tor is virtual as we need to subclass Environment. + virtual ~Environment() {} + + // Override this to define how to set up the environment. + virtual void SetUp() {} + + // Override this to define how to tear down the environment. + virtual void TearDown() {} + private: + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } +}; + +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class TestInfo; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. +// +// This is a singleton class. The only instance of UnitTest is +// created when UnitTest::GetInstance() is first called. This +// instance is never deleted. +// +// UnitTest is not copyable. +// +// This class is thread-safe as long as the methods are called +// according to their specification. +class GTEST_API_ UnitTest { + public: + // Gets the singleton UnitTest object. The first time this method + // is called, a UnitTest object is constructed and returned. + // Consecutive calls will return the same object. + static UnitTest* GetInstance(); + + // Runs all tests in this UnitTest object and prints the result. + // Returns 0 if successful, or 1 otherwise. + // + // This method can only be called from the main thread. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + int Run() GTEST_MUST_USE_RESULT_; + + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + + // Returns the TestCase object for the test that's currently running, + // or NULL if no test is running. + const TestCase* current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the TestInfo object for the test that's currently running, + // or NULL if no test is running. + const TestInfo* current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST + // Returns the ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_); +#endif // GTEST_HAS_PARAM_TEST + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the TestResult containing information on test failures and + // properties logged outside of individual test cases. + const TestResult& ad_hoc_test_result() const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Adds a TestProperty to the current TestResult object when invoked from + // inside a test, to current TestCase's ad_hoc_test_result_ when invoked + // from SetUpTestCase or TearDownTestCase, or to the global property set + // when invoked elsewhere. If the result already contains a property with + // the same key, the value will be updated. + void RecordProperty(const std::string& key, const std::string& value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + + // Accessors for the implementation object. + internal::UnitTestImpl* impl() { return impl_; } + const internal::UnitTestImpl* impl() const { return impl_; } + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; + friend class internal::ScopedTrace; + friend class internal::StreamingListenerTest; + friend class internal::UnitTestRecordPropertyTestHelper; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const std::string& message); + + // Creates an empty UnitTest. + UnitTest(); + + // D'tor + virtual ~UnitTest(); + + // Pushes a trace defined by SCOPED_TRACE() on to the per-thread + // Google Test trace stack. + void PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Pops a trace from the per-thread Google Test trace stack. + void PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_); + + // Protects mutable state in *impl_. This is mutable as some const + // methods need to lock it too. + mutable internal::Mutex mutex_; + + // Opaque implementation object. This field is never changed once + // the object is constructed. We don't mark it as const here, as + // doing so will cause a warning in the constructor of UnitTest. + // Mutable state in *impl_ is protected by mutex_. + internal::UnitTestImpl* impl_; + + // We disallow copying UnitTest. + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); +}; + +// A convenient wrapper for adding an environment for the test +// program. +// +// You should call this before RUN_ALL_TESTS() is called, probably in +// main(). If you use gtest_main, you need to call this before main() +// starts for it to take effect. For example, you can define a global +// variable like this: +// +// testing::Environment* const foo_env = +// testing::AddGlobalTestEnvironment(new FooEnvironment); +// +// However, we strongly recommend you to write your own main() and +// call AddGlobalTestEnvironment() there, as relying on initialization +// of global variables makes the code harder to read and may cause +// problems when you register multiple environments from different +// translation units and the environments have dependencies among them +// (remember that the compiler doesn't guarantee the order in which +// global variables from different translation units are initialized). +inline Environment* AddGlobalTestEnvironment(Environment* env) { + return UnitTest::GetInstance()->AddEnvironment(env); +} + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +GTEST_API_ void InitGoogleTest(int* argc, char** argv); + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); + +namespace internal { + +// FormatForComparison::Format(value) formats a +// value of type ToPrint that is an operand of a comparison assertion +// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in +// the comparison, and is used to help determine the best way to +// format the value. In particular, when the value is a C string +// (char pointer) and the other operand is an STL string object, we +// want to format the C string as a string, since we know it is +// compared by value with the string object. If the value is a char +// pointer but the other operand is not an STL string object, we don't +// know whether the pointer is supposed to point to a NUL-terminated +// string, and thus want to print it as a pointer to be safe. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// The default case. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint& value) { + return ::testing::PrintToString(value); + } +}; + +// Array. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint* value) { + return FormatForComparison::Format(value); + } +}; + +// By default, print C string as pointers to be safe, as we don't know +// whether they actually point to a NUL-terminated string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \ + template \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(static_cast(value)); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ + +// If a C string is compared with an STL string object, we know it's meant +// to point to a NUL-terminated string, and thus can print it as a string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ + template <> \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(value); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); + +#if GTEST_HAS_GLOBAL_STRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string); +#endif + +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring); +#endif + +#if GTEST_HAS_STD_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); +#endif + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ + +// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) +// operand to be used in a failure message. The type (but not value) +// of the other operand may affect the format. This allows us to +// print a char* as a raw pointer when it is compared against another +// char* or void*, and print it as a C string when it is compared +// against an std::string object, for example. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +std::string FormatForComparisonFailureMessage( + const T1& value, const T2& /* other_operand */) { + return FormatForComparison::Format(value); +} + +// The helper function for {ASSERT|EXPECT}_EQ. +template +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { +#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) { + return AssertionSuccess(); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// With this overloaded version, we allow anonymous enums to be used +// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums +// can be implicitly cast to BiggestInt. +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); + +// The helper class for {ASSERT|EXPECT}_EQ. The template argument +// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() +// is a null pointer literal. The following default implementation is +// for lhs_is_null_literal being false. +template +class EqHelper { + public: + // This templatized version is for the general case. + template + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // With this overloaded version, we allow anonymous enums to be used + // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous + // enums can be implicitly cast to BiggestInt. + // + // Even though its body looks the same as the above version, we + // cannot merge the two, as it will make anonymous enums unhappy. + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } +}; + +// This specialization is used when the first argument to ASSERT_EQ() +// is a null pointer literal, like NULL, false, or 0. +template <> +class EqHelper { + public: + // We define two overloaded versions of Compare(). The first + // version will be picked when the second argument to ASSERT_EQ() is + // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or + // EXPECT_EQ(false, a_bool). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual, + // The following line prevents this overload from being considered if T2 + // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) + // expands to Compare("", "", NULL, my_ptr), which requires a conversion + // to match the Secret* in the other overload, which would otherwise make + // this template match better. + typename EnableIf::value>::type* = 0) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // This version will be picked when the second argument to ASSERT_EQ() is a + // pointer, e.g. ASSERT_EQ(NULL, a_pointer). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + // We used to have a second template parameter instead of Secret*. That + // template parameter would deduce to 'long', making this a better match + // than the first overload even without the first overload's EnableIf. + // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to + // non-pointer argument" (even a deduced integral argument), so the old + // implementation caused warnings in user code. + Secret* /* expected (NULL) */, + T* actual) { + // We already know that 'expected' is a null pointer. + return CmpHelperEQ(expected_expression, actual_expression, + static_cast(NULL), actual); + } +}; + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste +// of similar code. +// +// For each templatized helper function, we also define an overloaded +// version for BiggestInt in order to reduce code bloat and allow +// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled +// with gcc 4. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +template \ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + const T1& val1, const T2& val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +}\ +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) + +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// Implements the helper function for {ASSERT|EXPECT}_NE +GTEST_IMPL_CMP_HELPER_(NE, !=); +// Implements the helper function for {ASSERT|EXPECT}_LE +GTEST_IMPL_CMP_HELPER_(LE, <=); +// Implements the helper function for {ASSERT|EXPECT}_LT +GTEST_IMPL_CMP_HELPER_(LT, <); +// Implements the helper function for {ASSERT|EXPECT}_GE +GTEST_IMPL_CMP_HELPER_(GE, >=); +// Implements the helper function for {ASSERT|EXPECT}_GT +GTEST_IMPL_CMP_HELPER_(GT, >); + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRNE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + + +// Helper function for *_STREQ on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); + +// Helper function for *_STRNE on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); + +} // namespace internal + +// IsSubstring() and IsNotSubstring() are intended to be used as the +// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by +// themselves. They check whether needle is a substring of haystack +// (NULL is considered a substring of itself only), and return an +// appropriate error message when they fail. +// +// The {needle,haystack}_expr arguments are the stringified +// expressions that generated the two real arguments. +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +// Helper template function for comparing floating-points. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, + const char* actual_expression, + RawType expected, + RawType actual) { + const FloatingPoint lhs(expected), rhs(actual); + + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + ::std::stringstream expected_ss; + expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << expected; + + ::std::stringstream actual_ss; + actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << actual; + + return EqFailure(expected_expression, + actual_expression, + StringStreamToString(&expected_ss), + StringStreamToString(&actual_ss), + false); +} + +// Helper function for implementing ASSERT_NEAR. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// A class that enables one to stream messages to assertion macros +class GTEST_API_ AssertHelper { + public: + // Constructor. + AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message); + ~AssertHelper(); + + // Message assignment is a semantic trick to enable assertion + // streaming; see the GTEST_MESSAGE_ macro below. + void operator=(const Message& message) const; + + private: + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + std::string const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); +}; + +} // namespace internal + +#if GTEST_HAS_PARAM_TEST +// The pure interface class that all value-parameterized tests inherit from. +// A value-parameterized class must inherit from both ::testing::Test and +// ::testing::WithParamInterface. In most cases that just means inheriting +// from ::testing::TestWithParam, but more complicated test hierarchies +// may need to inherit from Test and WithParamInterface at different levels. +// +// This interface has support for accessing the test parameter value via +// the GetParam() method. +// +// Use it with one of the parameter generator defining functions, like Range(), +// Values(), ValuesIn(), Bool(), and Combine(). +// +// class FooTest : public ::testing::TestWithParam { +// protected: +// FooTest() { +// // Can use GetParam() here. +// } +// virtual ~FooTest() { +// // Can use GetParam() here. +// } +// virtual void SetUp() { +// // Can use GetParam() here. +// } +// virtual void TearDown { +// // Can use GetParam() here. +// } +// }; +// TEST_P(FooTest, DoesBar) { +// // Can use GetParam() method here. +// Foo foo; +// ASSERT_TRUE(foo.DoesBar(GetParam())); +// } +// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); + +template +class WithParamInterface { + public: + typedef T ParamType; + virtual ~WithParamInterface() {} + + // The current parameter value. Is also available in the test fixture's + // constructor. This member function is non-static, even though it only + // references static data, to reduce the opportunity for incorrect uses + // like writing 'WithParamInterface::GetParam()' for a test that + // uses a fixture whose parameter type is int. + const ParamType& GetParam() const { + GTEST_CHECK_(parameter_ != NULL) + << "GetParam() can only be called inside a value-parameterized test " + << "-- did you intend to write TEST_P instead of TEST_F?"; + return *parameter_; + } + + private: + // Sets parameter value. The caller is responsible for making sure the value + // remains alive and unchanged throughout the current test. + static void SetParam(const ParamType* parameter) { + parameter_ = parameter; + } + + // Static value used for accessing parameter during a test lifetime. + static const ParamType* parameter_; + + // TestClass must be a subclass of WithParamInterface and Test. + template friend class internal::ParameterizedTestFactory; +}; + +template +const T* WithParamInterface::parameter_ = NULL; + +// Most value-parameterized classes can ignore the existence of +// WithParamInterface, and can just inherit from ::testing::TestWithParam. + +template +class TestWithParam : public Test, public WithParamInterface { +}; + +#endif // GTEST_HAS_PARAM_TEST + +// Macros for indicating success/failure in test code. + +// ADD_FAILURE unconditionally adds a failure to the current test. +// SUCCEED generates a success - it doesn't automatically make the +// current test successful, as a test is only successful when it has +// no failure. +// +// EXPECT_* verifies that a certain condition is satisfied. If not, +// it behaves like ADD_FAILURE. In particular: +// +// EXPECT_TRUE verifies that a Boolean condition is true. +// EXPECT_FALSE verifies that a Boolean condition is false. +// +// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except +// that they will also abort the current function on failure. People +// usually want the fail-fast behavior of FAIL and ASSERT_*, but those +// writing data-driven tests often find themselves using ADD_FAILURE +// and EXPECT_* more. + +// Generates a nonfatal failure with a generic message. +#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") + +// Generates a nonfatal failure at the given source file location with +// a generic message. +#define ADD_FAILURE_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kNonFatalFailure) + +// Generates a fatal failure with a generic message. +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +# define FAIL() GTEST_FAIL() +#endif + +// Generates a success with a generic message. +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +# define SUCCEED() GTEST_SUCCEED() +#endif + +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) + +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. +#define EXPECT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_NONFATAL_FAILURE_) +#define EXPECT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_NONFATAL_FAILURE_) +#define ASSERT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_FATAL_FAILURE_) +#define ASSERT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_FATAL_FAILURE_) + +// Includes the auto-generated header that implements a family of +// generic predicate assertion macros. +// Copyright 2006, 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. + +// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command +// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! +// +// Implements a family of generic predicate assertion macros. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Makes sure this header is not included before gtest.h. +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ + +// This header implements a family of generic predicate assertion +// macros: +// +// ASSERT_PRED_FORMAT1(pred_format, v1) +// ASSERT_PRED_FORMAT2(pred_format, v1, v2) +// ... +// +// where pred_format is a function or functor that takes n (in the +// case of ASSERT_PRED_FORMATn) values and their source expression +// text, and returns a testing::AssertionResult. See the definition +// of ASSERT_EQ in gtest.h for an example. +// +// If you don't care about formatting, you can use the more +// restrictive version: +// +// ASSERT_PRED1(pred, v1) +// ASSERT_PRED2(pred, v1, v2) +// ... +// +// where pred is an n-ary function or functor that returns bool, +// and the values v1, v2, ..., must support the << operator for +// streaming to std::ostream. +// +// We also define the EXPECT_* variations. +// +// For now we only support predicates whose arity is at most 5. +// Please email googletestframework@googlegroups.com if you need +// support for higher arities. + +// GTEST_ASSERT_ is the basic statement to which all of the assertions +// in this file reduce. Don't use this in your code. + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar.failure_message()) + + +// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +template +AssertionResult AssertPred1Helper(const char* pred_text, + const char* e1, + Pred pred, + const T1& v1) { + if (pred(v1)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. +// Don't use this in your code. +#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, v1), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +#define GTEST_PRED1_(pred, v1, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ + #v1, \ + pred, \ + v1), on_failure) + +// Unary predicate assertion macros. +#define EXPECT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +template +AssertionResult AssertPred2Helper(const char* pred_text, + const char* e1, + const char* e2, + Pred pred, + const T1& v1, + const T2& v2) { + if (pred(v1, v2)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. +// Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +#define GTEST_PRED2_(pred, v1, v2, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ + #v1, \ + #v2, \ + pred, \ + v1, \ + v2), on_failure) + +// Binary predicate assertion macros. +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +template +AssertionResult AssertPred3Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3) { + if (pred(v1, v2, v3)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. +// Don't use this in your code. +#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + pred, \ + v1, \ + v2, \ + v3), on_failure) + +// Ternary predicate assertion macros. +#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +template +AssertionResult AssertPred4Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4) { + if (pred(v1, v2, v3, v4)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. +// Don't use this in your code. +#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4), on_failure) + +// 4-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +template +AssertionResult AssertPred5Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + const char* e5, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4, + const T5& v5) { + if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ", " + << e5 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4 + << "\n" << e5 << " evaluates to " << v5; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. +// Don't use this in your code. +#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + #v5, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4, \ + v5), on_failure) + +// 5-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) + + + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Macros for testing equalities and inequalities. +// +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// +// When they are not, Google Test prints both the tested expressions and +// their actual values. The values must be compatible built-in types, +// or you will get a compiler error. By "compatible" we mean that the +// values can be compared by the respective operator. +// +// Note: +// +// 1. It is possible to make a user-defined type work with +// {ASSERT|EXPECT}_??(), but that requires overloading the +// comparison operators and is thus discouraged by the Google C++ +// Usage Guide. Therefore, you are advised to use the +// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are +// equal. +// +// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on +// pointers (in particular, C strings). Therefore, if you use it +// with two C strings, you are testing how their locations in memory +// are related, not how their content is related. To compare two C +// strings by content, use {ASSERT|EXPECT}_STR*(). +// +// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to +// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you +// what the actual value is when it fails, and similarly for the +// other comparisons. +// +// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() +// evaluate their arguments, which is undefined. +// +// 5. These macros evaluate their arguments exactly once. +// +// Examples: +// +// EXPECT_NE(5, Foo()); +// EXPECT_EQ(NULL, a_pointer); +// ASSERT_LT(i, array_size); +// ASSERT_GT(records.size(), 0) << "There is no record left."; + +#define EXPECT_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define EXPECT_NE(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +#define GTEST_ASSERT_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define GTEST_ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define GTEST_ASSERT_LE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define GTEST_ASSERT_LT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define GTEST_ASSERT_GE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define GTEST_ASSERT_GT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of +// ASSERT_XY(), which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_ASSERT_EQ +# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_NE +# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LE +# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LT +# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GE +# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GT +# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) +#endif + +// C-string Comparisons. All tests treat NULL and any non-NULL string +// as different. Two NULLs are equal. +// +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// +// For wide or narrow string objects, you can use the +// {ASSERT|EXPECT}_??() macros. +// +// Don't depend on the order in which the arguments are evaluated, +// which is undefined. +// +// These macros evaluate their arguments exactly once. + +#define EXPECT_STREQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define EXPECT_STRNE(s1, s2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define EXPECT_STRCASEEQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define EXPECT_STRCASENE(s1, s2)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +#define ASSERT_STREQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define ASSERT_STRNE(s1, s2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define ASSERT_STRCASEEQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define ASSERT_STRCASENE(s1, s2)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +// Macros for comparing floating-point numbers. +// +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): +// Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): +// Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): +// Tests that v1 and v2 are within the given distance to each other. +// +// Google Test uses ULP-based comparison to automatically pick a default +// error bound that is appropriate for the operands. See the +// FloatingPoint template class in gtest-internal.h if you are +// interested in the implementation details. + +#define EXPECT_FLOAT_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_DOUBLE_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_FLOAT_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_DOUBLE_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_NEAR(val1, val2, abs_error)\ + EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +#define ASSERT_NEAR(val1, val2, abs_error)\ + ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +// These predicate format functions work on floating-point values, and +// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. +// +// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); + + +#if GTEST_OS_WINDOWS + +// Macros that test for HRESULT failure and success, these are only useful +// on Windows, and rely on Windows SDK macros and APIs to compile. +// +// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) +// +// When expr unexpectedly fails or succeeds, Google Test prints the +// expected result and the actual result with both a human-readable +// string representation of the error, if available, as well as the +// hex result code. +# define EXPECT_HRESULT_SUCCEEDED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define ASSERT_HRESULT_SUCCEEDED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define EXPECT_HRESULT_FAILED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +# define ASSERT_HRESULT_FAILED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +#endif // GTEST_OS_WINDOWS + +// Macros that execute statement and check that it doesn't generate new fatal +// failures in the current thread. +// +// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); +// +// Examples: +// +// EXPECT_NO_FATAL_FAILURE(Process()); +// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; +// +#define ASSERT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) +#define EXPECT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) + +// Causes a trace (including the source file path, the current line +// number, and the given message) to be included in every test failure +// message generated by code in the current scope. The effect is +// undone when the control leaves the current scope. +// +// The message argument can be anything streamable to std::ostream. +// +// In the implementation, we include the current line number as part +// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s +// to appear in the same block - as long as they are on different +// lines. +#define SCOPED_TRACE(message) \ + ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, ::testing::Message() << (message)) + +// Compile-time assertion for type equality. +// StaticAssertTypeEq() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq(); } +// }; +// +// the code: +// +// void Test1() { Foo foo; } +// +// will NOT generate a compiler error, as Foo::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo foo; foo.Bar(); } +// +// to cause a compiler error. +template +bool StaticAssertTypeEq() { + (void)internal::StaticAssertTypeEqHelper(); + return true; +} + +// Defines a test. +// +// The first parameter is the name of the test case, and the second +// parameter is the name of the test within the test case. +// +// The convention is to end the test case name with "Test". For +// example, a test case for the Foo class can be named FooTest. +// +// The user should put his test code between braces after using this +// macro. Example: +// +// TEST(FooTest, InitializesCorrectly) { +// Foo foo; +// EXPECT_TRUE(foo.StatusIsOK()); +// } + +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ + ::testing::Test, ::testing::internal::GetTestTypeId()) + +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif + +// Defines a test that uses a test fixture. +// +// The first parameter is the name of the test fixture class, which +// also doubles as the test case name. The second parameter is the +// name of the test within the test case. +// +// A test fixture class must be declared earlier. The user should put +// his test code between braces after using this macro. Example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { b_.AddElement(3); } +// +// Foo a_; +// Foo b_; +// }; +// +// TEST_F(FooTest, InitializesCorrectly) { +// EXPECT_TRUE(a_.StatusIsOK()); +// } +// +// TEST_F(FooTest, ReturnsElementCountCorrectly) { +// EXPECT_EQ(0, a_.size()); +// EXPECT_EQ(1, b_.size()); +// } + +#define TEST_F(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture, \ + ::testing::internal::GetTypeId()) + +} // namespace testing + +// Use this function in main() to run all tests. It returns 0 if all +// tests are successful, or 1 otherwise. +// +// RUN_ALL_TESTS() should be invoked after the command line has been +// parsed by InitGoogleTest(). +// +// This function was formerly a macro; thus, it is in the global +// namespace and has an all-caps name. +int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_; + +inline int RUN_ALL_TESTS() { + return ::testing::UnitTest::GetInstance()->Run(); +} + +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/VihrevIB/lab2/include/hash_table.h b/VihrevIB/lab2/include/hash_table.h new file mode 100644 index 000000000..e89d72ad9 --- /dev/null +++ b/VihrevIB/lab2/include/hash_table.h @@ -0,0 +1 @@ +#include "table.h" diff --git a/VihrevIB/lab2/include/list.h b/VihrevIB/lab2/include/list.h new file mode 100644 index 000000000..629ccd5f4 --- /dev/null +++ b/VihrevIB/lab2/include/list.h @@ -0,0 +1,142 @@ +#pragma once +#include "Node.h" +// // + +template +class Rlist +{ +protected: + Node* head; + Node* current; +public: + // + Rlist(); + Rlist(const Rlist& ListToCopy); + ~Rlist(); + + // + Rlist& operator=(const Rlist& ListToCopy); + void InsertAfter(Node* N, T Data); + void OrderedInsert(T Data); // + void Clean(); // + + // + Node* GetCurr() const { return current; } // + void SetNext() { current = current->next; }// + void Reset() { current = head->next; } // + bool IsEnd() const { return current == head; } // + + // + bool operator==(const Rlist& RLst) const; + bool operator!=(const Rlist& RLst) const { return !(*this == RLst); } + + +}; + +// ............................................................................ +template +Rlist::Rlist() +{ + head = new Node; + head->data = NULL; + head->next = head; + current = head; +} +// ............................................................................ +template +Rlist::Rlist(const Rlist& ListToCopy) +{ + Node* TempCurr = ListToCopy.head; + head = new Node(TempCurr->data); + head->next = head; + current = head; + while (TempCurr->next != ListToCopy.head) + { + TempCurr= TempCurr->next; + current->next = new Node(TempCurr->data); + SetNext(); + } + current->next = head; +} +// ............................................................................ +template +Rlist::~Rlist() +{ + Clean(); + delete head; +} + +template +Rlist& Rlist::operator=(const Rlist& ListToCopy) +{ + Clean(); + Node* TempCurr1 = ListToCopy.head; + Node* TempCurr2 = head; + + while (TempCurr1->next != ListToCopy.head) + { + TempCurr1 = TempCurr1->next; + TempCurr2->next = new Node(TempCurr1->data); + TempCurr2 = TempCurr2->next; + } + TempCurr2->next = head; + current = head; + return *this; +} +// ............................................................................ +template +void Rlist::InsertAfter(Node* N, T Data) +{ + Node* temp = N->next; + N->next = new Node(Data); + N->next->next = temp; +} +// ............................................................................ +template +void Rlist::OrderedInsert(T Data) +{ + Node* Temp; + current = head; + + while ( (current->next->data > Data) && current->next != head) + SetNext(); + + Temp = current->next; + current->next = new Node(Data); + current->next->next = Temp; +} +// ............................................................................ +template +void Rlist::Clean() +{ + Node* TempCurr = head->next; + Node* Temp; + while (TempCurr != head) + { + Temp = TempCurr->next; + delete TempCurr; + TempCurr = Temp; + } + head->next = head; +} +// ............................................................................ +template +bool Rlist::operator==(const Rlist& RLst) const +{ + bool flag = true; + if (this != &RLst) + { + Node* temp1 = head->next; + Node* temp2 = RLst.head->next; + + while (temp1 != head && temp2 != RLst.head && temp1->data == temp2->data) + { + temp1 = temp1->next; + temp2 = temp2->next; + } + if (temp1 != head || temp2 != RLst.head) + flag = false; + } + return flag; +} +// ............................................................................ \ No newline at end of file diff --git a/VihrevIB/lab2/include/monom.h b/VihrevIB/lab2/include/monom.h new file mode 100644 index 000000000..fe1518704 --- /dev/null +++ b/VihrevIB/lab2/include/monom.h @@ -0,0 +1,19 @@ +#pragma once +// +class Monom +{ +public: + double coeff; // + unsigned int abc; // + + // + Monom(double COEFF = 0 , unsigned int ABC = 0) { coeff = COEFF; abc = ABC;} + + // + bool operator< (const Monom& m) const { return (abc (const Monom& m) const { return (abc>m.abc); } + bool operator==(const Monom& m) const { return (abc == m.abc && coeff == m.coeff); } // + bool operator!=(const Monom& m) const { return !(*this == m); } + + Monom& operator=(const Monom& m) { coeff = m.coeff; abc = m.abc; return *this; } +}; \ No newline at end of file diff --git a/VihrevIB/lab2/include/node.h b/VihrevIB/lab2/include/node.h new file mode 100644 index 000000000..b33cd87ab --- /dev/null +++ b/VihrevIB/lab2/include/node.h @@ -0,0 +1,19 @@ +#pragma once +#include + +template + +class Node +{ +public: + T data; + Node* next; + + Node(T DATA = NULL, Node* NEXT = nullptr) { data = DATA; next = NEXT; } + Node(Node &Node2) { data = node2.data; next = nullptr; } + // + bool operator< (const Node& N) const { return (data (const Node& N) const { return (data>N.data); } + bool operator!= (const Node& N) const { return !(*this == N); } + bool operator==(const Node& N) const { return (data == N.data && next == N.next); } +}; \ No newline at end of file diff --git a/VihrevIB/lab2/include/ord_table.h b/VihrevIB/lab2/include/ord_table.h new file mode 100644 index 000000000..2f1df586e --- /dev/null +++ b/VihrevIB/lab2/include/ord_table.h @@ -0,0 +1,129 @@ +#include "table.h" + +template +class OrdTable : Table +{ +protected: + vector> Rows; + void Realloc();//? +public: + // + OrdTable(); + OrdTable(const OrdTable& TabToCopy); + ~OrdTable() { Clean(); }; + // + void Insert(T Row, string Key); + int Search(string Key); + void Delete(string Key); + void Clean() { Rows.clear(); CurrIndex = -1; CurrRecords = 0; }; + template friend std::ostream& operator<< (std::ostream& os, const OrdTable& Tab); + +}; + +//............................................................................ +template +OrdTable::OrdTable() : Table() +{ + Rows.reserve(MaxRecords); +} +//............................................................................ +template +OrdTable::OrdTable(const OrdTable& TabToCopy) +{ + Rows = TabToCopy.Rows; + MaxRecords = TabToCopy.MaxRecords; + CurrIndex = TabToCopy.CurrIndex; + CurrRecords = TabToCopy.CurrRecords; +} +//............................................................................ +template +void OrdTable::Realloc() +{ + MaxRecords *= 2; + Rows.reserve(MaxRecords); +} +//............................................................................ +template +void OrdTable::Insert(T Data, string Key) +{ + if (IsFull()) + Realloc(); + + TabRecord Row(Data, Key); + + if (!IsEmpty()) + { + Reset(); + while (CurrIndex < CurrRecords - 1 && !IsEmpty() && Row.Name > Rows[CurrIndex].Name) + { + CurrIndex++; + } + Rows.insert(Rows.begin() + CurrIndex + 1, Row); + CurrRecords = Rows.size(); + + } + else + { + Rows.push_back(Row); + CurrRecords = Rows.size(); + } +} +//............................................................................ +template +int OrdTable::Search(string Key) +{ + Reset(); + int i = 0 , j = CurrRecords; + + if (IsEmpty()) + i = -1; + + while (j-i > 0) + { + if (Key > Rows[i+(j-i)/ 2].Name) + { + i += (j-i) / 2 + 1 ; + } + else + { + j /= 2; + } + + } + + if (IsTabEnded()) + i = -1; + Reset(); + return i; +} +//............................................................................ +template +void OrdTable::Delete(string Key) +{ + Reset(); + int K = Search(Key); + if (K != -1) + { + Rows.erase(Rows.begin() + K); + CurrRecords = Rows.size(); + } + else + return; + +} +//............................................................................ +// +template +std::ostream& operator<< (std::ostream& os, const OrdTable& Tab) +{ + unsigned int i = 0; + + while (i < Tab.CurrRecords) + { + os << i << "." << Tab.Rows[i].Name << " | " << Tab.Rows[i].Data << std::endl; + i++; + } + if (Tab.CurrRecords == 0) + os << "Table is Empty"; + return os; +} \ No newline at end of file diff --git a/VihrevIB/lab2/include/polinom.h b/VihrevIB/lab2/include/polinom.h new file mode 100644 index 000000000..d5bb34644 --- /dev/null +++ b/VihrevIB/lab2/include/polinom.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include "Monom.h" +#include "list.h" + + +using std::string; +using std::ostream; +using std::cout; +using std::cin; +using std::endl; + +class Polinom { + +protected: + + Rlist Monoms; + string name; + // + Rlist Simplify(Rlist POL); // + Rlist Parsing(const string Line);// + +public: + + // + Polinom(const string Line = "" ); // + Polinom(const int A) { Monoms.InsertAfter(Monoms.GetCurr(), A); }; + Polinom(const Monom m) { Monoms.InsertAfter(Monoms.GetCurr(),m); }// : + Polinom(const Rlist &P2) : Monoms(P2) {}; // : + Polinom(const Polinom& POL) : Monoms(POL.Monoms) {}; // + + // + Polinom operator+ (const Polinom&) const; + Polinom operator- (const Polinom& POL) const { return (*this + POL*(-1.0)); } + Polinom operator* (const Polinom& POL) const;// + Polinom operator* (const double c) const; // + + bool operator== (const Polinom& POL) const { return Monoms == POL.Monoms; } + bool operator!= (const Polinom& POL) const { return Monoms != POL.Monoms; } + + friend Polinom operator* (const double C , const Polinom& POL) { return POL*C; } // + friend ostream& operator<< (ostream& os, const Polinom&); +}; \ No newline at end of file diff --git a/VihrevIB/lab2/include/table.h b/VihrevIB/lab2/include/table.h new file mode 100644 index 000000000..b76961919 --- /dev/null +++ b/VihrevIB/lab2/include/table.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include + +using std::string; +using std::vector; + +template +class TabRecord +{ + public: + T Data; + string Name; + TabRecord(T D = NULL, string N = NULL) { Data = D; Name = N; } + bool operator> (const TabRecord& R) const { return (Data < R.Data); } + bool operator< (const TabRecord& R) const { return (Data > R.Data); } + bool operator== (const TabRecord& R) const { return (Data == R.Data); } + bool operator!= (const TabRecord& R) const { return !(*this == R); } + + TabRecord& operator=(const TabRecord& Tab) { Data = Tab.Data; Name = Tab.Name; return *this; } +}; + +template +class Table +{ + protected: + unsigned int MaxRecords; + unsigned int CurrRecords; + int CurrIndex; + public: + Table() { MaxRecords = 1; CurrRecords = 0; CurrIndex = -1; }; + // + virtual void Insert(T Row, string Key) = 0; + virtual void Delete(string key) = 0; + virtual int Search(string Key) = 0; + // + void Reset() { if (!IsEmpty()) CurrIndex = 0; }; //? + bool IsTabEnded() { return CurrIndex == CurrRecords ; }; + bool IsFull() { return CurrRecords == MaxRecords; }; + bool IsEmpty() {return CurrRecords == 0;}; + //virtual TabRecord GetNext() = 0; + //virtual TabRecord GetCurr() = 0; + virtual void Realloc() = 0; + }; + diff --git a/VihrevIB/lab2/include/unord_table.h b/VihrevIB/lab2/include/unord_table.h new file mode 100644 index 000000000..582b71ec6 --- /dev/null +++ b/VihrevIB/lab2/include/unord_table.h @@ -0,0 +1,111 @@ +#pragma once +#include "table.h" + +template +class UnordTable : Table +{ + protected: + vector> Rows; + void Realloc();//? + public: + // + UnordTable(); + UnordTable(const UnordTable& TabToCopy); + ~UnordTable() { Clean(); }; + // + void Insert(T Row, string Key); + int Search(string Key); + void Delete(string Key); + void Clean() { Rows.clear(); Table::CurrIndex = -1; Table::CurrRecords = 0; }; + template friend std::ostream& operator<< (std::ostream& os, const UnordTable& Tab); + +}; +//............................................................................ +template +UnordTable::UnordTable() : Table() +{ + Rows.reserve(MaxRecords); +} +//............................................................................ +template +UnordTable::UnordTable(const UnordTable& TabToCopy) +{ + Rows = TabToCopy.Rows; + MaxRecords = TabToCopy.MaxRecords; + CurrIndex = TabToCopy.CurrIndex; + CurrRecords = TabToCopy.CurrRecords; +} +//............................................................................ +template +void UnordTable::Realloc() +{ + MaxRecords *= 2; + Rows.reserve(MaxRecords); +} +//............................................................................ +template +void UnordTable::Insert(T Data, string Key) +{ + if (IsFull()) + Realloc(); + TabRecord Row(Data, Key); + Rows.push_back(Row); // + CurrRecords = Rows.size(); +} +//............................................................................ +template +int UnordTable::Search(string Key) +{ + Reset(); + int i = 0; + + if (IsEmpty()) + i = -1; + + while (!IsTabEnded()) + { + if (Rows[CurrIndex].Name == Key) + { + i = CurrIndex; + break; + } + + CurrIndex++; + } + + if (IsTabEnded()) + i = -1; + Reset(); + return i ; +} +//............................................................................ +template +void UnordTable::Delete(string Key) +{ + Reset(); + int K = Search(Key); + if (K != -1) + { + Rows.erase(Rows.begin() + K); + CurrRecords = Rows.size(); + } + else + return; + +} +//............................................................................ +// +template +std::ostream& operator<< (std::ostream& os, const UnordTable& Tab) +{ + unsigned int i = 0; + + while(i < Tab.CurrRecords) + { + os << i << "." << Tab.Rows[i].Name << " | " << Tab.Rows[i].Data << std::endl; + i++; + } + if (Tab.CurrRecords == 0) + os << "Table is Empty"; + return os; +} \ No newline at end of file diff --git a/VihrevIB/lab2/samples/table_sample.cpp b/VihrevIB/lab2/samples/table_sample.cpp new file mode 100644 index 000000000..aec94a9d0 --- /dev/null +++ b/VihrevIB/lab2/samples/table_sample.cpp @@ -0,0 +1,13 @@ + +#include "unord_table.h" +#include "ord_table.h" +#include "hash_table.h" +#include "polinom.h" + +int main() +{ + std::cout << "Hello" << endl; + + return 0; +} + diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj b/VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj new file mode 100644 index 000000000..d84baf410 --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {61D82CE4-9662-42AB-B81D-A6482715500F} + Win32Proj + gtest + 10.0.15063.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj.filters b/VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj.filters new file mode 100644 index 000000000..2dfaf7308 --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/gtest/gtest.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы заголовков + + + + + Исходные файлы + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj b/VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj new file mode 100644 index 000000000..b816b9721 --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {D7D853ED-CA12-48D9-B59F-8D1BB2B74E9F} + Win32Proj + polinom_lib + 10.0.15063.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + ..\..\..\..\include + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + ..\..\..\..\include + + + Windows + true + true + true + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj.filters b/VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj.filters new file mode 100644 index 000000000..963786ded --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/polinom_lib/polinom_lib.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj b/VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj new file mode 100644 index 000000000..6566ec481 --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {6DADD25C-9018-44A5-B0E9-5C415E538A9E} + Win32Proj + sample_table + 10.0.15063.0 + sample + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../../../include + + + Console + true + table_lib.lib;polinom_lib.lib;%(AdditionalDependencies) + ../Debug + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../../../include + + + Console + true + true + true + table_lib.lib;%(AdditionalDependencies) + ../Release + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj.filters b/VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj.filters new file mode 100644 index 000000000..81eecf1bb --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/sample_table/sample_table.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj b/VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj new file mode 100644 index 000000000..1cedcf514 --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {9AE67457-3F71-46A1-8360-0F89BB3DC90A} + Win32Proj + table_lib + 10.0.15063.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + ../../../../include + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + ../../../../include + + + Windows + true + true + true + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj.filters b/VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj.filters new file mode 100644 index 000000000..2c4942bb3 --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/table_lib/table_lib.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj b/VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj new file mode 100644 index 000000000..18b953a9d --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {34E283F4-8EB7-4007-B6FA-99335FB55DFA} + Win32Proj + table_test + 10.0.15063.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../../../gtest;../../../../include + + + Console + true + gtest.lib;table_lib.lib;%(AdditionalDependencies) + ../Debug + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + ../../../../gtest;../../../../include + + + Console + true + true + true + gtest.lib;table_lib.lib;%(AdditionalDependencies) + ../Release + + + + + + + Level3 + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj.filters b/VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj.filters new file mode 100644 index 000000000..aa6163c0d --- /dev/null +++ b/VihrevIB/lab2/sln/vc14/lab2_tables/table_test/table_test.vcxproj.filters @@ -0,0 +1,31 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + \ No newline at end of file diff --git a/VihrevIB/lab2/src/hash_table.cpp b/VihrevIB/lab2/src/hash_table.cpp new file mode 100644 index 000000000..384e2d8f2 --- /dev/null +++ b/VihrevIB/lab2/src/hash_table.cpp @@ -0,0 +1 @@ +#include "hash_table.h" \ No newline at end of file diff --git a/VihrevIB/lab2/src/list.cpp b/VihrevIB/lab2/src/list.cpp new file mode 100644 index 000000000..471c2a14b --- /dev/null +++ b/VihrevIB/lab2/src/list.cpp @@ -0,0 +1 @@ +#include "list.h" diff --git a/VihrevIB/lab2/src/monom.cpp b/VihrevIB/lab2/src/monom.cpp new file mode 100644 index 000000000..8e7e2698d --- /dev/null +++ b/VihrevIB/lab2/src/monom.cpp @@ -0,0 +1 @@ +#include "monom.h" diff --git a/VihrevIB/lab2/src/node.cpp b/VihrevIB/lab2/src/node.cpp new file mode 100644 index 000000000..b6347a4d7 --- /dev/null +++ b/VihrevIB/lab2/src/node.cpp @@ -0,0 +1 @@ +#include "node.h" diff --git a/VihrevIB/lab2/src/ord_table.cpp b/VihrevIB/lab2/src/ord_table.cpp new file mode 100644 index 000000000..7bd00b13b --- /dev/null +++ b/VihrevIB/lab2/src/ord_table.cpp @@ -0,0 +1,2 @@ +#include "ord_table.h" + diff --git a/VihrevIB/lab2/src/polinom.cpp b/VihrevIB/lab2/src/polinom.cpp new file mode 100644 index 000000000..8c6cde772 --- /dev/null +++ b/VihrevIB/lab2/src/polinom.cpp @@ -0,0 +1,286 @@ +#include "polinom.h" +//............................................................................ +Polinom::Polinom(const string Line) +{ + Monoms = Parsing(Line); + Monoms = Simplify(Monoms); +} +//............................................................................ +Rlist Polinom::Simplify(Rlist POL) +{ + Rlist res; + POL.Reset(); // current + res.Reset(); + Monom tmp; + // , - + Node* p = POL.GetCurr(); + POL.SetNext(); + + if (!(POL.IsEnd())) + { + POL.Reset(); + + while (!(POL.IsEnd())) + { + tmp.coeff = POL.GetCurr()->data.coeff; + tmp.abc = POL.GetCurr()->data.abc; + + while ((POL.GetCurr()->data.abc == POL.GetCurr()->next->data.abc) && !(POL.IsEnd())) + { + tmp.coeff += POL.GetCurr()->next->data.coeff; + POL.SetNext(); + } + + if (tmp.coeff) + { + res.OrderedInsert(tmp); + res.SetNext(); + } + + if (!(POL.IsEnd())) + POL.SetNext(); + } + res.Reset(); + // 0 + if (res.GetCurr()->data.abc == 0 && res.GetCurr()->data.coeff == 0) + res.InsertAfter(res.GetCurr(), NULL); + } + else + res = POL; + + return res; +} + +//............................................................................ +Polinom Polinom::operator+(const Polinom& POL) const +{ + Polinom res; + Rlist P1 = Monoms; + Rlist P2 = POL.Monoms; + + P1.Reset(); + P2.Reset(); + + res.Monoms.Reset(); + // + while (!P1.IsEnd() && !P2.IsEnd()) + { + if ((P1.GetCurr()->data > P2.GetCurr()->data) && P1.GetCurr()->data.coeff) // + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P1.GetCurr()->data); + P1.SetNext(); + res.Monoms.SetNext(); + } + else + if ((P1.GetCurr()->data < P2.GetCurr()->data) && P2.GetCurr()->data.coeff) + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P2.GetCurr()->data); + P2.SetNext(); + res.Monoms.SetNext(); + } + else // + { + double cf = P1.GetCurr()->data.coeff + P2.GetCurr()->data.coeff; + + if (cf) // + { + Monom temp(cf, P1.GetCurr()->data.abc); + res.Monoms.InsertAfter(res.Monoms.GetCurr(), temp); + + res.Monoms.SetNext(); + } + + P1.SetNext(); + P2.SetNext(); + } + } + // + while (!P1.IsEnd()) + { + if (P1.GetCurr()->data.coeff) + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P1.GetCurr()->data); + res.Monoms.SetNext(); + } + P1.SetNext(); + } + + while (!P2.IsEnd()) + { + if (P2.GetCurr()->data.coeff) + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), P2.GetCurr()->data); + res.Monoms.SetNext(); + } + P2.SetNext(); + } + res.Monoms.Reset(); + // 0 + if (res.Monoms.GetCurr()->data.abc == 0 && res.Monoms.GetCurr()->data.coeff == 0) + res.Monoms.InsertAfter(res.Monoms.GetCurr(), NULL); + + return res; +} +//............................................................................ + +Rlist Polinom::Parsing(const string Line) +{ + Rlist List; + string SMonom, SPol = Line; + int k = 1; + int d[] = { 100,10,1 }; + + while (SPol.length()) + { + Monom tmp; + k = 1; + // + while (SPol[k] != '-' && SPol[k] != '+' && k < SPol.length()) + k++; + + SMonom = SPol.substr(0, k); + SPol.erase(0, k); + // + - + if (SMonom[0] == '-') + { + tmp.coeff = -1; + SMonom.erase(0, 1); + + } + else + { + tmp.coeff = 1; + if (SMonom[0] == '+') + SMonom.erase(0, 1); + } + // + if (isdigit(SMonom[0])) + { + k = 0; + while (isdigit(SMonom[k]) || SMonom[k] == '.' ) + k++; + tmp.coeff *= std::stod(SMonom.substr(0, k)); + SMonom.erase(0, k); + } + // + for (int i = 0; i < 3; i++) + { + int pos = SMonom.find("xyz"[i]); + if (pos != -1) + if (SMonom[pos + 1] == '^') + { + tmp.abc += d[i] * std::stoi(SMonom.substr(pos + 2, 1)); + } + else + tmp.abc += d[i]; + } + + List.OrderedInsert(tmp); + } + return List; +} +//............................................................................ + +Polinom Polinom::operator*(const double c) const +{ + + Polinom res; + + if (c) + { + res = *this; + res.Monoms.Reset(); + while (!(res.Monoms.IsEnd())) + { + res.Monoms.GetCurr()->data.coeff *= c; + res.Monoms.SetNext(); + } + } + else + { + res.Monoms.InsertAfter(res.Monoms.GetCurr(), NULL); + } + + return res; +} +//............................................................................ +Polinom Polinom::operator*(const Polinom& POL) const { + + Polinom res; + Polinom P1 = Monoms, P2 = POL; + int abc; + double coeff; + + P1.Monoms.Reset(); + P2.Monoms.Reset(); + + while (!P2.Monoms.IsEnd()) + { + Monom tmp; + P1.Monoms.Reset(); + while (!P1.Monoms.IsEnd()) + { + abc = P1.Monoms.GetCurr()->data.abc; + coeff = P1.Monoms.GetCurr()->data.coeff; + tmp = P2.Monoms.GetCurr()->data; + if ( (tmp.abc % 10 + abc % 10) < 10 && (tmp.abc /10 % 10 + abc / 10 % 10) < 10 && (tmp.abc / 100 + abc / 100 ) <10) + { + tmp.coeff *= coeff; + tmp.abc += abc; + res = res + tmp; + } + else + { + throw "Degree>10"; + } + P1.Monoms.SetNext(); + } + P2.Monoms.SetNext(); + } + return res; +} +//............................................................................ + +ostream& operator<<(ostream& os, const Polinom& POL) +{ + Polinom tmpPol = POL; + tmpPol.Monoms.Reset(); + + Node* FirstNode =tmpPol.Monoms.GetCurr(); // + Node tmpMon; + while (!(tmpPol.Monoms.IsEnd())) + { + tmpMon = tmpPol.Monoms.GetCurr()->data; + if (tmpMon.data.coeff > 0 && tmpPol.Monoms.GetCurr() != FirstNode) + os << '+'; + if (tmpMon.data.coeff != 1 && tmpMon.data.coeff != -1 && tmpMon.data.coeff !=0) + os << tmpMon.data.coeff; + else + if (tmpMon.data.coeff == -1 && tmpMon.data.abc != 0) + os << '-'; + else + if ((tmpMon.data.coeff == 1 || tmpMon.data.coeff == -1 )&& tmpMon.data.abc == 0) + os << tmpMon.data.coeff; + int d[3] = { 100,10,1 }; + for (int i = 0; i < 3; i++) + { + if (tmpMon.data.abc / d[i] % 10 != 0) + { + os << "xyz"[i]; + if (tmpMon.data.abc / d[i] % 10 != 1) + os << '^' << tmpMon.data.abc / d[i] % 10; + } + } + tmpPol.Monoms.SetNext(); + } + tmpPol.Monoms.Reset(); + + if (tmpPol.Monoms.GetCurr()->data.abc == 0 && tmpPol.Monoms.GetCurr()->data.coeff == 0 && !(tmpPol.Monoms.IsEnd())) + { + os << "0"; + } + return os; +} + +// ............................................................................ + diff --git a/KorolevAP/lab1/include/tlist.h b/VihrevIB/lab2/src/table.cpp similarity index 100% rename from KorolevAP/lab1/include/tlist.h rename to VihrevIB/lab2/src/table.cpp diff --git a/VihrevIB/lab2/src/unord_table.cpp b/VihrevIB/lab2/src/unord_table.cpp new file mode 100644 index 000000000..8780a64ee --- /dev/null +++ b/VihrevIB/lab2/src/unord_table.cpp @@ -0,0 +1,2 @@ +#include "unord_table.h" + diff --git a/VihrevIB/lab2/test/hash_table_test.cpp b/VihrevIB/lab2/test/hash_table_test.cpp new file mode 100644 index 000000000..384e2d8f2 --- /dev/null +++ b/VihrevIB/lab2/test/hash_table_test.cpp @@ -0,0 +1 @@ +#include "hash_table.h" \ No newline at end of file diff --git a/VihrevIB/lab2/test/ord_table_test.cpp b/VihrevIB/lab2/test/ord_table_test.cpp new file mode 100644 index 000000000..dc604a21a --- /dev/null +++ b/VihrevIB/lab2/test/ord_table_test.cpp @@ -0,0 +1 @@ +#include "ord_table.h" \ No newline at end of file diff --git a/VihrevIB/lab2/test/test_main.cpp b/VihrevIB/lab2/test/test_main.cpp new file mode 100644 index 000000000..3968c279a --- /dev/null +++ b/VihrevIB/lab2/test/test_main.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/VihrevIB/lab2/test/unord_table_test.cpp b/VihrevIB/lab2/test/unord_table_test.cpp new file mode 100644 index 000000000..15caf2ca2 --- /dev/null +++ b/VihrevIB/lab2/test/unord_table_test.cpp @@ -0,0 +1 @@ +#include "unord_table.h" \ No newline at end of file From 9621c142a941b6bae9bf19a617e658eb67140f0a Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Thu, 17 May 2018 17:01:29 +0300 Subject: [PATCH 11/16] =?UTF-8?q?ready=2098.9999=C2=9F%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VihrevIB/lab2/include/hash_table.h | 259 ++++++++++++++++++++++++ VihrevIB/lab2/include/ord_table.h | 141 ++++++++----- VihrevIB/lab2/include/table.h | 94 ++++++--- VihrevIB/lab2/include/unord_table.h | 122 ++++++----- VihrevIB/lab2/samples/table_sample.cpp | 114 ++++++++++- VihrevIB/lab2/test/hash_table_test.cpp | 243 +++++++++++++++++++++- VihrevIB/lab2/test/ord_table_test.cpp | 254 ++++++++++++++++++++++- VihrevIB/lab2/test/unord_table_test.cpp | 255 ++++++++++++++++++++++- 8 files changed, 1342 insertions(+), 140 deletions(-) diff --git a/VihrevIB/lab2/include/hash_table.h b/VihrevIB/lab2/include/hash_table.h index e89d72ad9..8a96930f6 100644 --- a/VihrevIB/lab2/include/hash_table.h +++ b/VihrevIB/lab2/include/hash_table.h @@ -1 +1,260 @@ +#pragma once #include "table.h" + +#pragma once +#include "table.h" + +template +class HashTable : public Table //? +{ +protected: + int* flag; + int HashFunc(string Key) const; + void Realloc(); +public: + // + HashTable(unsigned int i = 10); + HashTable(const HashTable& TabToCopy); + ~HashTable() { delete[] flag;}; + // + void Insert(const T Data, const string Key); + T* Search(const string Key); + void Delete(const string Key); + // + void SetNext(); + T* GetCurr() const; + void Reset(); + bool IsTabEnded() const { return CurrIndex == CurrRecords || CurrIndex == -1; };// return false; + template friend std::ostream& operator<< (std::ostream& os, const HashTable& Tab); + +}; +//............................................................................ +template +HashTable::HashTable(unsigned int i) : Table(i) +{ + flag = new int[i]; + for (int j = 0; j < i; j++) + flag[j] = 0; // 0 , 1 -, -1 - +} +//............................................................................ +template +HashTable::HashTable(const HashTable& TabToCopy) +{ + MaxRecords = TabToCopy.MaxRecords; + CurrIndex = TabToCopy.CurrIndex; + CurrRecords = TabToCopy.CurrRecords; + delete[] Rows; + delete[] flag; + Rows = new TabRecord*[MaxRecords]; + flag = new int[MaxRecords]; + + for (int j = 0; j < MaxRecords; j++) + flag[j] = TabToCopy.flag[j]; + + if (!IsEmpty()) + for (int i = 0; i < MaxRecords; i++) + { + if(flag[i] == 1) + Rows[i] = new TabRecord(*(TabToCopy.Rows[i])); + } +} +//............................................................................ +template +void HashTable::Reset() +{ + if (!IsEmpty()) + { + CurrIndex = 0; + while (flag[CurrIndex] != 1) + CurrIndex++; + } + else + CurrIndex = -1; +} +//............................................................................ +template +T* HashTable::GetCurr() const +{ + T* tmp = nullptr; + + if(!IsEmpty()) + { + tmp = Rows[CurrIndex]->Data; + } + else + { + throw (string)"Table Is Empty"; + } + return tmp; +} + +//............................................................................ +template +void HashTable::SetNext() +{ + if (!IsEmpty()) + { + CurrIndex++; + while (flag[CurrIndex] != 1) + CurrIndex = (CurrIndex+1) % MaxRecords; + } + else + throw (string)"Table Is Empty"; + +} +//............................................................................ +template +void HashTable::Realloc() +{ + unsigned int OldMaxRecords = MaxRecords; + MaxRecords *= 1.5; + TabRecord** tmp = new TabRecord*[OldMaxRecords]; + for (int i = 0; i < OldMaxRecords; i++) + { + tmp[i] = new TabRecord(*Rows[i]); + } + + delete[] Rows; + CurrRecords = 0; + CurrIndex = -1; + delete[] flag; + flag = new int[MaxRecords]; + for (int i = 0; i < MaxRecords; i++) + flag[i] = 0; + Rows = new TabRecord*[MaxRecords]; + for (int i = 0; i < OldMaxRecords; i++) + { + Insert(*(tmp[i]->Data), tmp[i]->Key); // ? + } +} +//............................................................................ +template +int HashTable::HashFunc(string Key) const +{ + unsigned int i= 0; + for (int j = 0; j < Key.length(); j++) + i += (char)Key[j]; + for (int j = 0; j < Key.length(); j++) + i *= 13; + srand(i); + unsigned int h = rand(); + return h % MaxRecords; +} +//............................................................................ +template +void HashTable::Insert(const T Data, const string Key) +{ + if (IsFull()) + Realloc(); + TabRecord Row(Key, Data); + Reset(); + CurrIndex = HashFunc(Key); + if (flag[CurrIndex] == 0 || flag[CurrIndex] == -1 ) + { + Rows[CurrIndex] = new TabRecord(Row); + CurrRecords++; + flag[CurrIndex] = 1; + Reset(); + } + else + { + if (Rows[CurrIndex]->Key != Key) + { + int ind = CurrIndex; + while (flag[CurrIndex] == 1 && CurrIndex+1 != ind) + CurrIndex = (CurrIndex+1) % MaxRecords; // + Rows[CurrIndex] = new TabRecord(Row); + CurrRecords++;// + flag[CurrIndex] = 1; + Reset(); + } + else + { + Reset(); + string s = "Key: " + Key + " - isn`t unique"; + throw s; + } + } +} +//............................................................................ +template +T* HashTable::Search(const string Key) +{ + Reset(); + T* tmp = nullptr; + if (IsEmpty()) + throw (string)"Cant Search In Empty Table"; + CurrIndex = HashFunc(Key); + + if(Rows[CurrIndex]->Key == Key) + tmp = Rows[CurrIndex]->Data; + else + { + int ind = CurrIndex; + while (flag[CurrIndex] == 1 && CurrIndex+1 != ind) + { + CurrIndex = (CurrIndex + 1) % MaxRecords; + if (Rows[CurrIndex]->Key == Key) + { + tmp = Rows[CurrIndex]->Data; + break; + } + } + + + + if (tmp == nullptr) + { + Reset(); + string s = Key + " Not Found"; + throw s; + } + + } + return tmp; +} +//............................................................................ +template +void HashTable::Delete(string Key) +{ + Reset(); + if (IsEmpty()) + throw (string)"Cant Delete From Empty Table"; + Search(Key); + + TabRecord A; + flag[CurrIndex] = -1; + Rows[CurrIndex] = new TabRecord(A); + CurrRecords--; + + /*int F =0,E = 0; + + for (int i = 0; i < MaxRecords; i++) + { + if (flag[i] == 1) + F++; + else + E++; + }*/ + + Reset(); +} +//............................................................................ +// +template +std::ostream& operator<< (std::ostream& os, const HashTable& Tab) +{ + unsigned int i = 0; + + while (i < Tab.MaxRecords) + { + if (Tab.flag[i] == 1) + { + os << i << ". " << Tab.Rows[i]->Key << " | " << *(Tab.Rows[i]->Data) << std::endl; + } + i++; + } + if (Tab.CurrRecords == 0) + os << "Table is Empty"; + return os; +} diff --git a/VihrevIB/lab2/include/ord_table.h b/VihrevIB/lab2/include/ord_table.h index 2f1df586e..d3ff8a96d 100644 --- a/VihrevIB/lab2/include/ord_table.h +++ b/VihrevIB/lab2/include/ord_table.h @@ -1,126 +1,157 @@ #include "table.h" template -class OrdTable : Table +class OrdTable : public Table { protected: - vector> Rows; - void Realloc();//? + void Realloc(); public: // - OrdTable(); + OrdTable(unsigned int i = 10); OrdTable(const OrdTable& TabToCopy); - ~OrdTable() { Clean(); }; + ~OrdTable() {}; // - void Insert(T Row, string Key); - int Search(string Key); - void Delete(string Key); - void Clean() { Rows.clear(); CurrIndex = -1; CurrRecords = 0; }; - template friend std::ostream& operator<< (std::ostream& os, const OrdTable& Tab); + void Insert(const T Data, const string Key); + T* Search(const string Key); + void Delete(const string Key); + template friend std::ostream& operator<< (std::ostream& os, const OrdTable& Tab); }; //............................................................................ template -OrdTable::OrdTable() : Table() +OrdTable::OrdTable(unsigned int i) : Table(i) { - Rows.reserve(MaxRecords); } //............................................................................ -template +template // OrdTable::OrdTable(const OrdTable& TabToCopy) { - Rows = TabToCopy.Rows; MaxRecords = TabToCopy.MaxRecords; CurrIndex = TabToCopy.CurrIndex; CurrRecords = TabToCopy.CurrRecords; + delete[] Rows; + Rows = new TabRecord*[MaxRecords]; + if (!IsEmpty()) + for (int i = 0; i < CurrRecords; i++) + Rows[i] = new TabRecord(*(TabToCopy.Rows[i])); } //............................................................................ template void OrdTable::Realloc() { - MaxRecords *= 2; - Rows.reserve(MaxRecords); + unsigned int NewMaxRecords = (unsigned int)(MaxRecords*1.5); + TabRecord** tmp = new TabRecord*[NewMaxRecords]; + for (int i = 0; i < MaxRecords; i++) + tmp[i] = Rows[i]; + MaxRecords = NewMaxRecords; + delete[] Rows; + Rows = tmp; } //............................................................................ template -void OrdTable::Insert(T Data, string Key) +void OrdTable::Insert(const T Data, const string Key) { if (IsFull()) Realloc(); - TabRecord Row(Data, Key); + TabRecord Row(Key,Data); + Reset(); - if (!IsEmpty()) + Reset(); + while (!IsTabEnded() && Row.Key >= Rows[CurrIndex]->Key) { - Reset(); - while (CurrIndex < CurrRecords - 1 && !IsEmpty() && Row.Name > Rows[CurrIndex].Name) + if (Rows[CurrIndex]->Key == Row.Key) { - CurrIndex++; + string s = "Key: " + Key + " - isn`t unique"; + throw s; } - Rows.insert(Rows.begin() + CurrIndex + 1, Row); - CurrRecords = Rows.size(); - + CurrIndex++; } - else + if (IsEmpty()) + CurrIndex++; + CurrRecords++; + for (int i = CurrRecords-1; i > CurrIndex; i--) { - Rows.push_back(Row); - CurrRecords = Rows.size(); + Rows[i] = Rows[i - 1]; + } + Rows[CurrIndex] = new TabRecord(Row); + Reset(); + } //............................................................................ template -int OrdTable::Search(string Key) +T* OrdTable::Search(const string Key) { Reset(); - int i = 0 , j = CurrRecords; + T* tmp = nullptr; - if (IsEmpty()) - i = -1; - - while (j-i > 0) - { - if (Key > Rows[i+(j-i)/ 2].Name) + if (!IsEmpty()) + { + int i = -1, j = CurrRecords; + int mid; + while (i < j -1 ) // + { + mid = (j + i) / 2; + if (Key >= Rows[mid]->Key) + { + i = mid; + } + else + { + j = mid; + } + + } + if (Key == Rows[i]->Key) { - i += (j-i) / 2 + 1 ; + CurrIndex = i; + tmp = Rows[CurrIndex]->Data; } else { - j /= 2; + string s = Key + " Not Found"; + throw s; } - } - - if (IsTabEnded()) - i = -1; - Reset(); - return i; + else + throw (string)"Table Is Empty"; + return tmp; } //............................................................................ template -void OrdTable::Delete(string Key) +void OrdTable::Delete(const string Key) { Reset(); - int K = Search(Key); - if (K != -1) - { - Rows.erase(Rows.begin() + K); - CurrRecords = Rows.size(); + if (IsEmpty()) + throw (string)"Cant Delete From Empty Table"; + Search(Key); + if (CurrRecords > 1) + { + CurrRecords--; + for (int i = CurrIndex; i < CurrRecords; i++) + { + Rows[i] = Rows[i + 1]; + + } + Reset(); } else - return; + CurrRecords = 0; + + } //............................................................................ -// -template -std::ostream& operator<< (std::ostream& os, const OrdTable& Tab) +template +std::ostream& operator<< (std::ostream& os, const OrdTable& Tab) { unsigned int i = 0; while (i < Tab.CurrRecords) { - os << i << "." << Tab.Rows[i].Name << " | " << Tab.Rows[i].Data << std::endl; + os << i << ". " << Tab.Rows[i]->Key << " | " << *(Tab.Rows[i]->Data) << std::endl; i++; } if (Tab.CurrRecords == 0) diff --git a/VihrevIB/lab2/include/table.h b/VihrevIB/lab2/include/table.h index b76961919..05bcce1c5 100644 --- a/VihrevIB/lab2/include/table.h +++ b/VihrevIB/lab2/include/table.h @@ -1,46 +1,92 @@ #pragma once #include -#include #include using std::string; -using std::vector; +using std::endl; +using std::cout; template class TabRecord { public: - T Data; - string Name; - TabRecord(T D = NULL, string N = NULL) { Data = D; Name = N; } - bool operator> (const TabRecord& R) const { return (Data < R.Data); } - bool operator< (const TabRecord& R) const { return (Data > R.Data); } - bool operator== (const TabRecord& R) const { return (Data == R.Data); } - bool operator!= (const TabRecord& R) const { return !(*this == R); } - - TabRecord& operator=(const TabRecord& Tab) { Data = Tab.Data; Name = Tab.Name; return *this; } + string Key; + T* Data; // + TabRecord() { Key = "EMPTY RECORD"; Data = new T(NULL); } + TabRecord(string K , T D ) { Key = K; Data = new T(D);} // + TabRecord(const TabRecord& TR) { Key = TR.Key; Data = new T(*(TR.Data)); } + + TabRecord& operator=(const TabRecord& TabR) { Data = new T(*(TabR.Data)); Key = TabR.Key; return *this; } }; template class Table { protected: + TabRecord** Rows; // unsigned int MaxRecords; unsigned int CurrRecords; int CurrIndex; + virtual void Realloc() = 0; public: - Table() { MaxRecords = 1; CurrRecords = 0; CurrIndex = -1; }; + Table(unsigned int i = 10); + virtual ~Table() { delete[] Rows; }; //? // - virtual void Insert(T Row, string Key) = 0; - virtual void Delete(string key) = 0; - virtual int Search(string Key) = 0; + virtual void Insert(const T Data, const string Key) = 0; + virtual void Delete(const string key) = 0; + virtual T* Search(const string Key) = 0; // - void Reset() { if (!IsEmpty()) CurrIndex = 0; }; //? - bool IsTabEnded() { return CurrIndex == CurrRecords ; }; - bool IsFull() { return CurrRecords == MaxRecords; }; - bool IsEmpty() {return CurrRecords == 0;}; - //virtual TabRecord GetNext() = 0; - //virtual TabRecord GetCurr() = 0; - virtual void Realloc() = 0; - }; - + virtual void Reset(); + virtual bool IsTabEnded() const { return CurrIndex == CurrRecords || CurrIndex == -1; }; + bool IsFull() const { return CurrRecords == MaxRecords; }; + bool IsEmpty() const { return CurrRecords == 0; }; + virtual void SetNext(); + virtual T* GetCurr() const; + int GetCurrRecords() const { return CurrRecords; }; + int GetMaxRecords() const { return MaxRecords; }; + // +}; +//.......................................................... +template +Table::Table(unsigned int i) +{ + MaxRecords = i; + CurrRecords = 0; + CurrIndex = -1; + Rows = new TabRecord*[MaxRecords]; +} +//.......................................................... +template +void Table::Reset() +{ + if(CurrRecords > 0) + CurrIndex = 0; + else + CurrIndex = -1; +} +//.......................................................... +template +T* Table::GetCurr() const +{ + T* tmp; + if (CurrIndex >= 0 && CurrIndexData; + } + else + { + throw (string)"Table Is Empty"; + } + return tmp; +} +//.......................................................... +template +void Table::SetNext() +{ + if (CurrIndex != -1) + CurrIndex++; + else + throw (string)"Table Is Empty"; + if (IsTabEnded()) + Reset(); +} \ No newline at end of file diff --git a/VihrevIB/lab2/include/unord_table.h b/VihrevIB/lab2/include/unord_table.h index 582b71ec6..b0b7826b3 100644 --- a/VihrevIB/lab2/include/unord_table.h +++ b/VihrevIB/lab2/include/unord_table.h @@ -1,108 +1,120 @@ #pragma once #include "table.h" - +// +// +// * = * = template -class UnordTable : Table +class UnordTable : public Table { protected: - vector> Rows; - void Realloc();//? + void Realloc(); public: // - UnordTable(); + UnordTable(unsigned int i = 10) : Table(i) {}; UnordTable(const UnordTable& TabToCopy); - ~UnordTable() { Clean(); }; - // - void Insert(T Row, string Key); - int Search(string Key); - void Delete(string Key); - void Clean() { Rows.clear(); Table::CurrIndex = -1; Table::CurrRecords = 0; }; - template friend std::ostream& operator<< (std::ostream& os, const UnordTable& Tab); + ~UnordTable() { }; + // + void Insert(const T Data, const string Key); + T* Search(const string Key); + void Delete(const string Key); + + template friend std::ostream& operator<< (std::ostream& os, const UnordTable& Tab); }; //............................................................................ template -UnordTable::UnordTable() : Table() -{ - Rows.reserve(MaxRecords); -} -//............................................................................ -template UnordTable::UnordTable(const UnordTable& TabToCopy) { - Rows = TabToCopy.Rows; MaxRecords = TabToCopy.MaxRecords; CurrIndex = TabToCopy.CurrIndex; CurrRecords = TabToCopy.CurrRecords; + delete[] Rows; + Rows = new TabRecord*[MaxRecords]; + if (!IsEmpty()) + for (int i = 0; i < CurrRecords; i++) + Rows[i] = new TabRecord(*(TabToCopy.Rows[i])); } //............................................................................ template void UnordTable::Realloc() { - MaxRecords *= 2; - Rows.reserve(MaxRecords); + unsigned int NewMaxRecords = (unsigned int)(MaxRecords*1.5); + TabRecord** tmp = new TabRecord*[NewMaxRecords]; + for (int i = 0; i < MaxRecords; i++) + tmp[i] = Rows[i]; + MaxRecords = NewMaxRecords; + delete[] Rows; + Rows = tmp; } //............................................................................ template -void UnordTable::Insert(T Data, string Key) -{ +void UnordTable::Insert(const T Data, const string Key) +{ if (IsFull()) Realloc(); - TabRecord Row(Data, Key); - Rows.push_back(Row); // - CurrRecords = Rows.size(); + TabRecord Row(Key, Data); + Reset(); + while (!IsTabEnded() && Key != Rows[CurrIndex]->Key) + CurrIndex++; + if (IsEmpty()) + { + CurrIndex++; + } + if (CurrIndex == CurrRecords) + { + Rows[CurrIndex] = new TabRecord(Row); + CurrRecords++; + Reset(); + } + else + { + Reset(); + string s = "Key: " + Key + " - isn`t unique"; + throw s; + } } //............................................................................ template -int UnordTable::Search(string Key) +T* UnordTable::Search(const string Key) { Reset(); - int i = 0; - + T* tmp = nullptr; if (IsEmpty()) - i = -1; - - while (!IsTabEnded()) - { - if (Rows[CurrIndex].Name == Key) - { - i = CurrIndex; - break; - } - + throw (string)"Cant Search In Empty Table"; + while (!IsTabEnded() && Key != Rows[CurrIndex]->Key) CurrIndex++; + if (!IsTabEnded()) + tmp = Rows[CurrIndex]->Data; + else + { + string s = Key + " Not Found"; + throw s; } - - if (IsTabEnded()) - i = -1; - Reset(); - return i ; + return tmp; } //............................................................................ template void UnordTable::Delete(string Key) { Reset(); - int K = Search(Key); - if (K != -1) - { - Rows.erase(Rows.begin() + K); - CurrRecords = Rows.size(); - } + if (IsEmpty()) + throw (string)"Cant Delete From Empty Table"; + Search(Key); + if (CurrRecords > 1) + Rows[CurrIndex] = Rows[--CurrRecords]; else - return; - + CurrRecords = 0; } //............................................................................ // -template -std::ostream& operator<< (std::ostream& os, const UnordTable& Tab) +template +std::ostream& operator<< (std::ostream& os, const UnordTable& Tab) { unsigned int i = 0; while(i < Tab.CurrRecords) { - os << i << "." << Tab.Rows[i].Name << " | " << Tab.Rows[i].Data << std::endl; + os << i << ". " << Tab.Rows[i]->Key<< " | " << *(Tab.Rows[i]->Data) << std::endl; i++; } if (Tab.CurrRecords == 0) diff --git a/VihrevIB/lab2/samples/table_sample.cpp b/VihrevIB/lab2/samples/table_sample.cpp index aec94a9d0..23d377874 100644 --- a/VihrevIB/lab2/samples/table_sample.cpp +++ b/VihrevIB/lab2/samples/table_sample.cpp @@ -1,4 +1,4 @@ - +#include #include "unord_table.h" #include "ord_table.h" #include "hash_table.h" @@ -6,8 +6,116 @@ int main() { - std::cout << "Hello" << endl; - + system("color F0"); + UnordTable Utab; + OrdTable Otab; + HashTable Htab; + string Key,Str; + Polinom P; + char ch = 0; + while (ch != 27) + { + system("cls"); + cout << "UnordTable: " << endl << Utab << endl; + cout << "OrdTable :" << endl << Otab << endl; + cout << "HashTable :" << endl << Htab << endl << endl; + cout << "You can insert/delete and find in tables" << endl; + cout << "What will you do?" << endl << "1. Insert" << endl << "2. Delete" <> Str; + int i = 0; + if (isdigit(Str[0])) + i = stoi(Str); + switch (i) + { + case 1: + { + while(true) + { + cout << "Input Polinom" << endl; + cin >> Key; + if (Key == "end") break; + P = Polinom(Key); + try + { + system("cls"); + Utab.Insert(P, Key); + Otab.Insert(P, Key); + Htab.Insert(P, Key); + cout << "UnordTable: " << endl << Utab << endl; + cout << "OrdTable :" << endl << Otab << endl; + cout << "HashTable :" << endl << Htab << endl << endl; + } + catch (string s) + { + cout << "UnordTable: " << endl << Utab << endl; + cout << "OrdTable :" << endl << Otab << endl; + cout << "HashTable :" << endl << Htab << endl << endl; + cout << "Error :" << s << endl; + } + + } + } + break; + case 2: + { + while (true) + { + cout << "Input Polinom" << endl; + cin >> Key; + if (Key == "end") break; + try + { + Utab.Delete(Key); + Otab.Delete(Key); + Htab.Delete(Key); + system("cls"); + cout << "UnordTable: " << endl << Utab << endl; + cout << "OrdTable :" << endl << Otab << endl; + cout << "HashTable :" << endl << Htab << endl << endl; + } + catch (string s) + { + cout << "UnordTable: " << endl << Utab << endl; + cout << "OrdTable :" << endl << Otab << endl; + cout << "HashTable :" << endl << Htab << endl << endl; + cout << "Error :" << s << endl; + } + } + } + break; + case 3: + { + while (true) + { + cout << "Input Polinom" << endl; + cin >> Key; + if (Key == "end") break; + system("cls"); + cout << "UnordTable: " << endl << Utab << endl; + cout << "OrdTable :" << endl << Otab << endl; + cout << "HashTable :" << endl << Htab << endl << endl; + try + { + cout << "Search in UnordTable : " << *(Utab.Search(Key)) << endl; + cout << "Search in OrdTable : " << *(Otab.Search(Key)) << endl; + cout << "Search in HashTable : " << *(Htab.Search(Key)) << endl; + } + catch (string s) + { + cout << "Error :" << s << endl; + } + } + } + break; + default: + cout << "try again" << endl; + break; + } + + cout << "-----------------------------------------------------------------------------" << endl; + cout << "Esc to exit " << endl; + ch = _getch(); + } return 0; } diff --git a/VihrevIB/lab2/test/hash_table_test.cpp b/VihrevIB/lab2/test/hash_table_test.cpp index 384e2d8f2..1f9b95781 100644 --- a/VihrevIB/lab2/test/hash_table_test.cpp +++ b/VihrevIB/lab2/test/hash_table_test.cpp @@ -1 +1,242 @@ -#include "hash_table.h" \ No newline at end of file +#include +#include "hash_table.h" + + +// +//............................................................ +TEST(HashTable, can_create_unord_table) +{ + ASSERT_NO_THROW(HashTable Tab); +} +//............................................................ +class EmptyHTable : public testing::Test +{ +protected: + HashTable Tab; +public: + EmptyHTable() {}; + ~EmptyHTable() {}; +}; +////............................................................ +TEST_F(EmptyHTable, new_table_is_empty) +{ + EXPECT_EQ(true, Tab.IsEmpty()); +} +////............................................................................ +TEST_F(EmptyHTable, can_copy_empty_table) +{ + ASSERT_NO_THROW(HashTable T(Tab)); +} +////............................................................................ +TEST_F(EmptyHTable, copied_empty_table_is_correct) +{ + HashTable T(Tab); + EXPECT_EQ(Tab.IsEmpty(), T.IsEmpty()); +} +////............................................................................ +////TEST_F(EmptyHTable, can_assign_two_empty_tables) +////{ +//// HashTable T2; +//// ASSERT_NO_THROW(Tab = T2); +////} +////............................................................................ +////TEST_F(EmptyHTable, can_assign_empty_table_to_itself) +////{ +//// ASSERT_NO_THROW(Tab = Tab); +////} +////............................................................................ +////TEST_F(EmptyHTable, can_clean_empty_table) +////{ +//// ASSERT_NO_THROW(Tab.Clean()); +////} +// +////............................................................................ +////TEST_F(EmptyHTable, clean_empty_table_is_correct) +////{ +//// Tab.Clean(); +//// EXPECT_EQ(true, Tab.IsEmpty()); +////} +////............................................................................ +TEST_F(EmptyHTable, cant_get_current_from_empty_table) +{ + ASSERT_ANY_THROW(Tab.GetCurr()); +} +////............................................................................ +TEST_F(EmptyHTable, can_reset_empty_table) +{ + ASSERT_NO_THROW(Tab.Reset()); +} +////............................................................................ +TEST_F(EmptyHTable, reset_empty_table_is_correct) +{ + Tab.Reset(); + ASSERT_ANY_THROW(Tab.GetCurr()); +} +////............................................................................ +TEST_F(EmptyHTable, is_end_is_correct_for_empty_table) +{ + bool k = Tab.IsTabEnded(); + EXPECT_EQ(true, Tab.IsTabEnded()); +} +////............................................................................ +TEST_F(EmptyHTable, cant_set_next_empty_table) +{ + ASSERT_ANY_THROW(Tab.SetNext()); +} +////............................................................................ +TEST_F(EmptyHTable, cant_delete_from_empty_table) +{ + ASSERT_ANY_THROW(Tab.Delete("one")); +} +////............................................................................ +TEST_F(EmptyHTable, cant_search_in_empty_table) +{ + ASSERT_ANY_THROW(Tab.Search("one")); +} +////............................................................................ +TEST_F(EmptyHTable, can_insert_in_empty_table) +{ + ASSERT_NO_THROW(Tab.Insert(1, "one")); +} +////---------------------------------------------------------------------------- +TEST_F(EmptyHTable, insert_in_empty_table_is_correct) +{ + Tab.Insert(1, "one"); + EXPECT_EQ(1, Tab.GetCurrRecords()); + EXPECT_EQ(1, *(Tab.Search("one"))); +} +//---------------------------------------------------------------------------- +class FilledHashTable : public testing::Test +{ +protected: + HashTable T; +public: + FilledHashTable() + { + for (int i = 0; i < 3; i++) + T.Insert(i, std::to_string(i)); + } + ~FilledHashTable() {}; +}; +//---------------------------------------------------------------------------- +TEST_F(FilledHashTable, can_get_current_from_filled_table) +{ + T.Reset(); + ASSERT_NO_THROW(T.GetCurr()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, get_current_from_filled_table_is_corect) +{ + T.Reset(); + EXPECT_EQ(2, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, can_set_next_in_filled_table) +{ + T.Reset(); + ASSERT_NO_THROW(T.SetNext()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, set_next_in_filled_table_is_correct) +{ + T.Reset(); + T.SetNext(); + EXPECT_EQ(0, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, set_next_in_the_end) +{ + T.Reset(); + T.SetNext();//0 + T.SetNext();//1 + T.SetNext();//2 + EXPECT_EQ(2, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, filled_table_was_correctly_filled) +{ + T.Reset(); + EXPECT_EQ(0, *(T.Search("0"))); + EXPECT_EQ(1, *(T.Search("1"))); + EXPECT_EQ(2, *(T.Search("2"))); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, can_copy_filled_table) +{ + ASSERT_NO_THROW(HashTable A(T)); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, copied_filled_table_is_correct) +{ + HashTable A(T); + EXPECT_EQ(0, *(A.Search("0"))); + EXPECT_EQ(1, *(A.Search("1"))); + EXPECT_EQ(2, *(A.Search("2"))); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, copied_filled_table_has_its_own_memory) +{ + HashTable A(T); + A.Delete("0"); + T.Reset(); + A.Reset(); + EXPECT_EQ(0, *(T.Search("0"))); + ASSERT_ANY_THROW(A.Search("0")); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, is_full_is_correct) +{ + for (int i = 3; i<10; i++) + T.Insert(i, std::to_string(i)); + EXPECT_EQ(true, T.IsFull()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, isnt_full_after_realloc) +{ + for (int i = 3; i<11; i++) + T.Insert(i, std::to_string(i)); + EXPECT_EQ(false, T.IsFull()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, is_empty_after_deletion) +{ + T.Delete("0"); + T.Delete("1"); + T.Delete("2"); + EXPECT_EQ(true, T.IsEmpty()); +} +////--------------------------------------------------------------------------- +TEST_F(FilledHashTable, can_insert_after_deletion) +{ + T.Delete("0"); + T.Delete("1"); + T.Delete("2"); + T.Insert(0, "0"); + EXPECT_EQ(0, *(T.GetCurr())); +} +//// ---------------------------------------------------------------------------- +TEST_F(FilledHashTable, can_insert) +{ + T.Insert(3, "3"); + T.Reset(); + + EXPECT_EQ(3, *(T.Search("3"))); +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, can_delete) +{ + T.Delete("2"); + ASSERT_ANY_THROW(T.Search("2")); + +} +////---------------------------------------------------------------------------- +TEST_F(FilledHashTable, can_search) +{ + T.Search("2"); + EXPECT_EQ(2, *(T.Search("2"))); +} +//---------------------------------------------------------------------------- +TEST_F(FilledHashTable, cant_insert_record_wich_key_isnt_unique) +{ + ASSERT_ANY_THROW(T.Insert(2, "2")); +} \ No newline at end of file diff --git a/VihrevIB/lab2/test/ord_table_test.cpp b/VihrevIB/lab2/test/ord_table_test.cpp index dc604a21a..ddc33fe76 100644 --- a/VihrevIB/lab2/test/ord_table_test.cpp +++ b/VihrevIB/lab2/test/ord_table_test.cpp @@ -1 +1,253 @@ -#include "ord_table.h" \ No newline at end of file +#include "ord_table.h" +#include + + +// +//............................................................ +TEST(OrdTable, can_create_ord_table) +{ + ASSERT_NO_THROW(OrdTable Tab); +} +//............................................................ +class EmptyOTable : public testing::Test +{ +protected: + OrdTable Tab; +public: + EmptyOTable() {}; + ~EmptyOTable() {}; +}; +//............................................................ +TEST_F(EmptyOTable, new_table_is_empty) +{ + EXPECT_EQ(true, Tab.IsEmpty()); +} +////............................................................................ +TEST_F(EmptyOTable, can_copy_empty_table) +{ + ASSERT_NO_THROW(OrdTable T(Tab)); +} +////............................................................................ +TEST_F(EmptyOTable, copied_empty_table_is_correct) +{ + OrdTable T(Tab); + EXPECT_EQ(Tab.IsEmpty(), T.IsEmpty()); +} +////............................................................................ +TEST_F(EmptyOTable, cant_get_current_from_empty_table) +{ + ASSERT_ANY_THROW(Tab.GetCurr()); +} +////............................................................................ +TEST_F(EmptyOTable, can_reset_empty_table) +{ + ASSERT_NO_THROW(Tab.Reset()); +} +////............................................................................ +TEST_F(EmptyOTable, reset_empty_table_is_correct) +{ + Tab.Reset(); + ASSERT_ANY_THROW(Tab.GetCurr()); +} +////............................................................................ +TEST_F(EmptyOTable, is_end_is_correct_for_empty_table) +{ + bool k = Tab.IsTabEnded(); + EXPECT_EQ(true, Tab.IsTabEnded()); +} +////............................................................................ +TEST_F(EmptyOTable, cant_set_next_empty_table) +{ + ASSERT_ANY_THROW(Tab.SetNext()); +} +////............................................................................ +TEST_F(EmptyOTable, cant_delete_from_empty_table) +{ + ASSERT_ANY_THROW(Tab.Delete("one")); +} +////............................................................................ +TEST_F(EmptyOTable, cant_search_in_empty_table) +{ + ASSERT_ANY_THROW(Tab.Search("one")); +} +////............................................................................ +TEST_F(EmptyOTable, can_insert_in_empty_table) +{ + ASSERT_NO_THROW(Tab.Insert(1, "one")); +} +////---------------------------------------------------------------------------- +TEST_F(EmptyOTable, insert_in_empty_table_is_correct) +{ + Tab.Insert(1, "one"); + EXPECT_EQ(1, Tab.GetCurrRecords()); + EXPECT_EQ(1, *(Tab.Search("one"))); +} +//---------------------------------------------------------------------------- +class FilledOrdTable : public testing::Test +{ +protected: + OrdTable T; +public: + FilledOrdTable() + { + for (int i = 0; i < 3; i++) + T.Insert(i, std::to_string(i)); + } + ~FilledOrdTable() {}; +}; +//---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, can_get_current_from_filled_table) +{ + T.Reset(); + ASSERT_NO_THROW(*(T.GetCurr())); +} +//---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, get_current_from_filled_table_is_corect) +{ + T.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, can_set_next_in_filled_table) +{ + T.Reset(); + ASSERT_NO_THROW(T.SetNext()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, set_next_in_filled_table_is_correct) +{ + T.Reset(); + T.SetNext(); + EXPECT_EQ(1, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, set_next_in_the_end) +{ + T.Reset(); + T.SetNext();//1 + T.SetNext();//2 + T.SetNext();// + EXPECT_EQ(0, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, filled_table_was_correctly_filled) +{ + T.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(1, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(2, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, can_copy_filled_table) +{ + ASSERT_NO_THROW(OrdTable A(T)); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, copied_filled_table_is_correct) +{ + OrdTable A(T); + A.Reset(); + EXPECT_EQ(0, *(A.GetCurr())); + A.SetNext(); + EXPECT_EQ(1, *(A.GetCurr())); + A.SetNext(); + EXPECT_EQ(2, *(A.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, copied_filled_table_has_its_own_memory) +{ + OrdTable A(T); + A.Delete("0"); + T.Reset(); + A.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); + EXPECT_NE(0, *(A.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, is_full_is_correct) +{ + for (int i = 3; i<10; i++) + T.Insert(i, std::to_string(i)); + EXPECT_EQ(true, T.IsFull()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, isnt_full_after_realloc) +{ + for (int i = 3; i<11; i++) + T.Insert(i, std::to_string(i)); + EXPECT_EQ(false, T.IsFull()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, is_empty_after_deletion) +{ + T.Delete("0"); + T.Delete("1"); + T.Delete("2"); + EXPECT_EQ(true, T.IsEmpty()); +} +////--------------------------------------------------------------------------- +TEST_F(FilledOrdTable, can_insert_after_deletion) +{ + T.Delete("0"); + T.Delete("1"); + T.Delete("2"); + T.Insert(0, "0"); + EXPECT_EQ(0, *(T.GetCurr())); +} +//// ---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, can_insert) +{ + T.Insert(3, "3"); + T.Reset(); + T.SetNext(); + T.SetNext(); + T.SetNext(); + EXPECT_EQ(3, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, can_delete) +{ + T.Delete("2"); + T.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(1, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(0, *(T.GetCurr())); + +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, can_search) +{ + T.Search("2"); + EXPECT_EQ(2, *(T.Search("2"))); +} +////---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, Ord_Insert_Is_Correct) +{ + T.Insert(5, "5"); + T.Insert(9, "9"); + T.Insert(7, "7"); + T.Insert(4, "4"); + T.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(1, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(2, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(4, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(5, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(7, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(9, *(T.GetCurr())); +} +//---------------------------------------------------------------------------- +TEST_F(FilledOrdTable, cant_insert_record_wich_key_isnt_unique) +{ + ASSERT_ANY_THROW(T.Insert(2, "2")); +} \ No newline at end of file diff --git a/VihrevIB/lab2/test/unord_table_test.cpp b/VihrevIB/lab2/test/unord_table_test.cpp index 15caf2ca2..8c3fa9845 100644 --- a/VihrevIB/lab2/test/unord_table_test.cpp +++ b/VihrevIB/lab2/test/unord_table_test.cpp @@ -1 +1,254 @@ -#include "unord_table.h" \ No newline at end of file +#include +#include "unord_table.h" + + +// +//............................................................ +TEST(UnordTable, can_create_unord_table) +{ + ASSERT_NO_THROW( UnordTable Tab); +} +//............................................................ +class EmptyUTable : public testing::Test +{ +protected: + UnordTable Tab; +public: + EmptyUTable() {}; + ~EmptyUTable() {}; +}; +////............................................................ +TEST_F(EmptyUTable, new_table_is_empty) +{ + EXPECT_EQ(true, Tab.IsEmpty()); +} +////............................................................................ +TEST_F(EmptyUTable, can_copy_empty_table) +{ + ASSERT_NO_THROW(UnordTable T(Tab)); +} +////............................................................................ +TEST_F(EmptyUTable, copied_empty_table_is_correct) +{ + UnordTable T(Tab); + EXPECT_EQ(Tab.IsEmpty(), T.IsEmpty()); +} +////............................................................................ +////TEST_F(EmptyUTable, can_assign_two_empty_tables) +////{ +//// UnordTable T2; +//// ASSERT_NO_THROW(Tab = T2); +////} +////............................................................................ +////TEST_F(EmptyUTable, can_assign_empty_table_to_itself) +////{ +//// ASSERT_NO_THROW(Tab = Tab); +////} +////............................................................................ +////TEST_F(EmptyUTable, can_clean_empty_table) +////{ +//// ASSERT_NO_THROW(Tab.Clean()); +////} +// +////............................................................................ +////TEST_F(EmptyUTable, clean_empty_table_is_correct) +////{ +//// Tab.Clean(); +//// EXPECT_EQ(true, Tab.IsEmpty()); +////} +////............................................................................ +TEST_F(EmptyUTable, cant_get_current_from_empty_table) +{ + ASSERT_ANY_THROW(Tab.GetCurr()); +} +////............................................................................ +TEST_F(EmptyUTable, can_reset_empty_table) +{ + ASSERT_NO_THROW(Tab.Reset()); +} +////............................................................................ +TEST_F(EmptyUTable, reset_empty_table_is_correct) +{ + Tab.Reset(); + ASSERT_ANY_THROW(Tab.GetCurr()); +} +////............................................................................ +TEST_F(EmptyUTable, is_end_is_correct_for_empty_table) +{ + bool k = Tab.IsTabEnded(); + EXPECT_EQ(true, Tab.IsTabEnded()); +} +////............................................................................ +TEST_F(EmptyUTable, cant_set_next_empty_table) +{ + ASSERT_ANY_THROW(Tab.SetNext()); +} +////............................................................................ +TEST_F(EmptyUTable, cant_delete_from_empty_table) +{ + ASSERT_ANY_THROW(Tab.Delete("one")); +} +////............................................................................ +TEST_F(EmptyUTable, cant_search_in_empty_table) +{ + ASSERT_ANY_THROW(Tab.Search("one")); +} +////............................................................................ +TEST_F(EmptyUTable, can_insert_in_empty_table) +{ + ASSERT_NO_THROW(Tab.Insert(1, "one")); +} +////---------------------------------------------------------------------------- +TEST_F(EmptyUTable, insert_in_empty_table_is_correct) +{ + Tab.Insert(1, "one"); + EXPECT_EQ(1, Tab.GetCurrRecords()); + EXPECT_EQ(1, *(Tab.Search("one"))); +} +//---------------------------------------------------------------------------- +class FilledUnordTable : public testing::Test +{ +protected: + UnordTable T; +public: + FilledUnordTable() + { + for (int i = 0; i < 3; i++) + T.Insert(i, std::to_string(i)); + } + ~FilledUnordTable() {}; +}; +//---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, can_get_current_from_filled_table) +{ + T.Reset(); + ASSERT_NO_THROW(*(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, get_current_from_filled_table_is_corect) +{ + T.Reset(); + EXPECT_EQ(0,*(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, can_set_next_in_filled_table) +{ + T.Reset(); + ASSERT_NO_THROW(T.SetNext()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, set_next_in_filled_table_is_correct) +{ + T.Reset(); + T.SetNext(); + EXPECT_EQ(1,*(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, set_next_in_the_end) +{ + T.Reset(); + T.SetNext();//1 + T.SetNext();//2 + T.SetNext();// + EXPECT_EQ(0, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, filled_table_was_correctly_filled) +{ + T.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(1, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(2, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, can_copy_filled_table) +{ + ASSERT_NO_THROW(UnordTable A(T)); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, copied_filled_table_is_correct) +{ + UnordTable A(T); + A.Reset(); + EXPECT_EQ(0, *(A.GetCurr())); + A.SetNext(); + EXPECT_EQ(1, *(A.GetCurr())); + A.SetNext(); + EXPECT_EQ(2, *(A.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, copied_filled_table_has_its_own_memory) +{ + UnordTable A(T); + A.Delete("0"); + T.Reset(); + A.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); + EXPECT_NE(0, *(A.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, is_full_is_correct ) +{ + for(int i=3; i<10; i++) + T.Insert(i, std::to_string(i)); + EXPECT_EQ(true, T.IsFull()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, isnt_full_after_realloc) +{ + for (int i = 3; i<11; i++) + T.Insert(i, std::to_string(i)); + EXPECT_EQ(false, T.IsFull()); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, is_empty_after_deletion) +{ + T.Delete("0"); + T.Delete("1"); + T.Delete("2"); + EXPECT_EQ(true, T.IsEmpty()); +} +////--------------------------------------------------------------------------- +TEST_F(FilledUnordTable, can_insert_after_deletion) +{ + T.Delete("0"); + T.Delete("1"); + T.Delete("2"); + T.Insert(0, "0"); + EXPECT_EQ(0, *(T.GetCurr())); +} +//// ---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, can_insert) +{ + T.Insert(3, "3"); + T.Reset(); + T.SetNext(); + T.SetNext(); + T.SetNext(); + EXPECT_EQ(3, *(T.GetCurr())); +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, can_delete) +{ + T.Delete("2"); + T.Reset(); + EXPECT_EQ(0, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(1, *(T.GetCurr())); + T.SetNext(); + EXPECT_EQ(0, *(T.GetCurr())); + +} +////---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, can_search) +{ + T.Search("2"); + EXPECT_EQ(2 , *(T.Search("2"))); +} +//---------------------------------------------------------------------------- +TEST_F(FilledUnordTable, cant_insert_record_wich_key_isnt_unique) +{ + ASSERT_ANY_THROW(T.Insert(2,"2")); +} \ No newline at end of file From 3196f5cd219d34cb7deed18321925dc67ec8766a Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Thu, 31 May 2018 20:07:23 +0300 Subject: [PATCH 12/16] done --- VihrevIB/lab2/include/hash_table.h | 40 ++++++++----------------- VihrevIB/lab2/include/ord_table.h | 25 ++++++---------- VihrevIB/lab2/include/table.h | 26 ++++++++++++---- VihrevIB/lab2/include/unord_table.h | 23 +++++--------- VihrevIB/lab2/test/hash_table_test.cpp | 33 ++++---------------- VihrevIB/lab2/test/unord_table_test.cpp | 23 -------------- 6 files changed, 54 insertions(+), 116 deletions(-) diff --git a/VihrevIB/lab2/include/hash_table.h b/VihrevIB/lab2/include/hash_table.h index 8a96930f6..64ba7ba60 100644 --- a/VihrevIB/lab2/include/hash_table.h +++ b/VihrevIB/lab2/include/hash_table.h @@ -1,11 +1,7 @@ #pragma once #include "table.h" - -#pragma once -#include "table.h" - template -class HashTable : public Table //? +class HashTable : public Table { protected: int* flag; @@ -24,7 +20,7 @@ class HashTable : public Table //? void SetNext(); T* GetCurr() const; void Reset(); - bool IsTabEnded() const { return CurrIndex == CurrRecords || CurrIndex == -1; };// return false; + bool IsTabEnded() const { return false; }; template friend std::ostream& operator<< (std::ostream& os, const HashTable& Tab); }; @@ -79,7 +75,7 @@ T* HashTable::GetCurr() const if(!IsEmpty()) { - tmp = Rows[CurrIndex]->Data; + tmp = &(Rows[CurrIndex]->Data); } else { @@ -111,7 +107,7 @@ void HashTable::Realloc() TabRecord** tmp = new TabRecord*[OldMaxRecords]; for (int i = 0; i < OldMaxRecords; i++) { - tmp[i] = new TabRecord(*Rows[i]); + tmp[i] = Rows[i]; } delete[] Rows; @@ -124,7 +120,7 @@ void HashTable::Realloc() Rows = new TabRecord*[MaxRecords]; for (int i = 0; i < OldMaxRecords; i++) { - Insert(*(tmp[i]->Data), tmp[i]->Key); // ? + Insert(tmp[i]->Data, tmp[i]->Key); // ? } } //............................................................................ @@ -146,12 +142,12 @@ void HashTable::Insert(const T Data, const string Key) { if (IsFull()) Realloc(); - TabRecord Row(Key, Data); + TabRecord* Row = new TabRecord(Key, Data); Reset(); CurrIndex = HashFunc(Key); if (flag[CurrIndex] == 0 || flag[CurrIndex] == -1 ) { - Rows[CurrIndex] = new TabRecord(Row); + Rows[CurrIndex] = Row; CurrRecords++; flag[CurrIndex] = 1; Reset(); @@ -162,9 +158,9 @@ void HashTable::Insert(const T Data, const string Key) { int ind = CurrIndex; while (flag[CurrIndex] == 1 && CurrIndex+1 != ind) - CurrIndex = (CurrIndex+1) % MaxRecords; // - Rows[CurrIndex] = new TabRecord(Row); - CurrRecords++;// + CurrIndex = (CurrIndex+1) % MaxRecords; + Rows[CurrIndex] = Row; + CurrRecords++; flag[CurrIndex] = 1; Reset(); } @@ -187,7 +183,7 @@ T* HashTable::Search(const string Key) CurrIndex = HashFunc(Key); if(Rows[CurrIndex]->Key == Key) - tmp = Rows[CurrIndex]->Data; + tmp = &(Rows[CurrIndex]->Data); else { int ind = CurrIndex; @@ -196,7 +192,7 @@ T* HashTable::Search(const string Key) CurrIndex = (CurrIndex + 1) % MaxRecords; if (Rows[CurrIndex]->Key == Key) { - tmp = Rows[CurrIndex]->Data; + tmp = &(Rows[CurrIndex]->Data); break; } } @@ -227,16 +223,6 @@ void HashTable::Delete(string Key) Rows[CurrIndex] = new TabRecord(A); CurrRecords--; - /*int F =0,E = 0; - - for (int i = 0; i < MaxRecords; i++) - { - if (flag[i] == 1) - F++; - else - E++; - }*/ - Reset(); } //............................................................................ @@ -250,7 +236,7 @@ std::ostream& operator<< (std::ostream& os, const HashTable& Tab) { if (Tab.flag[i] == 1) { - os << i << ". " << Tab.Rows[i]->Key << " | " << *(Tab.Rows[i]->Data) << std::endl; + os << i << ". " << Tab.Rows[i]->Key << " | " << Tab.Rows[i]->Data << std::endl; } i++; } diff --git a/VihrevIB/lab2/include/ord_table.h b/VihrevIB/lab2/include/ord_table.h index d3ff8a96d..13f22ff89 100644 --- a/VihrevIB/lab2/include/ord_table.h +++ b/VihrevIB/lab2/include/ord_table.h @@ -24,17 +24,10 @@ OrdTable::OrdTable(unsigned int i) : Table(i) { } //............................................................................ -template // -OrdTable::OrdTable(const OrdTable& TabToCopy) +template +OrdTable::OrdTable(const OrdTable& TabToCopy) : Table(TabToCopy) { - MaxRecords = TabToCopy.MaxRecords; - CurrIndex = TabToCopy.CurrIndex; - CurrRecords = TabToCopy.CurrRecords; - delete[] Rows; - Rows = new TabRecord*[MaxRecords]; - if (!IsEmpty()) - for (int i = 0; i < CurrRecords; i++) - Rows[i] = new TabRecord(*(TabToCopy.Rows[i])); + } //............................................................................ template @@ -55,13 +48,13 @@ void OrdTable::Insert(const T Data, const string Key) if (IsFull()) Realloc(); - TabRecord Row(Key,Data); + TabRecord* Row = new TabRecord(Key, Data); Reset(); Reset(); - while (!IsTabEnded() && Row.Key >= Rows[CurrIndex]->Key) + while (!IsTabEnded() && Row->Key >= Rows[CurrIndex]->Key) { - if (Rows[CurrIndex]->Key == Row.Key) + if (Rows[CurrIndex]->Key == Row->Key) { string s = "Key: " + Key + " - isn`t unique"; throw s; @@ -76,7 +69,7 @@ void OrdTable::Insert(const T Data, const string Key) Rows[i] = Rows[i - 1]; } - Rows[CurrIndex] = new TabRecord(Row); + Rows[CurrIndex] = Row; Reset(); } @@ -107,7 +100,7 @@ T* OrdTable::Search(const string Key) if (Key == Rows[i]->Key) { CurrIndex = i; - tmp = Rows[CurrIndex]->Data; + tmp = &(Rows[CurrIndex]->Data); } else { @@ -151,7 +144,7 @@ std::ostream& operator<< (std::ostream& os, const OrdTable& Tab) while (i < Tab.CurrRecords) { - os << i << ". " << Tab.Rows[i]->Key << " | " << *(Tab.Rows[i]->Data) << std::endl; + os << i << ". " << Tab.Rows[i]->Key << " | " << Tab.Rows[i]->Data << std::endl; i++; } if (Tab.CurrRecords == 0) diff --git a/VihrevIB/lab2/include/table.h b/VihrevIB/lab2/include/table.h index 05bcce1c5..6a8cd27e8 100644 --- a/VihrevIB/lab2/include/table.h +++ b/VihrevIB/lab2/include/table.h @@ -11,12 +11,12 @@ class TabRecord { public: string Key; - T* Data; // - TabRecord() { Key = "EMPTY RECORD"; Data = new T(NULL); } - TabRecord(string K , T D ) { Key = K; Data = new T(D);} // - TabRecord(const TabRecord& TR) { Key = TR.Key; Data = new T(*(TR.Data)); } + T Data; // + TabRecord() { Key = "EMPTY RECORD"; Data = 0;} + TabRecord(string K , T D ) { Key = K; Data = D;} // + TabRecord(const TabRecord& TR) { Key = TR.Key; Data = TR.Data; } - TabRecord& operator=(const TabRecord& TabR) { Data = new T(*(TabR.Data)); Key = TabR.Key; return *this; } + TabRecord& operator=(const TabRecord& TabR) { Data = TabR.Data; Key = TabR.Key; return *this; } }; template @@ -30,6 +30,7 @@ class Table virtual void Realloc() = 0; public: Table(unsigned int i = 10); + Table(const Table& TabToCopy); virtual ~Table() { delete[] Rows; }; //? // virtual void Insert(const T Data, const string Key) = 0; @@ -71,7 +72,7 @@ T* Table::GetCurr() const T* tmp; if (CurrIndex >= 0 && CurrIndexData; + tmp = &(Rows[CurrIndex]->Data); } else { @@ -89,4 +90,17 @@ void Table::SetNext() throw (string)"Table Is Empty"; if (IsTabEnded()) Reset(); +} + +template +Table::Table(const Table& TabToCopy) +{ + MaxRecords = TabToCopy.MaxRecords; + CurrIndex = TabToCopy.CurrIndex; + CurrRecords = TabToCopy.CurrRecords; + delete[] Rows; + Rows = new TabRecord*[MaxRecords]; + if (!IsEmpty()) + for (int i = 0; i < CurrRecords; i++) + Rows[i] = new TabRecord(*(TabToCopy.Rows[i])); } \ No newline at end of file diff --git a/VihrevIB/lab2/include/unord_table.h b/VihrevIB/lab2/include/unord_table.h index b0b7826b3..51d14751c 100644 --- a/VihrevIB/lab2/include/unord_table.h +++ b/VihrevIB/lab2/include/unord_table.h @@ -1,8 +1,6 @@ #pragma once #include "table.h" -// -// -// * = * = + template class UnordTable : public Table { @@ -23,16 +21,9 @@ class UnordTable : public Table }; //............................................................................ template -UnordTable::UnordTable(const UnordTable& TabToCopy) +UnordTable::UnordTable(const UnordTable& TabToCopy) : Table(TabToCopy) { - MaxRecords = TabToCopy.MaxRecords; - CurrIndex = TabToCopy.CurrIndex; - CurrRecords = TabToCopy.CurrRecords; - delete[] Rows; - Rows = new TabRecord*[MaxRecords]; - if (!IsEmpty()) - for (int i = 0; i < CurrRecords; i++) - Rows[i] = new TabRecord(*(TabToCopy.Rows[i])); + } //............................................................................ template @@ -52,7 +43,7 @@ void UnordTable::Insert(const T Data, const string Key) { if (IsFull()) Realloc(); - TabRecord Row(Key, Data); + TabRecord* Row = new TabRecord(Key, Data); Reset(); while (!IsTabEnded() && Key != Rows[CurrIndex]->Key) CurrIndex++; @@ -62,7 +53,7 @@ void UnordTable::Insert(const T Data, const string Key) } if (CurrIndex == CurrRecords) { - Rows[CurrIndex] = new TabRecord(Row); + Rows[CurrIndex] = Row; CurrRecords++; Reset(); } @@ -84,7 +75,7 @@ T* UnordTable::Search(const string Key) while (!IsTabEnded() && Key != Rows[CurrIndex]->Key) CurrIndex++; if (!IsTabEnded()) - tmp = Rows[CurrIndex]->Data; + tmp = &(Rows[CurrIndex]->Data); else { string s = Key + " Not Found"; @@ -114,7 +105,7 @@ std::ostream& operator<< (std::ostream& os, const UnordTable& Tab) while(i < Tab.CurrRecords) { - os << i << ". " << Tab.Rows[i]->Key<< " | " << *(Tab.Rows[i]->Data) << std::endl; + os << i << ". " << Tab.Rows[i]->Key<< " | " << Tab.Rows[i]->Data << std::endl; i++; } if (Tab.CurrRecords == 0) diff --git a/VihrevIB/lab2/test/hash_table_test.cpp b/VihrevIB/lab2/test/hash_table_test.cpp index 1f9b95781..d11b0cb7c 100644 --- a/VihrevIB/lab2/test/hash_table_test.cpp +++ b/VihrevIB/lab2/test/hash_table_test.cpp @@ -34,29 +34,6 @@ TEST_F(EmptyHTable, copied_empty_table_is_correct) EXPECT_EQ(Tab.IsEmpty(), T.IsEmpty()); } ////............................................................................ -////TEST_F(EmptyHTable, can_assign_two_empty_tables) -////{ -//// HashTable T2; -//// ASSERT_NO_THROW(Tab = T2); -////} -////............................................................................ -////TEST_F(EmptyHTable, can_assign_empty_table_to_itself) -////{ -//// ASSERT_NO_THROW(Tab = Tab); -////} -////............................................................................ -////TEST_F(EmptyHTable, can_clean_empty_table) -////{ -//// ASSERT_NO_THROW(Tab.Clean()); -////} -// -////............................................................................ -////TEST_F(EmptyHTable, clean_empty_table_is_correct) -////{ -//// Tab.Clean(); -//// EXPECT_EQ(true, Tab.IsEmpty()); -////} -////............................................................................ TEST_F(EmptyHTable, cant_get_current_from_empty_table) { ASSERT_ANY_THROW(Tab.GetCurr()); @@ -73,11 +50,11 @@ TEST_F(EmptyHTable, reset_empty_table_is_correct) ASSERT_ANY_THROW(Tab.GetCurr()); } ////............................................................................ -TEST_F(EmptyHTable, is_end_is_correct_for_empty_table) -{ - bool k = Tab.IsTabEnded(); - EXPECT_EQ(true, Tab.IsTabEnded()); -} +//TEST_F(EmptyHTable, is_end_is_correct_for_empty_table) +//{ +// bool k = Tab.IsTabEnded(); +// EXPECT_EQ(true, Tab.IsTabEnded()); +//} ////............................................................................ TEST_F(EmptyHTable, cant_set_next_empty_table) { diff --git a/VihrevIB/lab2/test/unord_table_test.cpp b/VihrevIB/lab2/test/unord_table_test.cpp index 8c3fa9845..4eea4ed0e 100644 --- a/VihrevIB/lab2/test/unord_table_test.cpp +++ b/VihrevIB/lab2/test/unord_table_test.cpp @@ -34,29 +34,6 @@ TEST_F(EmptyUTable, copied_empty_table_is_correct) EXPECT_EQ(Tab.IsEmpty(), T.IsEmpty()); } ////............................................................................ -////TEST_F(EmptyUTable, can_assign_two_empty_tables) -////{ -//// UnordTable T2; -//// ASSERT_NO_THROW(Tab = T2); -////} -////............................................................................ -////TEST_F(EmptyUTable, can_assign_empty_table_to_itself) -////{ -//// ASSERT_NO_THROW(Tab = Tab); -////} -////............................................................................ -////TEST_F(EmptyUTable, can_clean_empty_table) -////{ -//// ASSERT_NO_THROW(Tab.Clean()); -////} -// -////............................................................................ -////TEST_F(EmptyUTable, clean_empty_table_is_correct) -////{ -//// Tab.Clean(); -//// EXPECT_EQ(true, Tab.IsEmpty()); -////} -////............................................................................ TEST_F(EmptyUTable, cant_get_current_from_empty_table) { ASSERT_ANY_THROW(Tab.GetCurr()); From 010580c6379afae977a7d2550701b5ab1d7daaff Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Thu, 31 May 2018 20:09:35 +0300 Subject: [PATCH 13/16] report fixg --- VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx | Bin 108558 -> 0 bytes VihrevIB/lab1/doc/Otchet_lab1_Vikhrev_IB.docx | Bin 0 -> 76112 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx create mode 100644 VihrevIB/lab1/doc/Otchet_lab1_Vikhrev_IB.docx diff --git a/VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx b/VihrevIB/lab1/doc/Otchet_Vikhrev_IB.docx deleted file mode 100644 index fc0f16fd9ce7715958dc00b19713f06ec92e7b14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108558 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 diff --git a/VihrevIB/lab1/doc/Otchet_lab1_Vikhrev_IB.docx b/VihrevIB/lab1/doc/Otchet_lab1_Vikhrev_IB.docx new file mode 100644 index 0000000000000000000000000000000000000000..a83ffd83e44cdd6c736c3f39054b5b4c8ae811ed GIT binary patch literal 76112 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 X=6itEzZo#{LH6%~Kn_U)1_AO9po}zC literal 0 HcmV?d00001 From 5a26beb0eb2b1ee85aaeb749e3cb99b9f3fce7d8 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Thu, 31 May 2018 23:41:54 +0300 Subject: [PATCH 14/16] report fix(2) --- VihrevIB/lab1/doc/Otchet_lab1_Vikhrev_IB.docx | Bin 76112 -> 76532 bytes VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx | Bin 0 -> 119022 bytes VihrevIB/lab2/include/table.h | 3 +-- VihrevIB/lab2/samples/table_sample.cpp | 4 ++-- 4 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 VihrevIB/lab2/doc/Otchet_lab2_Vikhrev_IB.docx diff --git a/VihrevIB/lab1/doc/Otchet_lab1_Vikhrev_IB.docx b/VihrevIB/lab1/doc/Otchet_lab1_Vikhrev_IB.docx index a83ffd83e44cdd6c736c3f39054b5b4c8ae811ed..6d6a510c45e2081ce6576d9b0c5a4c276f52149c 100644 GIT binary patch delta 45338 zcmV)2K+M0;(ggI?1hA$F3LbWg*XW!804c_kun8l76!am9V~MQyLy0)3r^kTDBgita zAA${r zi@_Ox^OP_cwz`|G?OwNi?$mqj!Kr^(`>+4y=hx0|_BO8Uw7Wxr4AC8&y|%k??$qVs zaQE!$>R{t?d#5#6+39TbdxPHAaAl*nv)bF*>TI-Eul4$ytFkDG_-VJ_+h`94Ju$<7&UXOwV4i0FwbASB-zLbB89bmJF) zH$n}ETuG}pfSev+_tJF4d9B~OvKx=qnQpY#yYEC}fn?VhixHWh+F&|h-n!h{B@(!^ zarX5~-Cn=7zD*z^BoheM1z_t_YeeI$_cq^y-@D|pdUm(fZ@s>G?v(C}QXrc|?S{$Th9epjT|f3-m_ zUu|ulJGDXNzul)-`)vI8!<({6Zw%gd2gz%z?AxmmRQ=pJHXQca+2Pvgi_vF)qd$}X zz8QTx`s3(p{C#iqr7-$(^eOrCccVX%Pxr`g_|pFqMxP1f)9*%q8GQ~Pza}@oA^-bq z^l#+n=j5+{6Gnd}1N{L9``zf@$*s@ejYIlgI+-lBHOG|#+j5uGo-4KgI@%vS9PN*< zkM>4S#vhNKjh>J81@gy(@lEo75&nD{UVJ{fkKg;Ae0nh2BVX9(o*Ca7e@JfckNyq= zl8XnU{R(te9LJPAbxCKQ&O~AMw){Sjd-&cidDW$UYv-+Dt3PCe&zuh)jPHzZj6WiT z`)>3+LAC;D{O;y_U;$HuWFarw?Y9T*{?+!WwG8(GgN^T2U@%!yO-ELLofFDn>kOlF zQ782W2Xg%9|0Nb-Z~SYb0YHN=#WKD#dL$5<-5B2(JwdIL&?4mOWAebG3KTV5-*tTD zq^gVsq$r{10nzKI9EcD;A3Y4oCE%qS<6DHDd*kcm(@jEEQ2&(R?{ z*MtkbomQ8Aafa%X;bP9OM^*9}(U+h*iGn1KG%CnvNj=wD+1E)Y@@Zw;L^i02=m zQXmfcSLBLPZhl9!_fiYR${V=u>73`2s@tr^V^g^>9( z7ZqPMJrU+OY32;>sxwc1eeq_0Zpfk>7;+VwpR}3lo+w+6`SQ(NwmnaGDrIX=*vv)8 z&_&0p;wqi6nX9&~`=TbjgmUf&rshg7t0$B7PZgP7=lxT9Z4O>flh>n%^yTQ=(f=9! zarA8k$3-#&(e;c}7%e%Tss$b_K~5m?l#a{dIjc37B&Kv`Ure_MG1c3D3l<9tC+s-h~QZ|jXy z%!e&R+wCnfx~eGPCnDbY9?` zd$UD!DYd8b`0o)%=L4)Cdmy9=1n16HYb$e{*r&Wxvr{zKtottAKzXPMql7oif`%i zJ69V7i}Ih1z9sj+ICNe|Z**p_>-Nq=Ru?~Sx6nqlTZ5rJ=(LE9zjEfn+iB#~b%L9) zT79TSpA)(ug|KGk0Z`~(sZux`Y>oa<1VeKUt`9{L5v%zL>>v=`z-sJxDS^T-%N#)h zyCMQZ!~hz9!rxhRh^l5OjtEPjjh0r6(NSq>b+&HX-7*6 z9mk##0@n{ry-IO&E+d>UbQrSaI9l^cs}m*{vMWl8<25cqI$`KgbzN3fyKyzzNkfNB zTnxoM#%tuW6&A}lPveVh@(5bA4GhtI( zj|*Jb6|M>0^-7{~$mE_tEU=yD@qnfg&=!(wjYBqZt=Ue^ZKd=9a`|GvV z_IA7fUii#KXyYREwgi{phzR>2@#x##&c9rLY17y7qpfmCCLjFnW(mTxQWxU1AWgyH zMonoH{$=Dd13HK2J==C|J+&q$2d3y62G-ofI+&nL1V@Y4Q6z--omiMTK}d>7f#mMK zHGGetmCd5HCDDm>uk0|IZC~9^F$B5ydPK=Ea~C}@Wr-bEZmSpQX!t>F-#3_Dh1HjT zzq4J3RcaVD!}o%~2rB4AgM`0m8#9yi~AEaq*vB;TJuB;gocSgfqXmEd1hq;TKnMDIj_>2lzw8;Ghli zG2{#t;TLkJPpslQz;)e?%RK_lFE92sG)dD8MV8ToUhWKrz5aWIq;9*Q_PVLnMhV=)F{iZ<4x1N32L)&QCW+lfV&jobusXCQ3a%=r7dAhh%KN!mdO& z(f_2|-uJLWUAWKY48O~U>x}S!NEm&OTjHUsPiFrD2XAeIRO{Kw)~D8}O-zkcW@>7@ zeWrNGH6rzhv!+f(+*z3iMH3B6GN+4rmgZrO<^i*)hi@KuR+X1_ps5}BdVGu3`wQb?Nu9poN8s7Y$sV;rJM+TFP~I>uPubWH+`H6YOMQPN`X1MRwHGoR$i%qE z2mOm`25>?4JB$RL!iHrUGc3)3tejLcpf83QkW^JR-1(XTxvCk^)TJ3nn*qf5Y|KEu zPEuBu>74>?{U!0wi7E~k59yX;*x~yacR*Yp-^r-%@tvj8mer-wo~P2*e8+GV)n6*@ zMOE5Zl`&tXz0AcVz_=WL)thV(p6kODa1$9T)&iO9Y?HeI{!2kKS$^@#IR{Yq8UZ>rfg057}h$5PQbtNx|O zUgWX=2hq#-u^ap|SU{yG!0ZXwT^{uN=RvT=_Aq7 zNQ8N7>7|QaMN8w^4|p0I(bLey6E5)0MjyrM`}ycGwD|nt`WN7P;|P#RfAqukKQGlf z;p(MYpKG$*b}Zjit88;#s`VpL>sZ7;Z?(Q${wz@IpNEoA{%hpmg&o>WZ$c}*;cezlx zh^kpB-J&@g)x30<6JX4Ep)ylCNYC!U?xL_nc>vpp=;0_!eXo@6SFQ2(h12(vxDX0o z3`E0IH7H#^lB)8TU7a7%7Se=<`V;JC96cF-5+3H9-C|#VkGW5T<~gz37p1aQj>FSD zimh9+A5`h8x70jy&^$BTomik(zTwt@aD|8-1-}=T;x3hpa$@()No7IA;VBtIR2)w< zmYe1lRt?Q?(_Fq9TBaGBx58k@;5;Awed!p+9D8DQ_F^=)P$kEfM5{`x_GJ$8NOU%0 z{Ahz#by-n=+Z1>CsxD923(|^!*#WL}Yy2T>sepv#ZF1w$=t<%6M@PEjz1!PtA3k6_ z1S<=Pm&;SB_>*D4PwZyL1u@`~E!l?WKx%Voz!%bh&v3WnjP;YctihgZytW8LE>P9- z$`QB{6Tv#B{?9fM?v!q=7ZmiWAb`EK7 ztjj#hrLmrku{IXnSP$ES;o$?uL-5Om#LESLsM3OBZG#U6=*vmZPqiCCs{XVU{k;(E_%Zo()UStSk*Vs<9Jm$QR?NbkP@m({|E( z5-drT4QfLoL#}IzF5=pJ+K{V`rYcZSfp^Zsr9f8#OF`jb2CLJB=8#*R{$ThH;1D6(ZC&D+EuWIA6*#UIz}qImAnUFk(Tj({ zmJL(FrHY7>mTh>N&r>q#r78IyN?qI82o-*{3%+zGHw4-gg0v#I-uU-g>Y1&Q7cU&RfG)e@GtcfZzguRNWT1 zK77+>hVhgz>8fa&avfocg=L#Sc!7vUyWieCPx#R3w_ESvONMKsdw2@j!-6f8A>2Mv zm_p5DK1YUZUpGuIbpVNCiLz{YF|(q+QAJAum6eqtI?)3DO{*AFk#*`Bld1fBS|9Uo z^cBO9obaprqbK8!qf;}nCoS}UAs^kxBQy8LH}QAWtd`!mneF1nzkvg@$Uatlyf%f0 zYd>87!<=Bt!8Bsz`xr0S>8UJQ{Yy62ohKBQ2Z6RaGJKP-EHi)QOa5WOWl zPHJBu!@gj>1FH3B7OWJc2;EVrB4gvTdb#a98KYgiUgI<$t-Tr??MkoI2AYV+YiaGwH|?v)MV( zPtnqW(8F(zbKquD3q1niLF$cvLq;Y<;_c!s;Hc;DgUT#$*;8QFP-Ni-iX5RTxpBIb zsJv{gA=EI;N9?r-9UABlDQAN^UlB%MlDU=YL(?)0QwxWECIE5(2cW7cVjjS(?{jwT zF$!E-F-)l!sDk=`8}YoppaMbMFQ%y;P&5euNy0Zt$<1h=O!$xEPs<=-eAQG#O`gd3 zw+JoOM8r2L_ii|7))0-~5w%OGd7qFL>~T^Lpeh2*eTOML%5A*Q@ffu?o`U`z{YBs~7440xOF;O#j zq)Upci%Jz8lGGGzYN-INJfW0L4dy14z+!Ze=G&NmE|d-I&H;a1xUx+y;E^(kG|!9UxB!2mgBm;4;KZgw3l{aT18~vF zZJY+uBwcdsGBAIVdVCjF#r%G3+%EN7JE)UQQ%bkm@bA9&{wrkwTAFNF^_fgS%vAy1 zrz=h~dM(mwAE-cZ|1mH*@R5kr6|6Z((~2OBJ|{2v?f5p4qyrR|Fr15+;UUj2l)rzt z{*%EV6@NszgG>?;WFqeHiUV+0b7XrCXvyR$Yq9NQ;XQNu)#l7KdHB;moeu3)d}+}M zG}{VN`_*(!*Azp8BS<)DNSfwJ_Bwf|X4)&XP>}I_fj=?d73PU@LoRv=xEaGW)SFbT zKZSG`3St_e_@iRR@wHy>()NS~-3=CK>VR;uJ%1Pujue7`@N@fGum4VUD5@n-e8)CS zT#sLHzwtA|f*(K>&eUX>;e$VFAf<}GsCuTW>PD4=4r?MMsXXd9kuq906t%~YQ9;ps zh(h;wqRM~6G9n4D#-{m@#5IRL2|^Ac3+au>{EVJgVHwF)Y)K4K>(qGieIJu*$8D_VS- zD%OMTp3tXw@k`}QFDXs@9Qn{Rg#PJKf)To*W)Z0EdsLU?_E%uz|k)oi7 z`lChd@HpC2!Jg=c4O%<9#m;Ef#51&U)8gL84_sJ_UHtg0wz_8pAr0J0``rl+c!Doh zgwdZ9h6h{|SaNw9t=O{lK(s&)cz=s^(7??D06br|JO)64|D8^z6g^+L_`BfwNoC$x z;(ejLMbwj|h?Zmuzvz}#dDjCow>G;7QxNkJjIRip6SC^PG*LNR_P)Y&QxPksoVubs zOd0r!t*Y@740{v1$gps)?0Kd-*;ldNv%Gd-;tLBiqO`s!HFmx1$>hl}%{7^Ejf0u$bU@`%UN+enHk#774+a{Hb%l3Oporr8oa!^M{I}>N(H6lH$M}{aQ^NGZ0OYR&0{7pp99!%^?E!Z1H!u>yOPJpRM=(#;VKfhu2-s-W&N z>#|Keg)*Alz?cfG*^>!$X(nQs77{fakC_T}eSw%fxBotWdwk7TB_%Y(tH(~G^5CDD z2KXX4)680=L<;5g-ozE(*m=Ag*6~B?71Oq1)%N4@tyH|Tnx9=YbknuXDytZ&WM2X! z;YGf(K5?f!<;t5LfRo)U!4u@LF>R38W0Tlqch7dZQ1vHl zb_T=VU*>i>{Uo5-Z>oN+bLJ)??-f5x^{Zw(GIama4Ct5 zwYY8F2vGPNL0qMi09Xh8jSB=ltN3}?Zx1&v!^bT$S9X1syMc&_aRGk~h}IC+ul-Yh zZ?nzHf8qIexB5Hqn*b=hi==yxfkV+#Cey3&Opcm!*Ai7Qu&Z5f#SFB?29PVx@vd zrCPeCNa;c%RrLeK#pB&4P`!A)c>>jA=1wd)P3x-@LXPjkuHUK*vlcq+nHq~|7v9uW z7P#9QSJ4t|Muc`M0#~f!ES@?-jIJH*2Q1BNPv*ALz_WsgA_sgAs0oV}r^}NhXG&Ei zYz!`I{E-+yBT zy5396mM9bNE3b&JTVSd9x*AxOqVT4*Ulk)w_%XYnQnxKr@_mSv`Jhr$d{Z~> zN?p^SY-lz?rCbnH(o&ygPDBP?;~&$33XjfH5ny_L1psdgrJgMDpuq(4JxrHFcDNz``$RHgjOlZisETQ%dp-vuc%ceCdctp z%^F3+Fm=mK?m(YukdaJj7xh(4*;@APX{ucdom}Y4KzlU(8rBcWF&@?4K_xs?Z?LNG zxC{@R*ym8Pc>u$NLxf3xcUnZ5*No;g_Y9O>;wGT+N8uCu*l2|ni6+O4VxYX}xYPj? zv3=z15KK3sMzQ#l@h5;M*gTjB%Zp&jBpWJ2wT?eweWVc!6qoHZ2dN1sKBVO3$sZE8 z0v%I|vjK6-(O4xxGT1m|OjZgUbV>DGE4@UOA2>*&Bc*qel(eLO$adS{TCdKefWKl_ zi8^{R#$Vx1hf9&5(h15BozmCT2I3`lX{s%n-_{*5_E^M^a)*(T;LF?1q$iQQL;@?nHCZQ$@ap) zAJaw95bH7deG5x}ks7!!VI!Kn?HZbFo3fnV9F`~2exO)EybqWoLh=q0K~hB9$UWge z3`D{TJUeGL$$gWYG^9~!2cd$BQ~Fqyy>JAzqUpM+E`E}$`-+y@-j$keVlliL4h%=J z9NM5Z-;GAP)M(Qj(vdxoQd&jK_YHM|xn%AhSjYS5C4sMh1RF2+OZ(B#$@4U2vQy2R zU7CE{Kz8hjqb4m@ITC~_6&R}L=%$Koqh=}#OFm!}V_ScIx!qaM7vUsH^Qol!k`j1n z5w1d|<14~np~{CIhBxO;n?n%Qe7b7BBq@rK+8wH@fu*W`oPy>cSduV_ta!PjNiOqBs>rs1i+7^{RF7E8=MhwqYiG9D0zt*KK3 zpJw%SIZj>IP?8JubBVe$TwR|7TG=gsD(GezaG6e0GRn#|S zdN7NBa8f}TbbFg~aF8Yu3EsD|PaY;3n%eb8b!04v53;LONvayP(#)g&5%n}3D+<#4SYss!K& z7;sgf7cErFVbwY=aubtwqd_LJDtjLyKGxoUoQrlia*ARn$9*IjR&FFuC;B9*nexrA z80fC1cva5FT$!tav0ZrqIprw6X+Sj?@qk=SCn2%aG33gYtJWFz& zbdye9HEhX?tG1SQ_n0sW9ASfY`M8SnQ5ceiQB*sTIf9HUcm_< z)5h-ZOY0fTe&S6MO!Oe}j9EJzx1~{*?)gW_@6ttVUQKjBo{iD-B^ z>wGFtJzvNS%@%#bNuO`0NtWbtTPAaaY*O-Vu_f;Wl&5o}*WvxtDFrB|xi;$sE7(e& z$Mi8Pqc%Ppd%=j%muC9Yo_sknra?< zrkl2*N_J}3v@AN3>`TdA2a2bQRxXy4cdGAmjewqF#xdse_R1pjWcSMAZr}{9IGCr0 zYr^*C^rqYNUfLp2N1r?1ggXm33!T^KB&qUKxpm8MYb14;3R&_U(JCY=S-xF;+*$tJ=GKc$X`j2=C6X+x{HU^^Yg&Aq^xxi9F7IwyOTLm9<)Ccr$30BomO$1 z6xUT88?7`qe^FNhQ#9j$y(8sQwM9e6{mL`dUZ^{>+6z^2jKGBU;!`5yUzahK;~APq zn=}+L)&UO3b%=%Xu#hg$_i%h;LL|ZPLLvR(`WICJTH{O8ChaRoz2wi6b#+)doO?!t zq2?3&W-~hEp z(6$&P37Z2$v{Gp7^6{jLj$wLg%BG2~7Y_UW5`7sddK|+u!16^&)izo+ys0XP? zP8|~Lde_?2YZfTI1KESSWgl&tBYbl%4*63VE`kHKS zsE(~!K`PSIMG0KIDb&Lep!Tcy*g}G<2}n(PEEDtxo}5F|lpoNZ=GRYC{lsp@zEgp_ z4Vg@oZRiM;h@rSAPGdJhJf8?NTLNo47)cuO9dT9!-Y3O>iBLel5-0&{hdEpu|7#tg z2XBM5MI`h6b#0CkT}?7&+@;E|ya$?3{*@}ygmze1HoKQ4$1}oac&ZX$4kY_2@4;BY#vswR0q78NP{beHvOhZXW`?@FkE^hOf-tZ?gigmjB<#<(cm~+kTDOTkj zRn4xXnzkw;|0I^y6wwV*3D{goW=iO&B$;&)&s5gb#Q*0+UVl5jJ-$t_4{;f@yAksd zf&Jn7@1Z+v=2$vZ2vN7!=T#(GSA9+P)2@zTNUCgqIZ?I*aqc;i>?{m=a~K!(*b5p3 zClIzGjQ%%2Vxv_V}(MOZI?}>*0jng()m1IG1CZN%?tR zwtl$&hbbYCc?OQ>yD5m&1FF~vJb!PGb_#gS&)^*t2#H@>725{A^KOdXV-U zIVD8=?~nBT5G}$=Hh2M547ui5vT3>*=SkKbC*@Y=!d~oaCclo>or9DSE9@7~=TBLB z8Jc#LW}h(tWruB{QQl)|3f64?AoFFY+-a15tX2cV6Gby)WNFn6>uqI(fH8tg7kM~n^DPsPWY}bc|mHqu10TQRaZHCQeNehV<)~sUX9vr zjc-MVbLNOBbnSw)RHy(j0~TWI26xs6o&$o--%l4D-AOGFT&4#Nvg$Ds(NLWN%*Oa( zKRRe7PQ6h*g16E@J_yf=1fD`+q$$@-UrH(s01q%ZHJCVlRJoQ5WMl>lR&3ILD=y(t zicrfMYCmp{2W%}YlGIFh{1o>yic|Vk$>YeX7C64sxR9Csq@vtiVWI&JEhVZ9 z*^BZ6CctG=u^XwkTEc)>FX=)~C(450`{sG(M1w08!05WfS`^*m?6 zgIn*w1p-`^0Pz4l9*+mo1Ty=7MELQmKRzw|_{@*lY6X1^-bnNU#L!Gw_=Sd8CaP#o z;t~3qs;7^!@?}{Qz0!jb7K~B_ChT+2L_mbFBjR&@K`2B$;b8^G5b$+^h2@0I9*+u&HJ{p97JCR`+!AV#Z z7(Hcgm8BHPf0G^F zbOxb$?vRcs$)cl_o<}q3oUR5i6{e1k5T?Q$OI4V%u5%eDL9N;&6k%@tn#yAor@@hA z=sGh={3OoUm#H1@%$y;AR6a&)^Y|(_84k7Ai)^Fc5`brq@az`)0-a(iq8exo+P*EE zTksVc6fnYZgd2OG8G^@tZL-FviYAstoiMD^;NX+R!dhw3{$J76heO985fZtbxxpjt zNSBDvvH5W#Os|4j#q?ZFHq!|r&$LB1b%tjx%yOq$)Yd(tZ*q!%YA~RBfl*m(*I{9U z8ZGn#;^3`JqiB*M>xmr&GfLc7onKL5G>tZ4%{My8J`6+1lv$Y%`r6Q;5S<*jL}Jdr z(UOqd0GS1>%yBv`j6cNB_n8NXf{IyJf<o7KnwwVRIqqAzzez^i!ulzqN|oLC(~_M7my%I z6|}2?!Yv!U*nZ zqE35!>omXYgKI?KCp?4?RaH4gmLQ#=J;CM7>?$kM$cZwXpB&07&k)XAA?{C#t8+9& zQb9wuk*aqHbi>>xC=kA$1GdzHIzm$rWuhq!BA{vZb$siUDjYAmfh?++zdIr7BnLqu z6Ve!lVv9q6>s{bujurRUC&zOt?xo|CNU$vH6)WCxN`Ib*8D# zs5m!acB+{dLop30z%u7XIAvO@8cunKxXdVkTOOW&PoJ}70-j3g%1)75WlPPn?&?vX zpWTc5l)AnIffS8}&J;a;g?M7#9?k1z2I$afv=U1S< zk!Nt2XyvfDBr!ogii=81Gm;nRDmK7aY~>v81}+r0+(no;Swww;64LW%t|DntpgM5& zZ4z^Tif(I`>Ekx(2y@AjhY7_HhmX1HTY|#1Lj0?AOAy4J;QA%;3KE8Ejogl*DySx0 zN@C-b2cfH$;|G4J&rGGlwnWFM+KA)u@&8TIgQb{Hpfp)OFrku#2>z9o)Q%CTifiDuMt7BfNXS^VuW)T^`-3y8SfV}N4jo=axVig7M8^?exxxEOS zT!i#t6~(FRiXKQ#%H-&tWx1-D+#jAR&8B4-n0H)EhPaos`%Jb0iPW*lEH~7Y-OO5l zSu*F7%O6F{NBQwb-OyvY2~lUTcsZcPgmMLDlI~*c#Hd#;MYQrX$FiXdJ2L@MeK~N| z1_AT2Fn3?YAx@NAMl?T;@)J}$rSXfE8n{xANzu~zs+>Z_)v|9a$%Yb z5vKkq)@fY!yx{F|xCoxfEdnY499_k2uRue}70iPrFy1PMkfENwq|$Mhwh{P*F!gC& zova8=YaNAYxaJDy1Y0;GIQaWj;U{OLSA?HBRWygM*gp9$39GDXhVNO)ilk(J_ala! z)J1+rUrw{6c!52n*Uh@4pauR>(il6_Bh zQv$6knq&uF(jTpbquH+$hZ_g#rRD2|c(I8qLNmt`|6*1eVi_P2fm>>BY;;K_W>E;sA;gWF%|35NWxqu)Mh=VF8><2hV*( zRc6ZB8ewU2Q!}WWmS*{4ssK{*RMQXa*a6AndeNv*AT@anJyNVaanB_ak8C)WqHmRP z<2{mP0+qukGjK{Z-PfElX?c1m*U7Z*FLPla3Nab zNlmo&I3> z27Z^Z_pdfW-rjC+p|VNwbaBa8&0f5kB0$BRCPnN zl0CS*Kv&%O5(R^`(aixP`E>+iLHY#KR>zqwpbF!Gl-$m^QE-ueRZRB?P75^&soNZilrNVraut9SZgZlbthDz2E6RB^O*ua zOFGcr~gDQdF zG(bUQr6Ut}o^vhssw6pd&2T*>y<(kf$a6VPlU2jcRdmU(r)QO~=(g4qHk22V{*^Nq z-Y(EPg*d1(&NY^0tAf#s<=AJ)sPX1$ca#j*He18itf5+e`|rN5Hy-OXnkCISC+4&1BNuxC4&a)Cy9jIA)-_={_x@tck9VU2W!UslLEXz)%T$ zr&32pUDh3cSxJGrG(j_G{ngcYVJz&A0|_ixOiOWi<+gE+C18YmUNB&TRYdyfKoBx9 zTE)(AGuFlhn8M58(uP}cuzIutlk1upXaQ!1c$xH!z;SR@e*%-2$Yf(CFJ#{-Elo}4 z$ylQFmWf&%khCd+XJ531bHbZ%zwyRt0R{)Fbdef=fj9mCc9GocUfJH>9rlZKJPevD z*35a+D`k(TvH>}dCkk|Q-xhLzTefv+ONLrK!62JKCYhaJk?iJf_QL{m zi=ExY;qHL@;&I}MV>=G8zd-s6_e-v-NJ%6`N+pSsit1{>NjE8xRnL1puh7W{33pE$ z8&SO5#JW&7Db{z4cH~Aj_KI#{H*%OO^VtpB>qGmMV-=*UsCpW>B#xK}G-uETsS7E8 zjq|a*>L9Vf&%{3u;6$~)7)fsy55m&Omcr#iMnPiZMAa* zVIpfp*5jYOXp|+JT=bTa9zycReZL6;( zil(}$$L-dGZDA#eaZi;)+SsYs20j~mtIlUBXLAUc3m{f$q)=dU!_kJL_kyE;PcQoY zc6UJly=JDajH}P$U(FWD#MS4+GksC=HKo=IAQT?V zLLmpigwZHtJyqHxb9OdYdM%`biHX@dKkammuLiw~ey80RcBXjdW3PKYdsUdD*-NP@ zIwl;LPWj9lr^&S}B^@1!A&awrA>g#;J(;4FyQ2VS8Zv|-DtH~#?Y>pvyf0c}btj0b zyqbFqn&GZBrPW$N#rl?UO~oNYKu8FRRC-Noa%5RZqqRYB7c{yS?aWq%ELP<6-07=s zrNS{HH&}2U-r|?;^@85h-zbqQLZL_0ntV5fT$cy$B$WGG6=KnhMpt-$sS;&C$YL*y z3jrHqySC%{`I<3JDWiN})U%;YiiOvgjN&VEtE(iJcuioV7z#&y4cu0nXiPY$AOy!z zmaVh%u~9d3g$gAA#kQwX54-2;W<{D@fkb}Y>lB@Z8&)tC^z(j~|2FVM4fjDY#q_#$ z&k9?EmJ$`=kO9C@v7Z8e@_i5`Wxu*n(T0zQdrw>|=cm^#8c#mx%dP+kE!Xn&6%N4b zZ)3Mk)cVmPWJlFQ>%~PuLTwQ1BJT3XwE5KYNz*;GX(kF%6of&HU3=w{*1eOWn{{9q z;ktOk!CAZ2-I`FnmV`D16NxsMVycxaDqJRXi4nm#nRaiOXbC2N8p}6X)t1C+WbkR+ zLbjw0Nd*ET4-zChg=7!_9NUgSX269(Kmh^uF|7$GuO&rG1InBCRQ$3%2rl}S)qI<_ zV0F@Cg_@_C*YDIVv$Ap)()DMVl{X&Q{f%P8UqR~HVMIeODo$x;D71Z9+F_)wu^s1< zXYEq_!}j3z!WI;Nby|-JgH5}f3JWq}Gu4h2YP^O5%0lWCQv4ynz$KYwKWK&nWxU+TEq~${X`E&7O8tD$8-;+o4SgVJ?8f$n#)+W>82lC;!PM zBet6;wyzj}v0clymaz1)&s0i+i^Cu$u}YyyY3GmXGsu=Ye^Bb$emo;nXy7wfre{w# zfPn4DiIHj>C=oOowF42NWrgMwmC`K*&Qfbw&_Lu*7xuu>rFW7fAlh?nv6;UIW z@vC09_vBE4Zy9D`NZrC&mc~%zW92(_EJ^mY^KA-$*y{Ekst*+3QmL;+4vO*2ca^E>_)sK238&ZWxM~&ULtKPNG3!PhQJd(oyIn+G zbk94Fy6v^%KG}Xa>w1<4C!Iy@1L}QU>;CDwuao(A%C9UDG^O#P?2z}-H&u@p4=*if zS_4XdmCsyZ7n#ZQDtU-D@(BszVnT)&+7SWMTZnfJCm#Eels1()Cxf*(M#eNpESb)z_;$(b`tuDSTr69j zFXobiYu2ZU?&W{T&)&4S6cv-o{ov+j3W$S$F^)pQv`X1mq3y*ECfjjhhsqT+aAyfW zuA>$zR82`Nrs^#vWSI}zC{3QS38n~wLePeC?ZRANp~Fq{E$|wBaf`fc*`C}|A|;Nh zCkjoOSEMJEU@O-QA!N89WFT@vKMZzMUAey`kZI7Z5ebA&96NqN8bgE~9HJ?{4GGkL z+6r19`~#5=hvTB9?P1Snnb?lOe?86GwZlJlozS!6!T|xeaqPum-bYy)TUZMJv!}@# ztg&CsgIwl~gOe%H*XW4Da8ml z(J5Aa5F7!nizBblm^f1dCq6J2O$WUAU&MMNTd~wKiJmUE(2WUNGZwLYEV5-st zsZ`7qA`|mL-n3TyrCY7(HI>Xajk)O+*Sga?>nKLH0QDGvSjhb>QALhJK`@tPx6TzQ zXtx*Hvg3%t&|aD0sx|8BGOl!o8~0sSkabR#D0CNH{_V>S|C8#r?nPAB059Wz*pW*+ zuN^=l9#i#D@krp=C|p0bQDJ?QOe&G>r!!qm#2;^EeCKUCU;Rgm|K|tMM_?Q+c{_Zr z!jIgR1q7%xBD*B~xXx+me9-T79~DSv%?!3pm*Nagx~(TmH!jeehd4958GV};e)B)n z1Biq%fMQlu-j|Re1gQ8~=D8GqJc&dR4N21aLfLESMXqs)0(1chT~95%u{G#!N|4N9 zxpJzN+TIe{IXU5$D8qGx(}$fWPtQ6Je^Xz$uWZ40KDd?k6Ow0MSzadVR1;?Wp8xwx zN;|R&{FxvsQO_zasZfv`VJAc?gWj~Fpb1aS!TrWif2YOobRVsSd7p8AJ7N65#1WII zJL^`b+rD;F4AKyBwjVftUkZdv42zh&uvi5CWqIMmKv9wx&?T|!IR$A1LZbkZKyAN*HnGn_$5Bb!yBxZsVj_kDC~*|KPACloW0$Va|B3UW!2WBm zZ@q3tvjS!Q`WzdFk-g0NRx*uqf6FR0=rvfE5V>1g)v4%AS?w(jYPXUkE!t zwFl+2#3bM)I;_3q^5WSI(QovNtiMX-aL$~F^5qtej|ij4_X?#_MrvFRf2pzj`qpR9 zUAg6#6*+JIM1Q=*rMtR_svVIYE@~JU6eD z!ib%OT2#bNrut;VVyB=|)eD)|UGVD3CrWVK_)3!u9QEaXaBB-oU1aL4@WiA%uuSBL z%R-POZM4*LdYFxX!&j1*e<$kB4GrbV@^D>P3IQVz__n`tBxZl0lv3eL4TJ)z@e?&9 zfv?hhYWME)wTNiuX=O@hlH2(1IN3bCA%$6*Y^pTC%XY#D%dVJNxQ0Q%Y=1}oi%Pg= zAu&G;Q3TU_Wnhvqo&;1%NwkRgw&xVuifT%NWuTgY$~z07Qcywbe;7+Qi$V0&qjhr7 z`5SrK{_D6BY9>OSMrm?aRWus583<7`#LRLyPHP%Z$HF0<7_SJ(iRB>718zTjDGwiM zL7Ixo1F#?t7*QEat083P?aX!&fGjEuH%H8)k!$CRYqZ_j(#)MZH*dALrUpq)V;eah zER@68t{nr!@}qDKf5z6u*p*r^Mtv8;VgZ{T(xYOa4&LlVwdkD`rfnX;~XHm%6mkTDAdH z*E=8d+pR*Gneclj72x^X=VdfhJ#|tFi3LfeRqGON<>#ZXe>t(d9e%$`)+oY3#HjQI zXEkHwdI$t-6^hp2t60Ao-6s9YC!a0dns>6H*7<3tGrK2#=dss4FTXPf2t^Pq4VG#O zn@6>!6hU3)dtO6!eSaz;p0*yf$2TjbE%I%O!eUu16YcHElzjyl5M?AIfD_mR0Vdwm z-pp_d!jv;ie~w!K!H^rLmD~c89V!>y$!kZMFZ|cj@vYN#chK%H#e1_1#ZAnQpS1cP zOS#Rz*x{goqCVq>$kRW*`ZxD_rvwthFv98D3k;KjXN6S=M4u1taz!9!JKy1`^tnL( zSiWR%GW=(*Twe`ekNz9wuPa>Lve}!wGDNs@^IZI&xxB-h{!R`gf z4p1!1xib`&Bbl*kgdk$m0`IIm&e2{4g((Z(TnAhrf2x>pq3B&6;48gfV&{*_BD=Ce zL!^HHMfkDD{%omkf3ymny9!iQK#c0^(sz9!49LH5MgLk1ArtXpF&pV+CR!|fUoxKa zo%GSXe-ZlsdSV4oBZ{^IgXQI61nJnx6eOd&Ot=Ho35wW4fT`y<2a)Wfnvf%$- z9$LfyE>@IgPs{%%Yvt<^hV8f@>#u^4 ze~aWU2aJi2%dui&&X}nGdBqQBuf^Sjhb_Lj*J4}W^KXAS`n!t#@f+#>UT~6^RUxuW z*=s-dhjE*VlUg3g+VCCB1W)`+kLri~?-? z#ZoN(6gTqyyrTsI8+%i&nY=OL_L`jce?6lj^B|&(r^p^~_oO;Xr)r zX^*Qb8_=<(HU4O-e(Kbj=_b~D`W*YWfVx?uex=vVG13-#-5Ifw>w3bZUgYU0M|)*+ zf)ccE*!G^HwbW>qCy803S$55sp@fX}#Kq>nrz%m@T1#E}#W?cLWm_@wUTU0?Cp~*k zAG?k>V$D@{)>x$^tUpO@DYYF}?uT59{SW^8k6bNt`jQ04um5jx{okg=ll%{H<^M=^ z_@ns5pQ;qZhW5Ssj=2r<-#7<-e<$}X_~^~(>l@Mj$eB`dE@C>yVaM-7Y{g2=CJTT zA9l|8-B|vt%WOMeboIgT-_qmOR|yHeNh;i>O)Bi%uZ1-#&krv|-Lf#Ae@9iHR8NtDJk#z3h#j3-RJq8F`Ty<|jb{^OewrP8?EilLHslCNZ_ zB#>H)idH(1lp`8PP8d>|e=M6l3kDAJLN}j^Q;z6LomqnDMd7P4-sYM1@<=^v+Dnh{ z3~)E*5C5}N6T($CiBA`VMajWntl`UY9}t5K6x+=r?12!0e147N5#O7Zo-9HGM8q$c zF6k30(J($HEeEj$c$15p#aqfirCho=SWuzaOR!@>ZjOp5M#ja-e^q(u3yi0 zc$UFE14?D?%|_HpyXkd%4=PK%7g4}!a6HNDgq`jD@nR;Dx}ZXq5#S)EG}NPXOKDa_ z2@~Z%USG-+v?Du$q0)(EIksPY#k2TKqs~FEd*0(xQ9LvaH)k&itWW-)HFl=syr*$z z=+5f1MWIryiy?ugkU*z1ggikJ3s(?dD?$Gjs$V5`Te*xd+ku9hEf#;TWd-g~+ zPrQ`V4{-T`9@#1lERCtx5c>F3LF{4%i4(fQjbreBN#w@Ui~DDt;&|Zwut=1qJrEEP zLa9pWw~=+t!26_N`kwWmHE5|AoWR8(phP9##ZW;rsG#CJVkI_`IF`uM$U9b-V_Str zP>d%9$?7-gWZ#H_LDlU_Sp(19vx%5vHhJy>#DBWcibd)$ZWQ>)(|T=cuv zflwLZQ@5q^xTdHrqBss?r6JNr4j4ILnBP>B0d|N&LVa^6Ffzc%03Bt(@$u3p0?Gf<5J=oj z$%hlilDH#&Qxp#*rZ#l22^sB=cqsONEJr+y07Raw`^zAn`qYiW!U(2P#0MS=Wu&nR z@fj>{1U~sP-^CDGP$xCUbA=@x`VRC#A@2see;inLJZ&9R39Z7#475tdCeH$JokBvz zeOJ^M%9YL57s{GTNnOh8$Wo|6p=W{HW@j|6x$kPhjAk1OthUXHGRlUOONxiim zf36Bc`0(*n10-FUZ*IZm8hTFYkW?2bbQSjLq$x$-zdDkAK zrBRU9o;DN(D@_8|0POb~OY&+J$^at|e@3#)zOjHCE1zZ2Y_kPig@Cv#oDC{;3?oXy z02?}<(y@MYs#3hmLXUZ|(imkUk+hXae8q$I>7ZTLn6q8&L#6Z<@uLr>L0~9WW7*TX zFF#XA%74dt+-^NknnDiTDE8sXNWQ!dCCzYO5J-i^HtGzkpSW!5ajD$;OeBQ%e?ULI z==a;*%6YQ76Sh(#tq9u0b5@SN8SkRbw&L2YTl6Jv75kBe5eh@Ha+f$0tI`hd6N}^M zNX(&0=4FpQAALD|HL2tiGg!V)rp{#VC=d+51mY0yY36P%2M)a{W3G_XT2@PcoNndX z%Wk4D*}R;|NaPU@pujL$C6j4#f3h>&w9`$T_Cy}K+)5!y{T9D;uNU;5{zi%8Ac`Y5 z#wNv1dyW&R{H+Sv8t&6Vm)RkT{ScWv#|dYZ!wLJ$CB!z-@J2`=ezwZY15{uG>;z66 zGHlSRF?y@}U6z>`<661KE2Cp$29C`@=mS7)!=>5_;pTGNuX~+_XC_pLf64c|{I`Mk zaM11_6gx~_x9(Y?>=B~Cg~*A5m_>U!dt;MMX~UeClR5V{3HpP+9Lk!=7A;q+5Q!_= zSNef@LGpwl>zd&$bYWAe`Pxl!BH}-yDDICUhA5kYz8XHWhR?0hm&2cBl=0i)_p**$ zRMMxlSjVxH)coN3d%i(v!XQMyx z|G!ia3II`;g#IOtx$U>*q{pJOx@>WEgT8urAF3M~W?7b2H#F}&fAGupAh_rk1AvVo z{3eF|R;9RW4XCBz-)^dlv*G~xss2z;TG;Lv*!3rMm9jB?1?NrcGkJ3VS+x2ZeJRiH zUyQyHzE6H?AO0X`CcWUdzLEC3CI5QGKlt~eWms<4N2LZljBywex~IcZi~(<4pW5K1 zsUq~l_TV;`3wx!we-6ZSLZiHPLGQ-~?i)55-kWKQrX!HWl!m54n44vZRVKz(zL0KI z5miZSvufk)cf;5G@9(*J_K(U28bTQQj$>le#y~R$+D;Uf_LB52U#cx!6T}JNtD{Ff7HfK;_ZV@LyA%EmU*TK8!2w&t+QLPsyCT(YFeC zhro%PC@`F@e?8uf8s6O&ROj-R6}#WPbv{Tnwf2XZ9HE)jnbn!qHEDI_D&BU03rOT& zH7eeyc%$N1Q}I_6Rs8fYe&yhu!Q;-kIE>5t{50Mm^ICYG))Sz9Z+_8!YOI#gosJhV?|AZ9~tvf43G0E)+2aA;1PsI+Og-k#$(( zj{^T7C$t&F#!Z-^i{@GB6;qq{!%`PExmdoKiEK&ZT!F5c%g@FDnc0$B%e(xUD?dS} ziF|ltc8G1`xbWoQnu^`!5(Y3041ej&Un*00Z4ddFm_VV{m~6Ngu_Re>KWvj@tK0s> z%C+BBf3i-f??(h);+DG&;JM1Qn*t>pVPS+tVGA@z61 z+QhYf4ZVJ(rGZ>71g3akY@6gyGq8P+nawJEwRuY=kbD_51%Na(OQFiK2oPCLox zE0kl>w!zsygAQwBa% zcER{IKNu3j#M-02xytl1MHvsq>^KQED9!q$*mE$7Oy;v;L&JvETUaH?U{jxX$R&og ze++AFiY`r%L2?>IUL5=87-2YVW1RNMlNE{u`9Tyi2~<|Joq((L zonS725n+MBeS>k2mgzw01Yrn>NsefU>MX}1_57F;*RZWIfHt-I%TVGA*RAojea`~{ zG+8-~P@hW41H_H72TZuLF_KkZddu48vm!^$T5})_kdZHj8f&9QR9SPXf1>QQHd$oR zY_m<4snA%mb6tQCBgC8tjHIYfQe^bjRBEWTr-(xwBh!LPdukM@RLN=q5e*{f8^2K_ zFj}hXm3t8*82Danau^z;N=*InPIj?&r$&Tv=y6qPIL&a{rZ}zN9$fUhd&y|;3?6sR zl{8w!PeySAg)duy?3qVGfUwC&)LO?Y z1=B<1g{~JHOlpkDiPNyavqBkL$JXto9RGG4MZl$|_^}xnH=$sie?!4iVX9?uNBmrD z8;#j8uFJBY5VuPGI3j{<*Nhd>+d5M5Wib+kG>Q$^YK_V5`?4?ys2?)p7@n!91 z8}<3JFo{VV28O7cOVs>pgS+kSgLc3D;7;pN+wZqqAIooDA}`kmeYyX{*>#}q)dGRg z_JL{eq_wtJ@oE9ze~$t53?_BPWR+J-WX35Svs^E7U0?!=+9P?cx-m&`J5rnKNpQ@= zFos4kPC2a{PSk~VgkxafWF*ptR=>|R-_}7YZu8z(QD9|>UlK#!l8wcZ?qbEyiyCp& z!f*sVYHWum5NlHpSf{g z)QvYS1vX&-0iW3>9jGx%(VVGwvy1s-!IkquFhYbd*Hm&EhBFMO#&B8AQ}q>-(2WR^ zjAGcV(J48Q8>l`BjD?~#CU=mM!!UCwHPN69U6_=d-E5=2k+Kd7Na&b6vqls3rAfR= z8uBZp+PEM@e*hXSuC*3dDj;Jn1(acfNsTc%b{JN*r%!VMmZ~Ge&_TBCnZ~D0MZA&$ z61ouDwka0W9?5ep3zN~X6Z>e=#eSK*1O@{PZAuKwH9@Ybm`D`Ihyvr|Zv;jwSegH% zan&(TFJ&xIn*rYsOnbA&=uy2_*E}u1#{=ZY5<#uVe=dTK@79+}g->Uj=C zHp5Y5{BBJ!MU>*9B(f=FrfRo20;PGnTO3`Rt+{jQTB>DFHsa!vVq>)H%vwr95<8wt zJjYmFT4QqiNh8Dt*!Ba{sVPGj%}p8+@r{P7spZl`V94UwAtvXk(d2u-*E?%A*(#=o z^q#i+f2~2Ue|&s!%3n7qd>|?5ynE|>aLtnURRlPsj5x$7cC8h=Qp*|hU-M`3BGrlk$p zwv1BOiW?KfRJ;qPogI&p!8&MiMdd(^0kR|N1xBtIxw6jcRFC@*`3M1Ij#h@=_M98W zf8K|wlvX`Y5b8KSuuYe6!y}h~M^MTmiQS^iBX$@A;+x`5!y{``p-SQ_@FFj;BSBe) z-VD91y*d+z*7NZFw|`r5=vJD7;Jd)FeZj~^Ko|jG#Fu8`OJsKKr2sp&9=6WTmD1G^ zvH_*03!?rqO4TfdzULu`1B20~Xr1Osf6jh;aMADXrR)?+L9Kmk;0A$f@_cn>GbMqE zfbaXjR7dEI$sH81`i!~6DU_%aH*`e4@nxV3G4s6pXnd`I@!s8!%E+a{4k13o1Qy(5 zz_wkV00p*+B0Kb_pUZ$Re@B8ZeL^MpP&x1fSnhS6w9l>E?N6+`y(g`1IX~R*fAv0o z(&~RKwKD%=M{H28xZ8Td70BP*>zxuv2*U`|^j#~wP|)P?&!f+WFNd#(Z-;*!z8L<* ze}7@&g03y_X9|(k-dL^(5A!3fR^Ctf(}({&d^Y@!Z&7UX`S9)NtKm6nD&(@n)OCVLs~ovXE$cHtK=S>;$uFMvTaTW!tX}st zpW;*j@7Rtb-@}dAXy*G;u@C=+OM##Gzc(s7bwKP9pjExkbf>GI<M2JFnZK&*VS;Xe+pHd?!ao@KNZNbM!y?KceX z7P?mOK@`Wg>h1fa;>%#X1X+0FA@F0`*~*CQTentCc# z*f4|ZF&(Ionk6{e}rP&_M3MUIQdMe<*j2w zgn~k_1iKNAY%1J)3$~|!#8z%%He$=tcdhV30o2lntvz4snTTzU1Qb`P5Vm~UJL{O3 zZMuw-nC&>RrZi(C0*p8-AB&fY*(!>+$>!F`L?JQo7?Ug0Mr_Yw{jw)`{bIR*H;UcZ z@nSPTWC8I*f9m0Y1!6x2PWlpmr+a#K@t|!92Uw?fKIpewPZTE=ARFU2Kt{YZ2g4k{ zo$ez={4$q>I52(q8-(B1*`r>+GkC1Z!oZ0jWjHn{ZUl<2N=L)tX5RC$zDLjeW8JP6z}Zf3#y$QI?Su%`1((IOmpKPI^@A zqH&dx=Yt0~ZX}kgl1+nM8zQ|@?+rN{a?X)+deT-Z_(dM2u{mZNde)epPkR??J|hY+ zu!&X$5QdlyG3SZ7(^cyG7;w88xLQT!4J{j5&e3wa``}Dzd|(uLIH1O*ohe))xHgfRSm^tA%^N#x;}KojV00`|)}T`F0b>NeG~DiTd=!Te$8 z$gedZiSAD|8<#3`PiX1GPKwnZgDHh~4QD)TI zLQx}}i2W!zEnP&o47kKjOJ(A23f>pGe>f=&eCEMRJUeqgah@LEOPdy|oz*F16wynZ z^|;T%pphp1{00xYYv8>&iZm4X6<%vCcaw#AX~e()eX~Fp$L#$A`LT8Ns+D>HUzJ$| z(ifQZA}D$OJVe7#ulDa+A;ee+#zHU_LNkEhRAn_g*2Tbl(=gvJc#D3S%^>q)f5LcU z1pA@(@O{6_sbSzf9JGslUK^`D4G~{9BK~E25M1<|OTgEz8`ZZd;EJB))yLl?Ip&4P zg-K)UqSfs)(b0GGttEr(KM$YXu=t0+$b{C1&vM{6Dm^B{IQCpdFL9BNIVPK9a*eEP zj>)4Af85YTz%-83 z9*cq@IT!ycXVw=&CohpFi(t&+*f*@&2qcfYGmVEDzB?XXo0a$Ja7(4GZ3ucX4Y0v} z1F&Cit`|w-y)u$WOn~INihZNCp*9}c+H6Cu!WEg$p?z0i?45)6;32rCIFA;JI_8)P zo-@4MI7$A_0=8{D*WS!ef5vX!!RpB3N250~ayp%sDw`0z=D(%^)wFs!cU6UVfscI# zOzy@Q9aosoW08D(yyzG-K1HN%QHy_Lf9e@kv$&ZTK>(R& zIMr~f;nWp5^~%zmdS!V|MFb!>@Qjyp!l@M!4cO4522MtzZBC*+?04GThBr}PFg&5^ zU>I1}Q<*j^>n2i8IQ{}I)@nFBzUJRjJ31oh*$xZ?!}x~r4dX9w%p~I&6LubRzsP$P z|Ez=j?ej7ra7}5He#;(d z0}|wfvAntf2vKB*{#2x8fRMi5a9)(DTV2(ntVEutm*mb0 z%ZMRE)YGbQf2NAU;7WXOmzxyre*3|l)}yx1mF&lIe}j`>bh@W!7Z2Lj)s#XHA752b zE)+vA(#xe+35v}3MgG@ejXw&YVqP4RAkb>!qZ+7EyX!{2sq8u?b?w>1Wv#OnaDt)h zAnG&^C*`{CQ_E5*8o&hjUTimyX~z-e^4*UE6ZK_mf7R1hK4-EgP2Clc#Lp;zI&t%m zRAI>SpG_dB?pYq=>Mtc65gf7@0Ij@0Y9d`JK`ufd!pP|M#h{{*&sZ3)Y?$s2R3*be zHlgn8XVbEUe{f4h=|ezK41u1*FY0QYv9L^3WneLm0-F)N$a?FL%6X9&Qe=U?*T>UR z-2hgsf6HI3@U?7m(7dJbFV+qnB})oMP8>#hrk(7BikFn+IRlmp+1jyqIRA;c_uu8@ zS3j54T*bO#YsNGIb{v+JiL4@YDQZby4Bv?G<||o2o(^UlzFda?PA~fXcDHueRoMH( z=Q7ed`id|3wd^)MoK&_eFfB$D1|YoLO1h>1f97UH?*gXHtHym`+7q>yqmQC6B1YRN z5ylqHm1RWb;7Ku1v7trX6n>HEj{$zN&ppe)9)wC?=(f&wMAo^n-YoOdEPn+)lLG3;FG&Wy_n< zf7i({RiUBf+ed#dboA&O1%%qr_X(z2RiW%a6qKX%cJDzucgTOodb+j)v1rd8rk!N# zb51B}3fp6Tfb{Z1s35-9v&7+t?ZIun^)165I6>r4tW}rRWno{wGe+VlbVIGmp*Buc zIRfZBtc#YaYR<37ra zWYD^Q+AJdA3sxcljA9ztTAuqWRvZ!!+DNNrv%4eO6-jaXDqCvoF~R5QbX>)szuV=Q z&3)`z(kwlx$64M2064%tq|L~e-iEMKJ4_MgFcdf3J+uSpF0v@zZHhL@^P#$J;e-+L zB#9Wp*|a#<#GlC`2!I>-2IpfDf2)$=YCFXCsHfhf`|1yF5^ zdb5E5{L#_yh0KV4nPg+X%qB)By|ly~k&He1a`csGvo-qN=vxaY;0^g9iEX!WuFhr) zrp=p;;xJhqr3Bd!WW`6*e}obKVWpHz4|1b3x+GD_b&vUpbH{r)XxA9#%Hi?4b^D`R zw-iOUAA;C#ZUY-7I}H&Cp&d2+?7I%(wa?C%$&M%oBR^YuF`}0wJ1!Rq1ne{|}Lrl?Q^acz9Hb_Lz+ z5SYgoAvY;7-ATbO47^7}9Ygg^j za~70}KZ4OP^gX@&5o^MIO);#GP_Hf7Kyl%fmDBZ!uob9yDT$tj(Q98snqRTRN<=C~ z-OH#z(6SxKf9uE5QflTh;wWbl7&x%_FN1+6TiF|{w%BdU+~XN-S=V!n~LQ5|LlGJZd*r|=d0Y& zU?+Ag%k^D#9oRs9-QEVA#A~~E76=kUkre?)3UdSWNtjh>#_*#%}7{Rs2VJV3U$ z-IE?qr(c13qrF8^5=E2J5lN9%WEqJ>Qukg~)j8*PKI+stUNVJIR58KK*W*tMWQ6z^ zLMTybm0YIhy5UbeXtv*e{q>C(x!((oLMBEdPK$nD7H$A-T~NlW5@*MGhU+G;DDo1U zf3@wDo4!vHOBUAHC@vfF-VG%xoL4jY_ufw@|L5c%PyTVxJhpG?ya)AprB)+~ZF0wD z)=if!>uErHNog#qIJ*E{I=d*~?W*ghqDnv3GG`l*3$*Sw4v!WWvf2A)N|r^x8xLrE zo>56Qrn=Rtu1jw}An+;d#296sc$HA6e^69%U6yXm(-+o+ zf_sS9I@%NBk`5+Jo*AW5OUBYjxws+Li>Je|G}c;#(gO_G&W!TDA|}1&>dWuLi?FAZ zi>~VlxBg4(#RAWL_FD*dy2tfXe~U-WRs&*^P*YMw zXnKYErq+^&6qCo;Du&W4G;{8(OkmPS^(U}O%>q%LdKJ%kL~kG?ixRvkD*kDoGTX(| z8a#>zeSrjJ5y`3)WtsRs)m&a+Ydrk2Xwtl@>48DS5Ij^eP0vC}h#31{d|8v@`vN1h zjqCr4Ux5PYUQ=A@e<;suPtiHGo>i4eyySHBSv>)6cMck@7u}b@yq?d zpd}=zXNI8U{QdcR8=c!ygL*FA!z0j^vs9JGKJfqvWLdykl5uB*)@#1+9F`$e^ZNbC zKllF7dv|(xainG`V5yKRrNL}N>Y^v1EWUX4W${-JijVGoe>58QAN|Xn3x9bvXi;%( zJ%cJKD_`ZFM+;+-SBqkghj;FPqW-0HrQVGEn#n6biPDv$>#zJK1IECmuhk-i@qkR+ z$C1wKuRGlZZf~LO;uS0dpd^HrIx6G$+vVgV-3TNFYK~EH`sI*mhDYsypV)oaINtrB z{`>qRSaSBte`M*anfe+FF|HiuUj$f2Dn^=lw59?DT&l}aw02DUWpP7}%}=2tz{zh; zP3b@PehB$D{q&l5#hoH#+4O!a?$%a!|BwAv0`Gh8Ajn1qA|*>M#DAS7UKnpDl)*F5 z!C#;+L)J}gw1YxC23zLi%5#J8!u1_g$VnI~E8@7xf4#ZRR;_z@behRk+y#X^WLY`P ztK2_uah6kGu6O$O%R&ud3@h&G7-BfCegdZiojhW~u|h;8zKshJPe?8i;e;!p6W!5Y zrl2jbK@_MS+Z1{kZ4{AfejF33l7%x0OA|(&)k%NVMpZIw6GBVkh{^?ZlC|aUfNXh6 z5F@n-f1ByNVHTR8wRjV;0p$!p#~z(0Om4zz+`HG06uk>oWBWZM|Lx=-2GOFkc1pb; zPyQ)HjCy}Q`7L1WkagNRj}A&jZZ2F-Fd6;XcO z3&30lOF~Ku0$G!kYlX|i6F*~ulBMKxjG@V^e=lzrzx?Ge6FX#c1T%BzqXLw!L5Lxm zWZ_vlrz|_IgW1X{pI!>&GMw*^9~7PL{zA_^b-L~S#kmhdr(~Ew(a(DT7Gj~5Q7V@M zi{CwjWwJ0{3PRRB034P96b?7W66Mz4Ko0I ze-c)T`nemDm^qJ#f73o*lweP_;9A|H*|*Z`U;RW|TEDt;2UK3ec;-}kO_G=E6(Y_p zLOi=Ri;I%n_!+sQcBht!p@#jY+1kIg_2%t&TVFK41XjLO!tgR%xCsTu0?Gd>q@#eG zRZ|g8c}_=JLq-@zF9JW@DexeM@f9rXe@#oOwAqkyQ;WJTEGul!zO<@#I`Zn?6cs`k zB9vsi^Pt$TRbBD%O~fLaHx-K*2rLQPo3Nhg$~di4uQjj=K7lyIsA8TAoL6`08uFU? zW|PUs4AZRAS(PmdY(Y7*);Z(WJ#Y?17=g9+0&PSF>J)xpOe*F!1Y_sH#89ehf9Lb# ze)Wn$ebdERA+;dGGTw#7NTpiC6fBiOS|)vzdHu`bwWZWE1=pTat}?DlFGLGsHl~$O zrAn_r!14>462T?qapwO|!Aq?*5ea5fO%~Z#yrC z+`C;2-b29Fme!|O;tbZb*=Xijf1FL5r;NDr4jG*2hFBoTDVGB4WfN*WvvF1hyn4cy z&5YWbn1X~6Y^WV`^O5#FNKl;#f}JN4r!$ov5B+WGT8F?gN{jy=F11g$K97r zSib;oWuf2s}0vjbVk zf=Hyx4bd7)hN;s&MT-Nf@itZ;KPdJ<=|seOUaG`nYLSw8MSV#za~AUrz%kHfv9COL zE>Q-D&XQGv(#j-mEUtWOnz$0lQYV^w7bXu;?O2yma+l9cUkA%$Y+XnzRaF!vdaeJ_UtSb`suRjxncvf>s;sn4g37*|&4a)UW$ zIoqG-e0jS031BBy8^gr8M9<`e>45^Drj)7@8_?YFT5T{15?quj$Acr+xxy)Ds0!$Ts>pU+77#d)@ zQW%Rw1646nz8?ixE$zX92vSKpwe-dz4{RdQx+=Gh24fTxx z{=(c;8mAttTGVx6xgg%Mq=wZ}xgqYxB3Ji9&1JCetJm8IinH!pjHfYD1OsqM+!*s}bW*pCD&d+cbls#x@RaPQL5*8*H3(2&W#9?Py zu5x-klT22YfBFmoD{!M<9=E@}VSTXW8ZV9;jo>+Bv;_*65MNmpXQ$)k(;2D~L@h#| zq?dLbuXLOT|5kJ44ROLSTKAgSQ2yq$q!if=(XETg;aLsea%723wiGIuAFXCor&_vb z5quWYVHQF;6NV;u+yiu&MQJQcnqD!EaDC_%*}7cD9FSd_Fk)1L2-hm$od^>$Ej3F9k4XinStCCz>eN zH+Y7JXu5|-^~-CVozcP~k$Mzu&VBTH#a5aAM;&#Hh@>;erYLPfN>&dcUAg+Kz2683 z+h>muf57>;sG7%}Zuq=-0O6CF*l_W6ggzPxCjcTsw;Rh$l6!HG=RfAj$DZy?Sql4|{(Q^r{a!!8yjrfyJA zRyWtn?jx3IjcG1qdL>bBK5K8lHajDQ0{cqmLe||BnuiXSXEqJ2o+g%|yz*wy{f79% z)R2fy`J;W)87ZfMg5sk)AAt-9BdgNU4arVQO|)x)#bbi~;T3nUyabeDi%R1O+LXrY zf9oae9}pe1b>+MlY~8CRFGBPek}ri_Nj&!(Vni*2EUQ4|2bbY(NLH=^83eaPD(%WX zK{Gq7DJ*|<7iNPoM~##@Lwr?$JqwW`bS){Syv!N0E6@x@vAB@>WHo?`U;c7}wLMS} zw=dBU4}cm1RUR{&V46o1>~lkGmXv{Cf1?j^c0){zx$xq~%PQ`FLBA{>6yJxFuiLo( zulN-xEf$f|DV_`aTuH)j+Q&Cc!do?$6wR85=#%dqZdvJK+aD!%4NL&Gva zc8LU$6{l5JZHfBAgG2oLUo^iQlmdV{y{xpX)FNBN*OC@2M15zKw_(=Uz}tHBfA+hr zTAo1h0*;CG>BS46O(zoJl(_I0gIr3dgrp>wQOSr?eDu{vll{vv<^t8YC@Z5q%E9b2 zy$)*mCON{`B-+Aa(W@c2<+6(NFw5e3XdYd2F}-Is=N<(M4JzYo7_&g0l$tP6ChoN_ zj@MRkXo5>=EJ-^}VG90ZkG&V0f85Sy8CLV9>91!yGJyQa@ea-7x6P9sj;W$p+eEXk z!t@}K3?j8GnabJW5%~dIutGJ0RHdRO(er~)g^x?>oOX$qXPO6+ms04U4QtxT5fVhF zM+^|F5$%}6GRmm#4d&SiS7vTQ@)TNSF!pSK0`84R0f0~zejJgyd zVg$N4V(*zV=N}D5Joe$ph_$6vU+15XczE&D5tAXZ3`twHTis6mx4q7Tt!K@{MyL3! z@on*>eYo2iPON|BIWv6SZofL*J$}^(z52#x5V#O9zu($Dtg-0%v-TdxoQGg&IsC2} zzA&&s?_W-S)BCaazV}n_e~8V>=h^PLS39Qo`+96V#b z50v66#ueD{ubZvCgV+0wVrwX#J1@5Y`jnFzskwnttOrIP^F4Ec+N{0%UV zeXBNni*G``_+pr<^?{`f%KEUFI-wv3M>1Gsuvka1e`vPW6DwZSP!O6=KsTr)!pb0- zov{oBbB%5)OP)4IgosZ1^qo0BJZYUOxRrWVEugwT|5|Z9rO%NM9I9- zjAoQLMTyDlL@cvhf|`tEG|gz5(KNy-03$P<#$LO%KVN7@I?fcRz(Pigj27#N78?+n z0VOqJf6EcYpa#+z3NjQ-9o) z(?2qRZYqG*@UoWp862y-Fvkj0s&$EJ27wF$n+XD&;aJsh0ClXGm8_C9+XWdCG9;`i zB+TSkQBNIZF53!cz%T_s9YI3dTnsJ)=!OF5`Z`vowxl$usD7nA5ugsk83Zy2WGgBi ze-s#Ttom>Ob*zxYm=d4uf(!{664n$FW^=4cXE?Gs1N;maCa)85MpB9(ogFiPW&mA7 z0A1%DtB+wjRzeYvl!Y|!%^;9LAX`!CpumM4s~Qf#J60v8)}!oLWk|@7u%?hOTPmP* zOlwqSV93Cbfnhy?Vdcl;I8)ZpY<*;qf5{-Twjkp>dquZhG~P73vy}Ux%sA%|&KQv~ zV*b%h<}pbeqt@heFA?)teOvcQ4H}K(#{T2o7Y%dV*nQQ%D{H75)llo&1p4`lMtAS! zEl^PzPDzO+$z8o=P+VcNEzIB=G`IwJcemi~65QS0HW1u3gF|o+E;TArTO(Hk?2-^Ip^L39jF(*_5W0f#uboysHMN>T-~jdg0U ztLj+8Cr>?qCxQA(3(Hr^9~x(}S+%2X>qp%pPBkSfpz17Jg>!gL-oLV{Uft@mDvR1TUA*nk8?>72 zGf+=2+nKUtrt_Uy7}o1=a#~OAn_DzDm82t6Q~!Pfj0p7!Idd;ZEo#wE@2Y*5k8tw2 zyP5Nv(7nH;65OA9y)0~BTvv(AF7oo6RwRkgf9Z(irV|1dH+M7K<&cP2u0C@ZU5AIj z`M8fNkENunn3sbpf3K9{0mPE=8UOx&L(Cq*G`m%qG}GbK=GiRX?3t*PcAQ5LxCV&P&J2$Vs#OH#)K#iFlQmNCZe$wCpjlu7u z6ft?Lry(BtOnn@SrIWHpT81=rs6Gr+;On6BA`W%=)BZZ|5`20|-OBstKJy}Z`8s+T zlL}OJl>t8jD&Gvz&t;qMr>~mxtncaozR2VEAdN8e7nY^V)Ax7SnS{BdFOEF$U&_TY4LYLIIbu)jP;n{gh-X#gIS4aF|uSh4F zi7C0lm#1}Vawm%yQZYFTlD>5F%oI$GhF=|cvK9FvcPe?p?`OBy8OEWHPx<))Z>^_L z1>|-O|EYR)?nzEzmY1tVGgHr{q(ibPrrV?0(XV1eMYZ3U36Au(V47^gpV?C z2{!Eqs~xy_hrbW6xijSEu6ejqolAqmOg_(-ir-kYRxThTLc&S-C)$miU1~{nXL-Y) zLDcUBU)vk*S#4{9uVlQ`;EUAxJ#6_|razE7yqDX#m0OjW9D0kA!QxT4UmYHf7fy1g zV5>#s*1Iai6;hr2REVbWG@&t{CgiD1laKP;BcV)cZ;vhNS{I&6CykhHFdOiR0&aWU zKfV53D@Bi&5yIMBZZJ*jbPI=tpQP^+{+Y#yfSVd@TptT)wp3~=L&sz>yP16Y*(3I_ zb}y@0a2xQ@cHMcsMNSU75T@^%q`+$)5to40)WoMu`+ClH{qnybkf{wLgF5{-W#HZXkN`KtjS*tF>=4EkWfmD8);t>RyoyFKsK&rZ)K&Ipg#0tA>UW#W{or!tx$u7HX zGIob9s>q{QfHjS8>FS|Y5z%^o8)*p}X$4ZSHvmUbXD`9{ug+o@<<^Mwc^ZX9--MF{ z^%)M~MoXB?N-gd+DRMt=X@ppssw>pf@}FUIn}sG=YfG5!yE)K8?Cag9R5Q;Uoa$a= z6?>NO`8eT>gv(2&3o{CxLV=Z9Vg(^u|Bo1d#%9V`RJEEpAlE_~&?%^K=?~WrHwVGD387mYo_SaAL z=H08@RmU!Iaep_h+GF)D#3m8gq|=-DcRq4bzc_vQIpTY=PL+_~Qwyy{%`}E9_xEOA zC;BPPjEXa(F%yB8)HUVH?4VsbhoZL(G2n3Xz22XB>cXdDev@voJ|l#wdh z4w=ZDqKSCPm62qWG3j0Z`^g4QUC>ilb5VnZn7kwAVI=a$+h4WT9y#tD5|yB6jnzPvi#nigE>d5FtuVF>2ZB z2;`5~exAf#L64q7CwLIA&4iaLxsli5_hqqb?>I{M%-7eQ83-ALMxXp~iMZq2L1pKTG(S)`kn<^Z7eh_M z?J1DjV>G$-=}Ho!v%45GgXCGchw+PV+(qb7$Ojdp%`k=Ect)(~WRNlA-Sw>|(k9+y zJvi}OTGpO?%Sfr3yp;FjK3RTiE?2|e3-bwK%z0@XP#WE*we$l_eJtIRH_KNj1j%Rk z$;s(C9U@!olH09}Xf)!8su~%wnkRboD^Sd$r@|M_AZW&za?7!sHBgjW7Jp&gJT1n_ z+1_uN?#k)39%gCf7vgdefC~YX{7gBL+PI-iW;2LZ#(h4H0$;RO(qc1zyCKqMVtnvUvFW?v zFJMyPrBf*iNf;=xV^W4mW{;~$89F$xVKV0(`9@USNGF*#$E2c{=M;yTUE{P`sM*Oc z)V9UHx=|(LhZAE>@@{B;YC0n<#6YT8jRIP|>W_0DY6O#Y?ZK%Z%q7-OKsh7y!qD^D zF{x=<0{gg)Q6cx0bcND#VEX@nV!ky~j#%HJ(hFvbtP1VqB+MFqxE0!)j=Q=Hw$7Z-F>#e`DFwF%ks`D)u~J+qS_NoZzBJV zp`g{IyDO1k^ZM_|MCP2s(h#=^nL|ADZ&Dn1NVTdWlE56KR7Fgpvu_*sH9;y;|4*b_ z)V#&#bSAnPIKws^zo8>pi=RP41f@NTaqQmF2itR^&JrhRe!gD#%aa{^>Xw-`Q6Km8 zr}w~MoNE4*&>{foyoLeB*dj;)nw&F;75CRKTiSeX4Wb9BMjzDzl^83wd)wESDH33M z#br{?HW1@4)0^HuUe$kO=K(?M-YM{U9;1>V8=^FyS|mJvR&Kv~^x}UXnH*!m%Isjd zEND3ZEhN)oeRF{Q*6UhWcA&hWw2W7i6kL^&^76X#~CW2z6#fBAej6*4)M$$WuG(DiM}=l%Ro?oK6;womWPA~1^Q3VLF0 z4)&eW6?w+$I-_QiC(>*UXO|Nm;!nv6Wf@1`RWv&xqsA9NOOjx$a9Ov+k zC-{SI$-=ePReDv?(4cPt!+~Oq+igDqWk?aQ1eTbPJ0CdiJkKt1i5B{oXMuH+8Jr1#hLHB}fdCpmn@65KDXBzp-d>@&0oo$g|D= zU*!+rlqfrd#0Fo&{-JKs{&#-!1K$v}c!}B9%Pb#-;53w07Z!R`AHGh4A^f(M2Ugl& z$FIx&|0zcgZ+2|vpDtYvab0IV-s{A=7}ZDj`QNoF9d}d@b-V2R?N^(fJASWr^m;Hd zG^kqT;``+Rq{RObc9&-H*c04^bF?b%+ber`YkrWtROx!yHRdoK@^Bc^ksIQU@D2YI znH-M0@;h-AVN(0W#rpE-=;ZqTDIf;=Zj9j6TG@#c>$;n~Sq#pPUmwZ1VQeK6o6*^A zfK0Y`D+Y2`N9f~=56Ez(#$kb{)PnyU?_S0ESo^iV)N9tH<%&@$C&hy zi||-rQe-$Jdv_2lJU1h1Zk7n!Mj4;dLzcZGDZAn$BKoR_GcYWZf5BUs#85 zCYvPy`2LE!e4as;V~>Z+EwU)I@)7L2&9)Uv>v1qaCBs=wZadS$iACw0aP6`2Bd^Rb zq>Dj_u6s-3%i7>#cI%d-qjTWHf#d7#xwrF4{`UJ7OTgO!Bi7~}WUy%v?sk!j!t2h| z+S`wgug1p79bZpRXg3LjxDB2^B0cmHV$~A@iSuWXkvgp{`7QPfx&Z>ZONH+ji|1zk zSJ2LQ_`7T1ZlX=>O$x5(VH9WSAC!2tlz5wQ-L?5fJp#4#My`EDX@lcBz*C@S99TJt z4(;N}&2;u2@N_(L}7^(1wg+U8?wY4Dpk<<-SCOvvWr zt4Aqi!la+sSdNNJHDNS`jQMFd<s07iDuy9n)es{9KREQf6f(ahVcK1duRmt5y=% zs$*ynI&v>krK`3g{#{?hMpRgyFC+o-1w-N^dZPjO#*5lu){kbh=8~NE{jko(^}85P zf*40XGS%?qW=%#;B}K)R?FHOvCda-5ZcH~g_J?!uc-rpXuBh#I2aMft_Dms}T?_$NM|A(-rF_4+rHFJ%HUebOsV zV-af1-oFWRFLpO}m0{|ZbvdT! z?v@ZHyQHpn`d=`De{kWs6Vn*hY<4+VX>w@TrNg&vAqt}1OE}}Nl5&4ROQQZxoldPx z$tO6|Bgmb1(%w&F5R044Ih+MV6n7>gsgSaZYtHFk7K>9*%L|XJ<|vp+=VQwTl$ISf z{A3mK%t%#zXK0E2)nNk_;9?z^y&L3XEy{jc@FE8!mKhHoID4Tdiaa$1Ki%qLvCgd- z2&M8((-iHH*001m4HxuSbvxl)(C)eiAMW(#Y=^kkG|;8rU}#L)$*u_mk=xp9~lVW|u?q?9#=5WXnu-+p;Q7m1a1#X4N>&RL_6{ z)!&hYv;%(5*#<4Od3L=0fo#USdJdz>L|Y)U5C)YQ@&1s#fVlH5ooC;w(uKZCLQk@w zXQ^8SU1N3ml3p#pXbM1qR)<-cm#Gw8;*rjWv=!REXQT}6dCK6DN@Q)M>e(phS{?x!7zUiS}vqyLyOc$Fm%>MajV9@+8_rp}$9aEQ3<6vebC7-CV zi~Ha2t@i2H_*>6opSenGwaPX{bI zz9I0GW1T$Ht@f`UVg#-m8X`)4ykOIqj;Me1vP7EK8UYM@O&Iefn8Mw4nxgM#$DFS# zjrph6Z@$Jdy07!YMRY7|j(4}TD*29y(#|b1p*-)N4}Uz1+^^S4*?9Id@H3Bar&=}o z^<#@y`)(wpk(OE2L%LD<$;oK^0^V(3%ZxWRBg!Q;d_y(v95iS@qSrl$;c^f;|L4^hv=Ink6+B#lu94xxo$sAOcNjtqMN*x`si0 zj3gD>PY75^h(=nKzos*T6=(}Gl*K?)pXO@KK3F0eB7ycjpykUy$}1>2MoceYs4CGG zKzCs33Z6ESwP8Vjn?ur-AWus#G3DF1;j$IH0YgeFY+ShgmdE^AU2;A&+XhsfRQT9A zsBQcV4AijhE5wFqBxS=E5!A*q$RnF*mrgJnpU-gm1Y!^EMg)Y_-M|02tb4oM5Fa%z zf48yKdggM&Tuf}3ljI9jPZ5W+DIlO~pV!|*WUGcD1c`` z++h?~FfIj8!!fD_JIJ-kntPq9FGp#v`X2V((Aa#QfUpS-1kmpTq`T+C&8`U5(UM)W z87l+!{06CXc)H%Ocz9qAAttul0nv>QT7XsG>2SViUy(E7fYELk!LdOfcb1sTM0AQ) zjy6#a5_#1%eq{eHH*GM3dswkjuN7^#{*3L30@(83&$ou8-Uf_m0-;JqP8ps4^jxoY z2fb1wZzY=!m!DQs@`y#hv-FX^NAO|HP~Bv-Wja1AU@>Cq0>3G0BKd2oq;eV?i(76}c}28A*yd%rp|fxUp=-yrXzxxnXV z4DDgl0em=ZS4cNcy2UZ|Q!taHg$s4MBBfC~OM<}gx|;&Fr-1U(QRQhLN6y`#E!ljx z-fN>*PJR!uwGn&K3h`hZ*f!@!6X39k0d?qB%PPc%!-t4N#O!*-$3>3@+j&LazEO5~ zWX;VMsd4woz0An#zNRbF9=O1Zv2d{Kd6Al zK{c>;`P>I8L*Px9hPL)&`bO$}(J3rh*(#PUUXrp(wW&fcqCQPBVJF})a|Ls^)pHb* zlqNy7X+kaHX9DrfH}{OQtrgRM?s9p*KJ<%jpgEf!61QD(Xzi1h0tjdD%tx$lGAJB1KU#i!-owPE#VHg~_fjO+*qig~=1rpyZJOqo9Vk)&qxcl} z^Oa!p%XG42Ql!Y*V=B!nAkJk|!h|8Sx{O+XE8EZKE>@J?w)#QaG*5CP7rn#l7WW`A z9IkRn__E`%+KVuXjG89gCT zWX=0+>W~YHkMx>-;RS)0wf?AcZCVd>0bq@JSMX0pD$xQOiZstw-lxlhdOD*Co^Xf0yNCb z9r^sa%-RAz??7{i|8$5;6yjslMVAA+mqQpkLHEKA2!yZujyRHfO%ZYI`Tjd$B{(+LEtlI zaldwdd=Q}1xqzS3prtZC3u~9Z-+#n4rbU7N#U;3v71+x%;3{Ru$DdDW|EsjA_8F1* zAIYUrJE195IYH;j&O10-hITjFn}fg?+po6aW}0X&F*VD+p7V)E;Ld;5Ji=>G`^Tdh zzxM{2n%kuIU9*u@c)|IaB#fiAggwmYUKFz)DYa=<6C^s1*qj@KKFKvorIJ=sWH!4L zYeF$I1lHw|7mCPHcYI;Z5iU%cKI|%z#55PWe&Ol|1)uxEZzP~t#=3|>EmEVSE;5+b zWP|Dpc7w@zyv6k4p-t1v+1^5z!p+>);-clEcv0gFr|bl+J!73by+;O0^e2NKzmZ^^ zP8vsfi5Y?1tj<0za5t1CLg`%u~}5;Xa6B{-=eEKfqQNP%X)( zvhac&=P4^|N%ZKkpXN4_Y@vqm3wlt_to2a+G5AB|MA%vPe7IkW=le#WTe5&}r8)a$4nuA&Ir7%>F|O@+KfiUL)R#TcMHGC_njCJG z0M4cVF^4JhKa`Yz;c4JS9!^G%K&Hg_IqwEE^mk z>B6dq!)Yo4x*@Z++>vw-n$&9Ku+E}kBsa92NlO=ypTH9`-8NX*_3%q$HEW+T8|{P3 zNB%naL9=bFMsp#Si$zlkwY}R+Ve=gg3S5W=!iHO+3%Pww6)hnJ#+@Lh)`@o{irBeU zs9E9!H!jY+6z(iO8w4degNu0$N@>{nb*YZdsD#=d&AK37?B#7`?JYIsoG5sr==bH_9)zZnvf)#D3X>#))y(ho0{YifB%}?Nt_EIH5lR#%`y@z4O>%&Yo2ab+3y1 z^g(2j1!q8L!4LW@i|=iO@!~^I{I3sOkb(5cwkquW$Tvw%*z>F~eFiD5U#oFy;8JTR z@d>p<;He!)?{tS`R(kXx(`((O&ZM{pxCP{EvwO#q;J+mUS6EL{2v}NW|AfrLSTmx^ z_$XMCubijEqdyrWM2pU6;Z4RnZOUN$qM7bEjkp~z*H3i#C(sffAmH|t`ud?ZXoOXv zaVgrDE;<66&gSQeoaKl)T#ShY$V2$*7q@;Kukv*9MFDvahZ3sm*eAAY3dz)R2*CI-A#`$+VLXh_T9R^AjT#g1pLn3pLX$*&kf~rY%ETaWB zsKdgvzR{tf?))<`EYE4FF7hJhC=r*9QI zi*qutr_7k+70>0E+G*#~2Is#h{n~4NbAR?+%q;UB+gwqd_(&$ z*JSWl9IH{yxgnXEKQ4M9)th!^gN+PMHK9|kgs5D4{j*S{5~B1eKH6*m5&IQ@t~ww- zPY|iP{6mj@J1n~NDpI%0XI?m^~m8Nsuly9RY%>>#qAgiOefEdpi8bJIMDsN z9K|lu%ze;XlX<+{H?^(`HyR5-d?qpH_x84=akqj!wG4;U)VnA8fm)q0KU`vK;@P=N z$fPP2cGo1#t~4?VctsES=TTUUjazolt-#SU2>{EQcB}tvmiy58FPJyXn=ey(`9Vdd ztSAJ9$p9uRMW|7b_RHVGZoj(hIPI?FCYwL>wL(^3lj^3&6w@EUt4HgNYi9t-zkhY(Kjv-%Nk6bE4-kNs zSDpX5eTX(Hz`)`_folmshyZ?yFZ(M93Tg%(3JMFd?(OVm!D{8~?BV3>Vd>7|&BhWU~8BIzVDxR(bLb0+tZdEs3>@}WuMf{|P zf@N9tkIOvlHw3zlFb`#Y@*6cM5Wz14TXvJ;?nR?Zh|*+8^Un?2{}xp%go%E|IZ_+@ zvj9!MdYXxDOl=Q1*nh*RUBDt|RWD+3`O@c7@IwA^4S_CzJB!4CUp#lY#tk!qzAzdt zJ}26mp766$fm@sFP9URo-0oew3rs7AVKA8BMivmr!v1SlvG zqSVS8HJHF>=+xJn-ypcu$y;V1FK4}+x9YdI(%SxMOhd|gJ4GyRJ{|M>Ld)I4uAQ+5 zQ4HEXmwD_d<|paZjq@aQxL$8VBMp{KCLXP1-nlTx`f>Dyt1sQ%B&)(oej}r@XnF;`fgS1g%%#j&tC@W_(?WDDI3hUw)2vs;34=Mz3EHL1;X-xC$eb`)qagCf*GOjTH%X7u9D!;Cz)7D?H`TLEfnsvE zf`ybJv?eiu@l=hfps%0PG}%@;4)ofB=?3fJjABt*N7!g>=)|ZK+z)+U8v4O_u zQZQUdN_4|cHPuKzC-Lr=_nJB85z?QLGg!I?6BMdrTi2a%r$z^JWGR@M4B0!i4M$-_ zhtDiZtl+y9geO2~PN~rOu$yN>%?XBC|1zA9keyY`rSxXaB~J*QAqX@KnNsoan0!#j z+}^CxAYiiM;#}`T=INt?KL|;tnVW_#%5b07D5{_|B^VYy=;4cDI3uS~m)P;7ATi%m zv=H88S7Z`8n1q%8yiBjC+BErT0J#QcU7>mpd8vYW6Dvat&}QuY?zqSv@*82%J;a;l z)D}HrrX_^2a}Fy-Uza-J#7NvRVdvbW)x!W0f!}373EtOzOn)M~ablRQDu+`j!uJn_ zJ;_;g7}W>uy4brCPc!%Jzk8jk>~R$+41} zU+ie$@;ivzac{C?*;0P6JmTDupiwVMA!uTbj@O*d4?E$Ch@(LYZ0QY9z+!ZLP*G=e zm5~oUpf{i`VP)o19>m8{KS&o)kVv$od4v3ts+!!RKf;l|<8Fo<*4LZ_XKUslo`gANgsjr@7M3BxYYL#$TRb`t zbRxFV!aq;RUkik+osHbx!QSPIELL5Y`gTrd19=i_s5*C4$$NJ{8E>n8>>B>P<1^m~ zytU-qJvCeM8dTW3ugmM*cY}Tw_)$5%pH09QQD)>g9+Z#UvFm=veR(nEr@|?~_mkNR z02aA7M{zf{e%{yRPY<(f0ZuK0D@X!Cc~s+8kLruJK7j7ll)BQUa98k$$$K*NjpQ;; zKsd2#ySqF#IiL0E`r9pEs~{8b8c5-<;n}(yZ*|SRby*fWeMj<3Pji3cwP(0vB4o40 z_u>4pp&Of4k(iy`bQm1K=_lQ&f_})(p4gQ^d&urfs&Shkka+B?m_IxrWHnU(QWiL) zWqEsUb^VVo;c~Uojx6^4xAnis@6lmzfXEi!vB#a#@q#i;S;y7eiK$iqnG^0{3o)+F zYxnx%)5EoTpxr>(iq_jaX@riuj6+T*P-B{n&L2%Cc_;svvE%GO@MDjcx@7lUqf2C~ z>D`i}li_8%W%MEe4|fexdKV0w1dzNP;qL zSiuZ)R>#dK3WFuH23Lwy_o8JIIq#3pe-Xgn2|ypgFEk*GM%-tA67*wh>Y;5&kf8+$ zIPjt9z}vJS0&qJXh!c>U-tZ*!)>Gd}o8_85T{h8KQp1vTKv<(EGQSjw%>B8mypx*L zO{NuzE=f+(+8CEi134PHS-up;FN6dluQF-LtI*!q4G^x1j)+%#A;5UB$nC&P2M%}5XOOUiBUp% z_|`Ik67l__Ehfd!kkxJ-EFwm{c$#S@C3gmJ`O>9dsNdvm$7^WUuVL=hoq2#+$1^vL zBqw87rNC3_y(Ip4<$ zb-a+a_WQFP$OH*TM1Mwvpn|d>cnJyput$VTvIRM>Mx}7SD6U=KpuD(TlFf7}50s%X zc_mB|Oq`IN^dviWDeJ~mpHPa^46N#M9K{(dCV>gjGfRWAPL8VuO~SZTlOhv!o_)WV z+MGH1p>M|Gqi1v&3;@nyI(;Teg`UaeBli~wS>4JoH6Klec^l@?Pu{|K^(&(aXT=$0 z*kM&Mq%l238JtU9gwm!w<2j zl{T?z9#WpbG4cp!CyJznbN4&c#m{{aBzE2&153B}HPI)TcL4XvIH);D_xZ%s?5f+!qii$!bkZTjzSko<_{+_uTP zvaXZB<1bgNR29tYj47;?1X{^m?P)aIM}u3@|6fgG=s*~)g~T9jSR|7Lr6MRuo_5m; zB8R*Ih5sb)8+b<~u;=FTZ`ABVsK^LXxQ^yM@(orM$x50ONGa?)n}=acqKD!ap*_8 zjBn2$t8?p*LM6!5P|m^EEU+CW6XPV>eTe{FHN85%PPAC*8ixjs{7!Rn;>VMoAvq4~ zM;z6|jQo{u({)dSv;KFU$#{pyr&3AV2-P z35D)Lvagr=J$%?B0E<4fpZA+)m%i>pza4E(Qi$eWss)Ea2%6B<(5ku|rmX3kk(@Qq zNiX5CHk*+3p(lb~OlPGaz=MI<2in1=Pq2iDr;)wx1C}Uli}G^r;i0W$1FtEiR5ask z2wve|#IsfyCsi&^Ba{Wz^~ga|OE#996HX;xVi~gVVd*Z*PCR8Kk{y;BPJIJ?GU6Y< z=8aD;?|7fztAY97JyvKe-=#TZsi0 zVFV zEI(Qsnd)UQ(a*1p+1TaU&g`NG|43|j&bs~kgmUAto>$Wao^2SPTL%FMP`$r{$*Dk# z$fRDeOGi0SQ1nA!5H*OK_`kIs$oe=WbHapx+W)+Ml!Dc%L6pS*H{FK>&lvx+4EeTJ z4o;>9Q4s&{?CXDilu!l!O$`!(?x+Ey(}2XG9R|Vb|M?s_2dC43XsP}uDF5GQC;R(< zvN(6}H64iPKk!QkUGM_NqXh{K-jYBY z)vae&S9g<5s+E{*R(0Jv_q@-!=broXe|UF$OSsYO_FA3x#dFfKcur`x*E<`n_SK8$ z-o6rlEScwoUcb@aXl!-b&5P&WYxd6l!|H$jPd~qTVWYEteY@H23uK6P@50TU^^51O z_4_*)R#tlJ*P7dn-tu;9z1!(^Hv7x#o$Zy*=4NZXxpK49-B^)DNyJY(-OhTm*CX$9 z8|@p7-Z?hhc6PMRPP0vJZg#rcjXwFadv#@hyU~5;`pyy=eW%fHt+lpV{rAY&q8<*@ zxp?k+w|#*Pu@nIWk6fStv0vd6-74>;k9Z6N_{NoPbBn;xY4@(RcH(K&9gW<)77lWw zY!WxNx5Dq;+>zADXyA1lH_5Mfz$)Nx(1*6SDCFfMN@4|yz!1?BRX|9-GlXQj(Q3zk zFRq0e4!M#x-T-oXfSs$85$CmT=lV`OT5Gb=UT?n>jRlfD##oHV{M34r0rS?i#txCd z?ez<e9jc()hjf>}WUz7sbBq9%2 z`^|UzaMfV{$khu(yKP*)c#gmwNRBOkMwc#i;i6<|zGX!hz2;`)`c^;t^-FLm(3QYa z5SpD!UHH}8X{?hOkS}eu0FSbYPrx6SufsGN*ZZAwEAZ7;dxPBBY;}A6H}Jb6z5c6p za`{GM>*Bd}BLB@Uz1n5tzaQR|O?spEzS~P)TVdZ`iJLtb^Y+t_}q-{|();8W*={o%dg?cqm+ zaNiA%5@aiY#&2)T1{N?iNEY&Z1qPEP)pTTk)j6XKw#G0z z6Lm8F;6RT5_`k#=>${Gx zoK=-EhZH6BJS2J@l>-sNqrsz)TmoLYJ=`Vq+#B8^pY9NXyM+t42q@!!|!A!me@{{>2kO#4GJ;eEu&5uoEgo>o&!b`V(F zf{9a1oR2O|QykkO^^sg}h7YHedw}ws{#Pj>8 z6o`ZV75OG;gQw*CkHASMq|Z?xd#FH?x`^GWdcd0pTC)Z8?q<|hFpc_XKm)XC(4#%zI-#6ZO_x4O4-^oHgnN2 zbkVV@xJqYi=BjP$zNkqrp`81Hskze2>d9pNQ$?oNdH z9DG~BagoeGbUh;#MoW&TYJmq!kRwPuq2n@t&gz&;5)(SJFD6@rnCR_)1q%= zLp)c;g|=ttx_%6huM$3`DFT|AIuwStX{7lSVns|F?2-SHsiu>|^lGJ8RZ$huxAod7 z=HnKkt>z{fUDXtbv~om$YN{@erdYo0NmatxSs(VyY`WoKQ&3w|#j&9)s_lEVSE`F~ENW!>rvt}~t4#?PYsw4-zIqZWgj#7F-ILIQ z4~F-c)`MhQQpa%GZWO^L0^&m1TPXXAijgky$6GT=fgY4Fz3-A4Za)R z!mRa+;k{A|X(*DafP&{C(q!2+%$g9bDyF21%92#}T29u+e#2UqirnfibN-dR)HNl= z_oj>JQfg1;@joDr&IedOwlAa#1ZU1xtIIQ-*r&HY5e)S?czh_5h*-%_UQyS>^;1 z*cA~NA_mZZ5dO}hLsT_OaYR@Gt+ljTjE+i6tMi5q-B&DIF{`Y%z6|J4R8`irN;_Io z=s5L^5V(F|>Q#!Ha~a``p~H|R$Iiu}OG@fQQ>dLRby7KJ~aR%uRDF1V7e*(zJkVr*X9z5-*;2Z==tC zv8Pgh9MI^kw^~=OHMhwK+pTt|`;T_J*8(`hFgW+-HTaNwXT8_wE<3G_7M;pkI1@It zwYb2AUE!)=ata{BYndRu*r*%VxYBO>g*#G`MwTmSukdXv76A8mz0GWp=QH%btmmAVk81!)Qn zH)=|w@Gm2u8PGXA@7cC%>!~$4IWR@nFtFw(*1-g2A~;&Sjv^tv@5I8)2|`jt3M6;u zt^Ruit!x&JO^HsdeSMqJZ0p8WiXq6o*CR@XnY-wL2}|s_a$CJXN5cw4f<31(#7@I1&BWiYEcnyLiFXp|Thb5`2unj+|%W@7_%(MBg;SF;o~ zy{Qch+Qqbcx;O)`okn0k2@6uAqutYhG-wHPWx45+U!&Sev|GvhzwaIi$!Klk)*)Xu=PZJ zv&KzeT(g!a50NCgp!ZT4z7guuz=)$rUCvH7Mw7r1a-8!1Y9>lOJ?Jmg$H!!BzQV3V zchLW&+urxELtVJfW{KZr!*xb~cq|OQ$1U;D)hDxmfrEE!gEZE&m95WMqt-ArhFE55 z#(4Ww@sMjo#v{(EIuUWFWgcWn(m-|Gb(3T#)?^BY|hIVVTAZ3o~HIXVnbob72MyB~UHBQVZkyWDif_97RP0OMLzZ?aB!t_xGZO=PTC3uLafMeYXpF9pqLO)ua! zy|C{!^rGDxJY|)XaF)O`@adNqs^3u0s_Hl9LiH<_XZc1@rC_tZ>Q}0&epAi10eIO} zKNjT8SoJSF_9Bn{--%v+h~40y!vZQj0cKCY?((4DpA7aETADC_=|W4-G^=9Rs;%Sh zhJ}`%OD&BB{j=863m3hLmd3Lm@H94}r=g1{T;Q9HK91G*(clTR`26A47vOv22#`sC z{KKt3FVs5W>V;aLY2F3)Dr%L^{#vN@6H)6(gjuWg#qwu?TK_!M<;_!c>63U9`nrZ zUX;p~qK{AW7>eSkqIhE4SzdO{GsVq`1$yNhZV3n%i0Dc1dtoK+LdlqCcFUYpwvu{$ zN=8*AO?0){7GEv)%uS$%rnqM=Ukxp?jP*NVuv2i327g~ThB3#US)E;$_c=bDEm@`^ z%lcxk#N6tC>?v+=tE-#TML}&{+~upfJY_FP%K~NxxXP{Jhp?jp@|AbVjmLwhg{L2# z=!W-pXQO%ifbkG4&m~^2O{C(_h5^%ur|UXA?}x3|`h z))ys3vyax5QyZ;sciNrpbe6fx?dke0fS_{6@A^f|r;R_p{Z^O^*Hg{=0`U}dQE9)L^+gsT1xwPR^+~;23 zhL<^ioC_O19UCqa8~)dYsXmpadVObSB6WT?jP;rAelRD-TGD-AcN}kFtmoBOPqF<$ zePdn5tP5j39b>I6jP=4;*LZe*jP;rAhau0$HbqUb4d1uHEH8}pTpH^sHpHlJtjoH$ zER6MZjI}=R#=76^^^YGg9)e%aC0;H=HQLF4B4&9m5wmb%P=TLW7iK;-LF=yJXyS}d zpjfyt^<5Zi4!Xdo%Vr6)E?k)DxG;0SH~=opFIm!Id10PVIM1wkDl6$ZKJz5{qHo%n zbhss{vY}#^n#erqnxc!CoK2f2)zMTX2=82iOM$KgmVy$*)Nrc}o%}Xi-CqBVR-3?o zik2u=(>+i6_om@S`@sueh{7F5ZV=(6tW5xsaAY}qg+ zjOimvTDIY7K2OP{@4;M;_VsN>=dBxmTj4$CY><1eM{OKKvd0e~V}PFmEn{d)5~3+v z?W^=}9O75&;q&W+63s5tzq!hJQ%z}Sw3`>tz16(hX$o(@&Kt}uC&BB%I3~XjJQw|q zqhlA!h{IIbl6`uE<2wdO?|m1*NL(AogIViz-q~(+-+8Ow==RA&Ef8FQs@(v8gU;zo zopsYr36rjhrYVmjOtG+R5eP36(P(y?8jCxeC;Vp#QM+#G@ znatA{8xj(-(Plx53{nHBYoDq0GttgH;ti5Bp0TE&=(tW$rFOy%Fw`j~&C zuNa2pgkL=vJRN=<9dU>aM4@Sa^xz?$Z@4$SgTJHBqV&d{Y|kzJ4IG$7_OasQV^g@l z`opb1%m}s|Oe03VkMV*%$v!T7KQkuDF_l0GJbg+)6?l<{$;Ply6NJ$)$Rn z@Jjl;SgU5OSpBIL^tO0NwBjE9O1eHf*7Psklp<^B#VVd{tM`YMtiUA(G zd54?wusWh<1XgWfXZo*yjB_94wlt>gj}IxGhWCNb$Sm&{og+o&@d#!_F6@(Ue;*b@ zr;e9Oo-I|pk+>R_2Y(>i^*&`=u6HwB%A6f8;C;mX@MEG=cHon(oAo7tLj)=}?hx$H4 zO9w&^zd6oVH zF0B|Q)C*KW{f&5kUSCjwAnq5_RQnW70zi`RO;U0*I3N@LAN)B~uBKy%+?3XgId?{hps?TtrPe@8hMkyM?r zxDN7E9KdEgBQU_Mo}hBv$Ahn_#^tTi>DR$S61rVh20|7PEhs4df6P_M$h<5G~xDse;fbT+I0XgppNa*+AbrJRV zA?PbqhlyhdQg#cRKwv{UV9r_Td1K_6LwXf-0q`7w<6!t{fpma6CByE4I)onNe~%{! z!OVA5V^WBJfVshkOuwm+OpKX3(j~>!#Y($S zlbV7}Eft`ZCzP_O!Q6xrSd13Zd<)ZsGChPA{AwaOil+u%gpNOsrrzTSX zW|K$A7zGThs;Z@+4Ao-bx|T6TwtTD-CMoNuKpviiyOtY^o@H&f=EoC{BGDwU-@~CPW z3zCww4Eh|HT_Hf^XIDl9*`tty8X|rzgbVN|I;gQz4Nh!2v|v#WJFOI*+}dd%P0}SN zu6M`*^CzjtcVJb_@5aXMYPYeCIyt3us}28u?tAaQQU;)<$%ZvPlL?5qDxmvx#c4{f zMOqyI6$tJ>1||nS5|O$>=ES2ZNYk<)3_d3>`R(v7k)%TumN1-)nBfu6FOyuakGiOnZeE3NoHA@F(WG z!aPxK$VD#!H)FVldXuX4XOQkfK};hQe^kskzSikn-5SwOxyAy`I3QeU_WHdOg&-jO z+`QT8zEd5FYRMDdu?-W~{0xq&u#Ds? zwj>6rb?SL!nQzhlK7>^fG=A)uOIRj(O4JfM;!|cF!?rC|G}GsbiJoTZW^xgK-#2y7 zf{erT^!n=H0huPy6)ir^l@EVQ;!e=l&vT}qSP%=>7)pYJyrm5|U@O67U>hnKLCJSr z!%iVfv0c%2>Dh!4vK&Ly#MtU`cuC$FGjkhOgf@PaEEgTS!YVA&No4L4Rabxl21Oo3 zBQpwPX0!~&Q5{pQlF@Qh)fQuabW=vuEmfwqNEw7DzK#fIU*-^=o6)K`=e+!97K?cq zDTFthkqTd*JHuMUD6I+lng|$VcQ8xN^y?85kvRX1p~}-tke|)^AZHb*VoR}u0PB5t z0dft?(hVrai;1ifr&rEZEJ;d_(7GJbFuuT*YA$IJtB~S)pdyva8Au#|zrah4s)<0o z9e{(%`~uKoM>LNV1wGUsEoxrI(VhzSNI$IC*xo62MzbcKp^cjs_db5$!o5?)k56j@ zcUBP6z%4i59pQi{_+nWY{5fHGz%_v-muJz6En5#n3$)K$tiu{^9suC^vgI)V3jFVM zGNtJG%EjLW&yOne#uD#;%gs$xPogE6!Y|roRo>%)nOmD(gei#m2*#I%%y#GTUYe*J zE_+{Lx~Yg2Q%+q`9;OU@#a7jL35LCiU1V5zQ1(1io$RYv?^#|uF!F_k8Btnalp1@y z?8)fKCVVvkwP=+$7Nk?^%{7^Ejf0u$bU@`%UN%`9Hk#6S2nHH|jCF-~P@st7`<&`C zu>8Apl4y%yiDURlxS9+FIYcpzGg)R=D?E~%EEmm*Dk-5MUOjahl?Q)m65xyAOfzed5-F6|2P0Q} zW9RXHSjP{kS4`W6RohR7yQz3*B|p1r=%#Dqak(S+Lnf1deF=<&7x~Ki#GUe#D{p!L zPIj{dPmsgLv_WE<2@MvWLxLx&d4~1LXXKBtJRa-jE8#{qOf~SN6mBF#Rt-;zH!yHB z%Rxg7`jn}%3oolUiT;v42G%j4_uDsEIS%0SoywdJnXk0vZt>53du(Hxy zzt-Gt^p-n2%{IBW+39XK`sB~<)fI-i?X4A=@b=1fqtzxbbX?d~+q8Q-WC~F+UHSVb zeJeMV*XTEd>)lq3p>|s9{p(#K8b2qWF6=~Lkxvtk*1mD6wGMNJKL{!q(ZrBwm*}@C zwZiXz&?g!I03}Wqx$&iLw{!Dav#|l~R}kmPQSi?M6l+_pouIX~1#f`QLia**d#y>J zBJ2zsi5kGIZ}j@?6UFNPkWHJ&r0guYn&>X6qTw&umTD{+qHn08YD%u;{!e(C$iVd; za8+Z=+i8U)medR`w_EGoPOr1sUtaHQuXHwlH(Tq?5Ss*-lE_$#+t!T$g})KR6*>uk zwbxz0OwhA}pZncrfBhPK+$3{l*H^e3h?p1`@K=v$4Pou(KXo>mto#?Ae|NLH4ZjJ1 z!n;Vi_ZT=7J!LYz5b?$UNv*!>_>Qb_d|Xmu$5Y7gp$h z6@(ukW*^Cac#o3@{%(*f?gQ+tI7;lw9=)w0yC|iEW-Ln* z)iZS2QK0a!mfw+DK$*@;)mP{&JS|^;Lm0jI6!~X#lPvfs;F^2~ZV6U~zTk7KkUK0` zq=MpCmcfL9V6kkUSjUfsyH#rbva~PGBKXiPqQaQDM4&?~SMaD*OV<=BT}UL0o}|ht zk1Chy#p}%@s2($SV!>%rU!4$gcprBCR%Mvg&|%NiSVX(o{6H&i7V*RB zh#!zza}YlOyDs8~8u3HEOrQ3D_(2N-MK|441(jrqx~Bxm62xRc5XKM5izDI(dZ}2E z*Nz|PkFlZw=y8!O1sx|Q$j7Fk5WM{HCZ1(nLMy3VR{<1#7mR*s;g?hu9vhX|9Rw8$;5S;%>R?inbH!%Z5) zkHRMoun`6;;!BPh`KWo(OR3i+Vtc>oA((CyjAEsy!%qNDu(>M{HWk5?2?i@ewT3?- ze_e|OipwhMgH(qTA5rr1o}cH!I^}H9HY=!4(VF3=7F@N8wv);l z1CTqJ2sfJ_3t1{}T~3q@CkWCVXI0rHURBaaDh}*~orG~l^_qx^%Ngl%=mQ&la_EB@ zzzlu3_Z2CmF9*psE@fIs3?$nNn*m`s4-Jc+kl(vlDpDhJ8Fq7j&nu_bWZRVG^yZyB zk@f?{3gUg591)UtkO-0@+D2|)bukbLEAZ@`*~Iisa?+6Iq8(leDgx_8hWff(vTYBn z<3se4z*mBeaR;S;{X*#Ed73iWsba@BKmQ^mGEQmWNSMTO`9`g>!TC`}oM<&EgO!iY=$FTTHRbrNq~M9*>#}R6mT5K9 z@Kj%nRYDGnCFY*PcgZ^$4~WCo#HoQ#v--Lmr><)#$pzGzMBN##9-l=j_z80`nc3tl zvPq{sSp0-UMk1FsWx%G?j3lcSP6b(}(+B13PQGFbmZ=M6wH9}tr7NNaYqYf-K?Zer zv2r|H&|hJHqMiNI8u6@Kh)PZbS5eH3&JUCEamI%vCx$s0q(&Y4j$n<0)nq+q5ni}U z5sFo&tUeMfm(CeR?c#A$D6Y;FcECPK9inKiMcltCJw$VL$jL?`2Agv9KxNEPCa6 z1uFSp$W`H0i5-B&gG{fD)}GS`xCXZ;_LzebpD`Lm{8t1nxppm5G3#5+Mi;ag4!|mC z1US=gi`)(HUp0w_;O1YTzBF8`hbjR$q61tN=oJbjZdg@}i`>Md-L8>|tjgZUh>z7b zXQCZ{PMo4xWO{%k!^(~1=`o)qHB-L%6$9PX6tBwpg$wh$Fuz4+XY^_J3-db>G_@;& z7WQ>vUuS}k3es?SHfrH4*j?4~EXj4!O%!$2uq7|9+FID%Q^F{4#0c8u(<;spMFyt!FU(iPuRm(Sx2dX6<;~mRec5OS2N~ zaZ;7}hF)<+%hl6|D`<*tn39@2T%p*|C-3CeLY{n`bDh!oVP;h&n^yr@#{L;eg^C}4 z+%z3iz_Uyqq6i_F9hi6w2HAVaRCG|_p1@Q*sa7$F4OR0#ms=KM&ktF$^XyfsJwz9NWVNEE?y8v={Epn!RxbwRT`~iqsq4@%I?TgGjJG+uLvv~v!U!ZmRWK@C# ze#o>(Nv5shtEzz|N|FYlAMZ8?4dqb{@wjc)5sU|4cCSD4GHBgzn>E;`}_Y zZ6s?Q1cw*F_wHqm{08k0#p(NTGs-G%lj6FHW22Sk<}d1MV2WnEccgrOs3(AeeUNf#Z%^wgA16J5tKMKPI2 znhZ|`y!jad%wj1x3z;>lEoT*ebSih5&Lk=CC|9``WomW-B;tVHhmK<)HmoM=G4wIR z7CVHWp8&D;6M|G3=xSSDL^%jVJxE1@vMX7RsAA)rdbFAPVxAO#HtH$ZXumr63qu=p zOM}GpA$FA`Y+GzxOWB;ZuI4(1kID9i>e!kUq#`|Cl)%NCKs}rQYQKt)l_R(sfz+hO zGD3gg$tE;S`2p=Yed|2cPwZywI~BOwkjX^ZhK@jq7>ax1Ja!|*^J6fxC9t-Gk)#pd z5obl~P)k+KhRUzRzskz-ootKeMq9N#fAjYuTX z@=Wz)BUXHS*5||MGDhm>Wz3wg7ok5$cWPp1_0+Rj_bA+dSe5538$n9?zPbG&L*W8X`Ro+q6=t`<-t0HnwVqr}Y-5`~I&6Q)Of=)_~S>x|a zUCo&I|C~tcZ-;k>cM0|(Dq~hR;yog+Kiv8~^oGqG8iwj1>h*e5MUHjV*JMBK=op5i z%9a!5N)YFNo+HW5+@LpyaZ!uCpfPX)Vavkce`8<^A#HfnE|?i?dvC|2zksiaCq7sL8ShNWmyDuNxV*BZfi*0 zkt(C~*xcM#Rha2%CQWLju@3bd{U(T`kkZe`M-o4Odgh#tG0yHhL8?|{%F;86PnLlo zr3&WYKA|FZtet`Ul%EMcT~wDIb38*%2@(JM6Ma9#im;9iUO*K?t~r)$nr_BQI?YNe{x z!0<$W(M{*vJk8R5KaNpgj>&}d?86obk)MrQFw+|2`SUm&c>!)Y@(A%=lC#f?NhEZu z^6?^Rj$@b_WVZOE3~>To*`H_$LsB%`iB{-X#xg(dS z>65@7A25e6IPb4g&0GeFReixf$Mv zzXF+dpOWrco2yqv*#-EhVoa4C|2wKv*_gLpxnA?uV0av+T{I0TQA8*z-OB+7-b zHi-B#1O#{sFbrxHmP}48j-*!kY9L|oH$Ihz>WNFm6>uqI(fCN`g5-B)n^DP5_^vO1 zc|mHiZj8>rs;+YOq`bx{$4-2Oyc#v#8tz6%C+3JK^z4G9RHy(j{}p2EHh0noo&tic z-_I8utVk^oT&BmsvDz^b(NLWN%*OcPAUb9xPP|b)g16E@?uV!N0Z*YY(u8ZKDow{1mhhl|JE&w0wI4UfL$(qYNouAyev11U#VP%&)$K+-e6d58#>vhzIELcs!6MklClgk6-GLo;FFmlQEN9b#+o<79Nmt{@#N{>aDGfEYhu+Kpg0TIG} zh)4W#P>6cOZB>g@R29K2z_VO$hjJ57+w&11_h<|eE`y-##dHK?f{gTAoCWUY7oPH0fTj=89UL-K9ETu^P8}0C>GYIu_hjc_q79FMZG@4PTbk%^VFm-f-Fcs!l zs=}0Yoy#~0D%BpN2y?5~R34)^4Gttj*O^J;CvnEUOzm(d=JcWNF z`9|lJhhYerGAr^yUmN-pqLTxcNX+>+S`d;OAhUp#IZo$=;fMJ7A@cySI4I;Ayq3o1 z0UT6%5B)>jQVChDJ#-}rL{)gqFf`qg?35ohhteBXca*6-8tVXmj`oO9f*1N6h#`QF z3Ks7+ctLk#Q3gRobd4p<$#fgm1tf@41?_4ed5$9i&Q3Yn|A42$ z4Q5^90y;n-;2vYw-^9X&p(KVtcor|yxs{MBTR|X6scIih@g>n#OPk2e7jg?UFo*Fh zlCc00f+$$TW|3BZA=(F6I>CavFoJuQsL~$pp68c+aE%E3gh%k9sw&6G5~LHfC%BxM zJ!NGYIZ=l5lVf@165+gM;{K$#I!8k!6*OcUsd|S%H_UB<0^#d9U_&jaBQyn3CYsV9 z0-9!Dhr6#-;ds#vWKqTZ-5F6QIS2}wkj5|+TO3;N10QpL#9#>wOnZP;eiXX8SXv7? zuiR)E%0{byVK!`SNZScw`TvqO$QgT{_m-3k4kCR3k_`(iG_;~BvQo*Y z;y5H?!d1fAuRNTH&Ci563FKw1Gfj0yrMU^SQ_Z{>ifKpz7CG0#DbrHbaLPNxWkvzq z^6+%}oFx-~@Kj1yc8b(0TWXedSC0by>`vTg)b%9@q-ZR3rs&x##1ljB43uML6K}aK zco3D8fBnzXJ7*JcGkTD~H7;i3##iTvS?`k-R`xvHit-E9Y>3 zS)sV)F2cmgBI*;Ake)|#6-ko<)q#_5lbBOogqKTj(pBZ>DZTKSKMA5|p@>;cY-Op&vd@#=C7(khk@K-mLJ@8s<|;|1|Ni^%xR zUP$zP^0xalf=fV%RTQ{u90RuG<|1%%5zX4cA*IiFmA{wP{L%8x(B4Lv5C5OoHNmjlL_P_Dp? z(p`+581>4fh*qBFST=NFrzRk(F9)t#BVaxi=I*OF#EEjth~_6zeu8SJG=8yC16S%X zDSEy@Ytp1K45DdgIQXU9#f$|+P_9m_{PMN9R6 z#J9y_7xeE6g0Fm=f_Ve_WiD7L7pBn=Vd{@!oyKKH1#geTMes~^38(;YbQL$f0u3ow zFb|f%xLXb(Lp^;-rNb_5Bk&1f#;0|4vLZB%H58`)sw-R+Y+*@o@b|02PnM)tgr7Q9 zG>5O)KKU;RtE_5y8{ z=46@^5rMM}$4jQWQnVgrTINFxze1UTf{CX@6j{AzY0ni#zMMt)xP3`nXq?1x!HzHN zLd+jIHeN!0vEj0Mg#Vio(WbzuAQXH+1W^TJ0t@TEk)BkIUD$nyjfQ za!?C7XS3Dq_20nnGAa3g)p{r*Tg^?>St-#dt~?vFp|2+Srea}l&RSeqr-}^WOnG{q zZzy)U{z4U1-4Ly0BQGz|6*s;_!C<|3bHGS`9l@BBX2Y~!a&{*vI{`c;w^QymTx49+ zjfT_0%u{08jfH8+9I?BYoqNVq(c_%{;+Y;-IjT79*OV7mn6_nq+Gc9!lOjoy=gGHL0mY=^S5XO=8U_kq(bdZgEU( zC&*C=$vdbL_`L^z6hu~mGI9eu*Qc*au0+=i*Hh99-?@f7pW}*WmH2vkR{4r`4Ai{IvX^eC;*+bk= z#B@sqtSgQgsBXILg(z#H>tmCU8B6RJxTg{d3-48GkVj%HM^;kczI39P&vGj(@!CMx zA_QW1SWif?V&%?RIci{l1^wto!V(GnbSMZJ&#_|LtI85pFgv^qCN$hZfJJYW^tu^n z0Y;)c?|Vjn;5fJ#Ij6Nm_Q*lMk<3Fpw9IB~Hnxmysy@siZvXk1juwah5BAs9n z;YW?_ou9!a`IV%;%BK*avh6x}I80&*OOXTERyGNLg-T7=bSMPVTUjaN<1(P>^QiYm zH3geYR4TQK*K{SY<&>xp55jV_mqS$6I-RZAN{Z0gX?7d^P8Y;Q_{n;w-RmbcEJ}~? z<|_i;E2DZUqgPWw!eO6^qNl~ruw_>=lL_Ai)hDJp=toBN6DGTC`Kn^4Lww6O4GT*g z7i6D*9@+oP#VSOvVk~vn(gNRrMFWm(l5R=59whU!#R>lfg)$VncyY8YuH0o=_R%GoK5A2E@gp^tBd-KC*wHyd@?b}eP6woe!kyy%I`jE zbvYi0Rgml=3s;wzUA4M9eiiri_ST{i0l0hGny>USDydjMjcI@=tZTaLCIy%!vReR9$5Hru7<$wrvEG)_3LfLVi`Nk}l~p-$_H zoft0@al|~lbsws0z;F;r$7U`um}1IV?B|jkHekRk37kB;P|ui1cJR(P3?a+&&nL<2c2 z;s`^O^K)41QdbwP?sn0YigS-_Rm;Sx;#X@fks++k&g;9VK;_FmX?YX*HktSClk>7M$d6(pd6-){Jyw?`L^?X?Y zc#uykyyo0P0~S;Qhc)>T_QTBPhKduX+|$VsRTVqHde{*ZM*c{b|&q}NhkLyCeZOt43cDu`MO zX6s7P%{nlwa9zCN@U+=zZ%wFPO#`TsiDWM}Ia)=PVl5LO#fV~@j$F1(v;-3k<(sNL zN+Uih#5L?=SWv`Xf`Hh6hZLzg^9ck1myj6b=7n1XOdy~-rnO<~wWMfa*n0DxieEN+ z;YGK!f@{+jtVwz-SEn@d`klIER#whZy8f(^0f%#Aztzku(2%+$idp2x`B9-9MI=zg zBv$HL+i@;=RxZUqX!dRkI^3E-yP7iCxYeGtAX7Het@GF8H54*`9x*ppQ~&`69-TmGW2ytDM2sEd|Rk zR38R=?_6wU{!=%+r-R*C#hb>I5+zxW5h+l{&1O|w5^?SK8WIC~0RfEV`s3+)ed;4I zHjR&b%0Y>Q_8CimK)5ozw{HS%53m(`bB>Nwi_4|@Q4}MM_!!VQmho5{>ra!9ESmk2+f7L0FGkcR}3dY zv`$M4*ors6m`8$SMy9YZ;GRm)9&Z2v;;OM_dK)MZGzPUUk)maVMj55jEd$O{Ygo|i zP2Pk7A9sB556sX zhkS!(3Dk7wylY2-|KxvrdlQ8^<#1xDdS;~ZeJJBRdwu+ZU9So}evwJ9LG|6Qm zW3sr}f(9Uw=Lu`VlLzx!sn%scG*`T8N^E7vRo6{D)#pz5ew-xEu>+iI&QK>fLdZIP zAjjr{tIj8>Ru+G#dv7>G+Q~t>L3ra+4fMhU#}VbVn{Kk$^+a4ZahX~{4R@Au?K&!@ zL|GJnL}|+2Qb3l|;T)~WE`(x+AjpMtn9xDo3pU>{=koRkR}v|8VV!9-h+dJNbi%Mg ze?*YuoRERYje;oLQQhVKlE6f>aDzx7a+Aaja?%(g?BWQG@oh<<(zev*;2+3DIh^F} zaUc5upNRTc{8!UB-Z=bY&y9SdCSp%I?Y$&_@snuUd%0wX^8);F4aNMR-mZIh#|I&C?!yu10;yPPO_2zbNoL z9Q(PJRVa3$kNLDAnq!0sYMcIK6=_qvIOMrL^#h$_wwX~mgaC6f(`k=XC}wgoi}@gb zuiHR@!mU>Hno{N)N8`+jc-`rowlrg2fcYFiEam z*Eubn_qwh2qa5iNAO37N&X#UzU^ov6W_T^Hk5 zGbMOZi6UE-WR-{M9QCP|CK}KMH1d4C@W$4lyD333hvkZ?R%v@jYUlKXTc8Yo*AY%1 zw9cNKwjTbrx^Q37g73V4E9*3*&b+GdOjWR^%=m-&_veguRDJkUNmR1ZRbJAeATP#l zgmi|^8AU-Oo|=REjiLTdLwwSHv=-(AF6@Ni15-y#s_vXyt#sznS(X2q3zdo1XC??CSZza=sYFUK_ zy#eczB6mxxI(DvHaWa*zs>bvDtQ7mCsMk{CEJPsz`D{K$JUQRp^0(zn@2&8WhHq;Z z%PL)xymPj~Y9Ss=qhzaYQFXH{mIkTe|6JPnnLVhcHKqYC*?aAUkQYy{%TAk2X_q~+!@^6-QAtw4#C|axVw8eyx+xtaaOHaYc8j|t9RE_ z)!q#`zL6TXe-Ir5TflYYD5k2GU?`0aWb=Wny~B#uSH6Z%FSLq>cFm{Z>QocE#9j_h ztK_vy)%E*c246cVw5@tp(V$Q*n0cBY%iZ!9x>~^X$y#-Vmx}2nv&BA$&ngUWL4l`` z6igQJ6xMRx;tdJFN*W~YY6Ipt&E~TM?20sB@neJi7nC{-s8T^wTl@jlTbh>sRa||gI{mxa1QdIPpu*3 z=98|o-w#H41^&8M3`{3^*TN_N$3l0T3in~ka8y>o!$OGum84Mu!YFXJ(%{sD3a{RN zJ>3`YSgq_wQ1H95rkZ9`)TH}Y;ED;3dm(LDlhsC=4~i(pku?kTQS&VBcof{&wVBOP zVMR~73h$FY+z?2#6w;~#?8HG43Gjo@8(Hf{c7ouBG`56NYbKdRJQ6EY2N)1;I#c}I zh`*9bxqB)YBez!_$kuF@msQGc?CbG*)OuBlYxdN(t+Xc393h@3m+*Z9Qt7NtG*`6r z6~@rU`48%}tX6Opbq_n1Y&aa)*=Ea9l3U~fFFjF_{r-o>f% z!2(#mz`CQ*AtgJ&XGk;wK^VP!1W!J4F5UngaW)$PdkA5&v^EAxaK6_BQHpNoajG{t zHp;G(Fjz?~oQUjuT_<-hJuGW4lgc^-Rd62{{XS;ug<^ZYq%LpzQy;*OK@W~gl`vH^Mz*(0+ugOqofj*7Cd3J7>qi^1TvgV>haKJi z)y;$5lU(D4Nb>t+@Rz0B**<(|QZ1#ts|Nt%#gXzcyJJfCJQXOH>65Y80b)OMm=#&* zxn&H&+=vwnCNH2v1F4jn%F!`6#8^ZYV1>qq7b+5N+`=EEsbsaUkvVTJ$Q z2k)AF{pRv7m%bj5nVT}zJIyKj;&BwFcJd%Wxzs@=0pcDw>SFL*!kYDcYf!wa**hc0 zK};Yu)RPVDE4-8u1TC6uqw8T4C*W%!ka4nbG()mo>^)L>aLXPprfg-2Xe9c`OxA>}X4Q~mQ zdp5u*cOsS@ZPb{eriYd5-QWC(T@@tWz#}z|JFz0;n8;+v4_EhmnI@eWR4AR|!yK80 zu#y~;hJ{-qlK3r;2o9ZbTZ^uCTx%9G@1Z4FKQH#R0`7AlmU%diWecm5%0*?uQ9^(2rtS|l+_=0?(dsJ zNrpSf?)x89&QAp$yD_HlMk23z-ot&t&vyO+UFxsNUUwc>6V9ecQM20;)w+gARNwiU zMh2rl#L_Ali)=24!0Mv)3c!tGt>n@i;10QF52}yXTnBVPc>4oQ!v&n#nH=ABg8;8* z-(9D-z^7ZoQ&q3@(j4bBo5KhOLF|9pF6%Em+pTn?i9@$r zG7?ckm}fLT?^7SVn&6yP8izNB|87CgewNNm#YPqpJsm3_l+cBjA*^a2zm`8#R=N`R zcMFIV^(tQ!BV%=8!BqL%T;%U}B7qumY4l`++=b`9lw!TV5y=gD6r#s>=NYI)qmygl zc`WB-`Xh=`#7!9As+@?Z#o3}asEoSiZ4%6Tr}usK1MT zl&8`k%GZ_p>2 zYpUCwetAXb{|ZIb)auHTueMB6x#6y;)!h~fp%$<^VUbnakR_-$E-HpoP8yy>dlc)Ln^KX3M<>*q= z*qm?B4bL_BZ>4}t4ZT_hf(oQdosLvTx7(}@ACDDR*24%J7FL2UQ?xst1t?hqtrP*S zah0+J3pu^~RlzEC?M||yBk(EI_=j^xV@d`=c&~)Wq~y+l@)-RSJg{tWzk|`gT(!jK z>9BePVyBs^+(^RPEi#E~kH>5(pjbQkgNe-?Bg(_Qt=2s59|Qi!RJjv+b3cxra>ws5 z+R^htl0%^bV-ERhz>fem>%wbsz5>qME1%efIb=SH?|7)rt((kYcVzH=PR&RB*hhm* ztLlt8l-g9b;4aX@ zH@XtHyZ1vbJFqaK3!d6Eb)!8xVVZ_>lnpM;xsagM#Qj22&stfFs79f&b3?*%g-qK9 z*BKk$FUqEW+5ubIeS46K_J9-`xfZ%Z6<)1F&!}J37`Vk}z;A#fboEnHXv=W2^u*Z+ z+V2~b8cHe!><~Tm{XmcQ7rRG-mdUJL4GbNZCa2;bEB^Sd0%^ z5h7>KBF>U%^5?KOITgO?K-43n?<}i?*Rhu$8j)_;kU*#x=#kUU4U>s6+Tqp|9+mKg zPdRRgWkA8eo%AY=;Z_$h587E-gfB&7R%xpbZ12XlmeN-&-u^UK`R6`^{ErF)iZeQ} zC2F$ybyq3xJgpULZ$q_Q?a+;QXIbS^@jUbBHM1|%Rjro}y^&_$;VYXb;#o%16Jc-#s#K_?z?|p&ROP-agVT@?S{K$$4xMIOnJrMxr>Viot{5 zeI-V+hlbSi{EWCz;f4G9`RP+MqSRe3`81PLf&sBK=m2fkb9zk=+Ob7V2)eJ8btm6! zsed)_2w#ga5O4D#^ zQ(Y>Z4F-QE!NMtIM7h{hK@dw8!2%%Cg(U1G5+^dUK|);Nc%nT|g3bZI3UAE#L9WBh zCtKmV!DpXs9hPSm|qiSVC?s;|oq0rgaO22T)cQt0l*l~0K>Dxs7#uNOmR`k2#fDkZ~A80u} z*`ee9;bSB)Kljh`724%iioYtTyke_k+pApuLU62_B7kw>`8}eyW%iL;{`|eW+z)wb zP-2tjbwdg0#Nhnbc^1vmbXp(`NkG9BPPH~Cf4S(}QmtTorL2znBGllj{U@kXS?7yG zV?0Q&J@?TV;SuRO(&eO+2n&Gvr+&~$mzZw6ex4?QwI!RDvpllAuvxR!{=xkt>FM>0 zVfK4LvtKYuu;1zGawGe6rC&38kZA{5CvCFj1gjN=4(6>a2XlGFzJX1HoXAr!>rL7> zO>?oK6;{(6q%O=Q{rgQ>o43+wD&uN|{OM-7+Qp?s&D$<_k?7=gVNF13s#W8rcl>w0 z?8s=HXu11FY%8?Y7{zA%AV{E=&me5`?;rQ!fK96_CUM)I^#utT4T8V;RiT7Ph@{A# zKkdFOox=quaV3}X@tk~E6*nwp8h!Qq-fsVsd(Evwo4uo*{^;vBIvSU5&(n?+3(H+( zR+T_Ab@NYCFIo6j;RftLAWw7sHUf2kuGI!>igz|=Rj-5Q`WFtL;d-4h$eH@cgmygD z5=|m#{LqIOcI(bNbSWHAr92q|K)acF%j3I=o>6f&d0>q++`lU?V` ztBhJ!eft52473HHGnrf*V4-ilbg5}v4f=3(HYhD;_pL!n2)Ukx+x zc+U@pCski{=}!Zpg=DwMZCkY=vuWkpN0jQnVXA5DHRqyb60&(95fj-0Zl}p=-)$x1 zeMLqV)F?FgtpQD|uT~@TUX)`&3kLLC1p`r}oAt@2RdO??_W1K%8m(=a;-o2*c_1Tk z$JL2ruOK5?G_*lO;i_>q+=Mk`Y(os?7?BKW79lJS1CzuyEoy@SBB4k~DImGprsoe# zKR5_*ZEy}#+)v&V&Cq*Eb@WGQZ# zM!L(2K)&*@U;s%U_AOe(OdG74NOVd<@BdRnSot&~IZ}5DlmJo`qdEJ(;MMm|c5R;`Re_F=6T+U{% zr77E`Ap*36LKp3gt#q2qoYvmBM`o1S2G^Vl{5OpXy)bx+D8$-zf}hg}?a8^8n&9tE zlI>od15A)c8yRG*;L@KxFnqkY-kWt}5NqLk!a_5{iCE)|o50M$%_(i|5=C00<&30O zK0kBw*>J3;^mT`ZeZk&o#){c5jzZlDIIwV3p!e2o!4PK3r>l=jkKzz?T34QbTnCtP zo10Ex6Uf7%p$+luPrEX5-A;>{rQH}Wi~Y#tNn%zWki{de`!qRT5880#ugW;h|7LOm zKl7FKB$y%PsSMS&u_rQk2ndeE_`>6=k~we^7W-Auk&&;s{MTF7P53yaRFfOCd@Js= zwg`Ng_wxq5qwHgnkAEBoD?ydYMFXW_Cv-z3w*i4lQ}tEsz8p<2V~RTnOI6q8ewP6# ztCg8rr3zJh;3wqEUpUq^zmHflbjqzBG>}M4X*m)j#w9T(5LU>V~3}%xA+^7M98@%N|wL%}-k?#EEhVHA5#|&r>OtB`iP~VFE);wLS$} z291hKR*xj&Oo(p-2Tb$gNy{(0S!YJ)@=>t6f3V7D9n$w3A#0o1tR;|^`9dej zR1a6tL~-(2f_mk4Ax~ij-hs}~e$7L{Gxqi`t+GXHOPQYXWZo;dCR5(H;DI&*`7=Cv zw5bHdf;VpiMzaR8(V4;A*-4|z+%C3^`%jcoc#ttGJHs9Z>%snVU!iG(%2EdLBOICQ za2w2YI7fVx*DddNL#au!@o9~koeOuzcG#jdGBv8%Kb`K;)DWef2-sO1<`%+QOliun zQ9T^%W6P7m(8{l7REns%zu;IyPTx2P;Ej@)$X&DcD(rF&>(Kc;p8u(sFZp$;BLph1 zg*5jj%&h7SS3vs{fls%jvf(6{>d~j+lsJ#yye;4QB2nSS?6sZ@QS_cm+MH1K+7tFe zX$^86G#YU+BgbP?0zG{r(uGJ>J~>uhSpl-^@}Bypeo3T&6q36HJElx~#QtRp`%YWX zHljle3Ej#pixqw9LU_ET*obL*FD&*T+_lY|FEj;WRQ|MSHM?PCN_bJYYIaVLea=!8 zCms^VHkh9;dd64P??peS=G#{W-|Dtj-HEY@rCZHux#{~gf#5mg-%^uv_uuCJL{KY7 z8m&|=QgbU}mx3cz1sSnXxW>l!GrQt6%;dtg)lze}uZTO7n(AWA{%LYI`&>zx1h)i^ zy(Q_U>mPw&jautJ>8n9MhWKHyhcOdij2(`c=&TfS_95s%62W;9u-7)bb8RGgV_;!? zuyA#Q{zIhhK((nME3S(XVN}~PV?s)gVJNZTe7z3-UU_ubz%PI7T7iF`&Ka0AsDP=C ze{-iighq-7CG>MGV?jJ7y|eAb;+da-NH7uBL(GNQX`?4Qy^=^{?ID$`^ECVLhb&jL z@u_P?0CoO17`kEz>`EWR3^A;#+Jp(0#54eh2UP- z${8nW$;$na|-+G50`Tp=uDi}r7D@8ELX>O{Xb7$e8X#R ziGKjLEq3Fq6<0fdTH;%SOZ237CNFXPv8oF39I^P~keeiXsJIx;qQ-_D{W)&m-%;F8f9Ve83gTA~W?ac(Tah{&IDXvLCY0VfOPPXyM? z(`PMvk?YI8wO(LbEt=&KM|&H^2&oJFNjp53=(pO4aJ}@=5M>~Dfkh%JW;!H*40HpB z#@gwI|;dK+?N(x2bv>V53SR(;1S7G@_9 z)+(c>w!9x-^n=MfWxmV7odpiKU1#E;`KVS6_=2Yx>(lLei>1&OC1H+KGAEEGpF`v4 zDjd&sWlzt+bM0-)cK0DB>6bImy~M-oEVQFyph`dER#K6J-f-}RyIT9cN3B@Whn;jf zJP#4_jJ(TS)jNiO-=c_B>UfX2wTr(Xj}q%qL7NhUIx}&ql|M}C3t0f%95qQ6k$h3O zJP3&P^#Dm#n`U~>S_pW#^>g!_bYncs3LbZh)!&8yG)4a8R!oZsw&|!kAQ@G%KCnuRzxZuDcXQOhcf2<=^R6494lHg4!c{L%< zzN&6I;fME?=7+^c8kYdZvtc-AG$e*Z==X0}%M6Ta%W%cAa9@FT-4PlsN-MV_(H~mS zj>+t;XlH5S<(ZJZDK`fVBG+RJ-=i@dhsa>SOE>D&Gw(cHGtR$E*xvSL4HcM8+i(a- zhqWbh`LGcVbCU^beH}rBL(pShF@7@>GDw$_XZm#ui(cx;M?+9a%_EVaO&SnP(Q~L%HIALc6mdV6o%#^5?|)2njkct4wv_-q zfSeX1LNNNS!IdWSR`oD)JQz?+`bp@Ybgx;n&a{x%_yM&`CaTu4@TDK3yXt{d?#&@a zoU8E`(lQX(96BzLZ&~oH9P8_eBHrbyqpF4uuc4wG+TNwbEhQHa()-D)u?XGdupU8R z)_U5;B)kZLZ`h12KOF`8P}ih@*#qY{9YR)@^b0*c--kR4>#(mrBc6b~y;N81(EYOa z{#Ypd{W$$hEWW#lAMiHe3&p9lsy#+jtI+M{<{yY zf&9S2$hN8J1r*$83zMyc3doElCzt$eUGe!<&i=p@?TyEBs)~*3$ej5Dj5L&lx2k$k zR^ODpN>dh~loPRUJh)RD3W8~He8Ifp>&yN=4W`Ytkajp2?m3a5X9}I&z8WIG!cM_w z2&DxR4&b!>#Ch&R^P4a~Iv#EN-;Q4x`X5C9-nn*0L6$N%8FP6A&;P^rlLL_AII3R%Odp>tHYFW(j(Sgz_5eE|9#r+scQ*y ze)_+p(=$PR(?WJ~DC2k3kNOn^#k%XCP1C@%E?37 z87AM;q>|9X=b2N(yK}%uA$_I5PqAj~5L9U$Gg6FCJT53$ ziqX=B)*(B=O3>%*BD${19b?H6bp5NVK|LN)*ST8zvft&tsOUIq?v65N61n-9kVEx( z0^xcy<-KGs(m^$I>f3K-NFa~CR{3f~PaEA~HO6?*r*PdoL+TJTf{UA1qRjq_=pT