From 1d0613942cce5f36b64781777cadb568eada0246 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Sun, 6 May 2018 21:07:30 +0300 Subject: [PATCH 1/6] 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 2/6] =?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 3/6] 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 4/6] 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 5/6] 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 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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 6/6] 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 zcmV((K;Xabp$CTC2e7pX3t%AO@u8Xk0Mud%lfVfje@pmgNlC5*9E^k%c z2aAvHrXeP?__Vt7P#%t~VpwsKVa6#YDE;QQRR&Te{z52q1pIu2W zc^4Xke_^w`+uZMU+b>*rqdmCrx7+{yzy0{e)^4wL{h-|)Hb@iQ!Pbq#)(aP|4TpzY zo125ywe~@CuyN37^?QTf-f*MUJJ{^)?R8r1%^SV`?xvyX8h$(M_gd}2fbgGYS|LXO_e@mqG!{)HF)7kF~-ym&kPS#BCg$vjF z-7VI{rOANcl`T3T_L05OSLv6&5;F*3kDLAWJ{d!=JGj<4%%?GLYvks&tdZC1Ch^+A ze)imrL)}^o2XVi7gM8!-stkXZzI3opM_%8et|?#ynwY$yG6b>DY$ONGPB-s(F3@nm zf7R{T8ZhJr4zDhToEQ7O>xX%3oyA&vsr%}rE#T}K+G0rNr#4t@Ft1!|9uf{bXl=c8 zwcG1AclODM2+A4+>J1?43)@8E?DTfufX_p6+1fg6_M0#5zHq@wG(9yu!t!u+*nWKo zS6%jxT-_qlZTIpE7s$9%Jq)zTrI-6~98ve}#P=r`%;Ywo{rp+)$=-KSUkto>hQHw};882l<4h}SmR)0>k~^-JeC zXR|l9hTEgxk3Jp!f&Bl=(O0A2j=sRpk4K+3MxT#9B0oPI{f>P5n0&%R|F1Fnv_Zao zIQrA*Gx+)ix%nme@6*x0lfR#lU;o}1{h2iM34b>B;pqR6Tc1LYL)tH$OcC3580l%? zM{8`KDz^VTIvL#^os4gejz$m1?~NXho{UZ!{7jl!Q1eN~+s3?raxBgB;O%E#IDfL4 zE-nT>C9)3W9uaQD2u9)dc>ESh%14|YBm!~#b^`_A+h{XCL~%ic=*0#;2%3<7-UH#< zfd4(hr_tJhYf6H}h+{Lb)&y{71n?O_+FM}KfPq@TC8&p7IiMkn7rrNdL35xX+dv%( zmu}*dk4E1Uo9KO{mYX%Cqhc;OdViE^8ld4BA_x_%qTzBxAPIiMF+0ap%!iSA zz+65N%}gvW)?mofCc=iHIuY^lQ=f=yXh!N9Di~Sui8!%l_@VdIPs9k~*nbI?;(x0> z5iN8bE%a6N@oG=R3IZq5Z2jryktFr(NPor@;*BaJ#x#mX4867l3u$`esD?iueKq=z z(QijzDQHLCOSLF=B@adqW6MrsSpAuTo&~kzsoN_v26sh!=KIB>vwUL}fmW&cNdp{c z=~y7(Pt2mP(ICCwU}n|>W`7B(#Qq&$bL`jvx17VY6NSEGIk~g`tT5sVxGI17uR8R` zHqpAv2#kG6JmH(fpLu{DF*-$e(TSZnGWQ52AHkO+LO>6R2lTI_qpG1T83Za8x@nnO z5;${*o6edt_uG4Zyojq1Qk9J z1vu5JCoI#q*)+4p7G~`!7KCG3K@!isrc@0w%_g&XIzYx~&eKs+*U3igTF`;?PtL}I z^!Rvu2Oac>=&g(FDoLz5=+<s2}u!hN{paY7{8twjb{x!m~;3efL~ zR=rcJl3i1`OpsH22Yf8_gp<#Lv>z>UdaMgVjhC65PO9H_kTSIxz;gC5W9|(JAbqj zlVB{OVs0KmZw8j73+8UCx8H+DaE==Olg!5|A@M*_x+-^6FE{2H`u6zN#^~|6j8j6} zJcGY@MwnC}!XxGan@h(lG0N?q9txCXB#Uw4Jemt6O>bcOV;yeZD!qUa~t&PU$ z_n5!=6M`5(zMA6o64u-*?(HB_aRPVvs9BhX{tr3Ker|| zQWc(?dooQKyZ7XGh zO0!!vG^J6JdX7qtPbr#Kdv>m&hoL?HTI^~Qp%H1i8OC$3Yp(X}EXOe{E0}xvdBtaE z5Y=Wz(t1Vd>{fEUVhUyYz8RzTjECh)W(|5T6YjNs_feYyp z`G9p(<1ZEETj}VUdjuh5c$mYNjnzdlIUkBE0`fb6I2toOY+h|=)_*?l!S0ZKu(#Mp z+UpKs$*nnPbvjqBwGT)O2c2%O|93%m(1CGgj+4<66Mr@nHnp96#gAR#mIX^v6tZgt zx2N5`^s`s8iPPD20GjyLCCf8x(=i>k(74-cz1-{%|8eJ++^-j#`}^(w8`(QoV2^8~ zx7UaWj0k59gjavo?fmogHtmjYZIc5s`I2;ZYXD9<=^V5Nji0t}G%oiJn%xOZOYgJ> z#mh3tEPoyZbTE@Kkne0RC9Dt!K@>PraN0;cEplC4o6O}Pfush80xwvIbCrZSk8}JX za!v(9AHFhtgFu_jqPeHjiFL0ZFjVfpwlC2Mx%bip!I_qvyimKoKf!_mL`_G6D9?AW zVveC72!(#jvb|LjD0D4ybRFZO(?n&gyPlVpL4Vc?ZOcrn!KgDRmc*!OaJ>PMXEs8oB5I=Pw1$p^XA*xTQYt~H?n_U#JF z)t&a$4iZPHuB_t;rCvMT!LWaY&_P9X^U6O)ji2`#7xYWSl>Yg(#?OD%`1y5=F;3nr z8GqW+W8m(qPbH= z1M@UD7qQLL(KPycIe0O-oTLo_fk0@}NPld;0i8Ag%jk7++;5x9CZ~$wx9OVqM1xFN ztx})(zGL`Gfu(AFVj7Ma(^a`y^@*^esq1v9;JMN`)1)EVP-h?wC!@yuC06lpyVmO~ zQt^tTKt(1m3RFSG{1Nv}Ljok^&%zd@Bdnp3rPN;H6Kc6VWcM4R?{Iq(>^l}W1b;3; zk~~j}$zCfai72gARZON9Cbnm*Bt5Ma)43=nj7FWYnQp8#&>|Y>3&_w%-Gc=^uyV%} zx;GXowuoh(#8Nv;5Dm|hrg7GqMj}3YRW*&STWJ_2Dk%_aO>-`q29a>anr23ieXVKK zG!3q=euHk#Bk~^<2fJ0D2fWra^?#biU27VN_}o?1G-jy9K@h7XO3tro3{_2ITWd`t zYZ_dMIcrU`v5u=Pq-#DW4h&Hw*(xgCtH*6d9^WY_p7EWv%9&r~cx#m-(csFe9Nlp= zGfk7V%2`#FgL|dUT;;3-X|u174X#bnhFXMJ`_LqAc4Db`z^t8payP|)(tiM_>nX8h z1{9n-8a-r5sZd7u5%^OZYsEFc;_}yuOCm}!J@@p6KeOV}Y|o4grR~}CD=t%2ad}p8 zGxl??xNy(dIVi5Rx3mZZ%Z26WKUr0#C!@z@?vnz<7agNQ`pK2%&gFKi*WW#Z;qd*g zRqp&M*VEQ2S0bmCRk=nG27kI^s%+(3tK4%@xwsqR98~VwTU@@%{c!X()wC?*j~$nT zrO4sPoYhgf`|UFr3g72i;Vz(X^|iv4$Z2I2u9>E$Y2xm;wZdIVg^L@s&q3j?vriUU z5#-(3T%$r&rpKcbEVB88__ZIviFE8h7FyAouTDI^vsOb3s3BvmhJPfgTv;{bYPuP_ zwn~+xwHi7XHH1}g&Or^$xI1L6h7{G%S_Pej3NqI!NTSG#VT*I11F!1zFiyBi|dp1{{MnLS=l<8n(ljg9IBl0GrvAr z$GR8LC+ATBz*_I3JcTVCC2FRjZ!|EL^9|J4qy^E&@374t|_QV{PkiRZ=QLuzow(PqZ8%7dgUh~=#T1iXjtg2loNJVR%8+b+r zlKJ!)NNe+GZ5}PIBA+AkXkD75U>>b(;b=FFJJx_+vx;Re35L(&IqK50(UZ|}Np_Mg+&Z9bxwJuC> zMuw10452@-l)W=(9vnWeYQJ@OxNJfFJSqNlNg`SC8!NjLLrb*83&QwJOnu6iOu==!u!nxH(;p0f(&>`1qK=1AF}@WU z+xE>Qba|iv1ChVc06#hT?}_}Y2%1CuJJ=mYL}#_T6glK)5k_{B#D-?6ETTE79tN1) zBEyJ559fpPfB_D1WQWbG9Kn_2$&Ld*a09>yH-84putUv_A@4aKL+YAgnh%SD(>Dz_ z$??ezEP!&#n4UX99($NWo@mH1JFa{EfT4E(wf*cKv)stNmnJn6GEC<$AT5B=2gzDA z#zTa1r+bzD#wLE*%HD4g^tAi*s%&Yri1~M=bI=|%e%ij#xZFEvP6Qwm7;FkVz22(_ z&42!@uMC_0A$hR_)DJy(n_z43Cn#C0D~Td4C-iKD%096%E)#-k_uIQK6YPckcJozy zXShB3cyvtk`rV2>7}+oq1OXicV3-|x`v-F9`XWQ}#?v57j{hwy-9rne7h1~cXAhGdVNLP;-Jw3rPl1JkY8sm4c z(ib6*AIg&q93Ov1!3jk%fj593V7QOrIJ}2sDjA1BRTwgFc{UdTB!o9k=yZV__@ZV| zQU;1X-zwwO@tXx^C4Be@j^4{^FF+BRd&C9FMv0r0zlWgg_`T70WXz;#((?zC(LzB_ z7zvd4JRocJAz7l`7tkCdGdDEyFIbmQ1u#bL< z3amz9Z*v{#M!@upB zh9j~tdl)-p7Kdbb4TM@UfSOz5cg7z9lZG8A ze>G47ZLs7#(6TlPhg~B*WdsTVmLrgtA4$F87_pJ@2dLa|=no(klTGj;u1Fo_LJwr- z-5HP9HhsrUw6jInMXVq;ewP3qAbJAER*s&GYaau^ITVd=t1z0WrD<$n*$iG+dXevk zF}RQU)Puw^Tr}!=2PCm|bTf+%i14_~e|BSK-#P;{Lz z3_pwXn&Q9J`dU>1))I+S$Eu}BU1Z3^ZKe*th7nw1LJ7{lx(AnuI0A`sUl5bhe*lYa zA`(Ug0b7>ko5({m60ouoln~0_VJ^L_JpN3LcB1^jGy%z3)D2ZwDReU2-cpcJy6YN- zrO9vz&B#u|2^&&4#75whu41K@6}Xd#3c`W&{Il78G0H17qDDcp+?2`>bEaASR9UAr zRJ~Oo;W`$mH9Y4tEE~iChNhk%e-_1?4K(2HqDB8LsBO;Bqitrc#zs9SQmil-b0G=P z?%*3egdhR@0DXQp?{R{G%pe#23os18tIF+JIGCItlLnz)KrQ#{G8PP&E=E2!r1=n&EJ>9cl04}()cZi%Lvv7dQh^Ae*|<3QyF1gXi?4e z*PDMRN_{py7I1>jFi?~Sm1uZnLYN4}Cz+4NhleNPPaZsZL!>WB08AIZD)Q8bEL}IS zd@4_#hUwad1ujM2p-6-x{FWp(P4HvSEfhA22Daa0^T>Ng_zKbl1ci8^t9@v4O>h*xQ0(XkzyP_VeLC5@BmgB!1B5I%h%y&xN(leZOUH;te=3s`@CD=+H>Q!1ZwLe06-- zPbVU4VrWh@`3&<{@?CvDb~Q}75aMf&Wk#;3M@sGTn&@`D9${0>ox9mJtJzo5qzdzHfk@E`qVLpATO??3fgYkke@uSCfFPF6`X)acal*;46V>Z!+e?)3W>Nx=!}>Cy7Rp}2HIrfp9v4Fja*7+^jDwhx?(_wU0;)8qu0X3C87g0J z1D6&|UWw+5VQ$2Kg^3V)y5mIP^Yd%Hv1JFECz-01>2Bg3Io+)qXk@0JWHx(=`%vxD z&%ote5Cz+o14J~2Lj(>AF)ALbcFA#wro1+1f5x}e4*!BEgXZe9{rWU}n#0X}qu`#M z!5k*&{)3<*nAJm+5Y0%-*1k)K{5=+8!BjWMh9OFk;OS&^fBdHMY-d{r*rw@m(9zpS zI`=2ZQJ}~2SsaO4_FFCxXqKn3G^XUK%(a^E!;3)S_i)u6d4{dfkFre>l@f#k7wuD; ze{A%A6-WV~R;ual3^ASwJpZQbvU1iv{F#UV3_t36@L2)4fW*9uknk+IeHQGZ%R7Krv-C{9|RN(X|-276%-@9?G-Q0!EkqC3K z75piTVrRc|n0EH}p$GWh=x?U1Oxh?GwNOWuG|2O*#n}>!9DdOu(~=--rG7uyqZ-!s(0b`X+Y+0h7Z5 zehr9#Xzbkhhu&_ML<8@?zSlp1Pcp#9>xjBH*l;L#>UerHfBmpO7{1u<9W>wzfi)Qs zHs5@W%!59fJpz}zJs1~uf3n{dE^N{(IDQy0`%3JpNHeTOSqM_H_hr3g%BUFy%l+_I3A!l*@OfwOI=I9=1RMohjX^sh!CB7Vx5 z!ZB?-@?6-1!3Rl0e=CVKQ&lD@F@+?PSnx!7YnzSTVbT|MC8g6FFg+`Z)Z8zhgr!)8+U(PKCcixpVFBf2^dxGjUP@O1y&tK%31& z@u7(Y4E$M4`ZBVe*Q7rad)*E#Uylt*G8u+Xq?HYu)GH+uRV-8v_Cpo>f50@N*h{3mKijl*KXF9+fK9!GTEsi&=eE@@@JYa_NasTzuQuP1OOl(7 z(eqsA-x3!P7Ut#UdR(3PdVFW}5Lfm`_i5T)4SA?;sN?haCO&GV8+wBK3g9-MG*AbW z<@%!qhFH9-xhf6K*VRlbCKmZ`%8JRNBRYL3PAxYyeI{<@n|^?2EAu|3m$+^!MKxy98JuoCm(?-H(tOjmA%w|$i$)OH zp6>WCu+#Jw-3o8fWlyfX#b?`F)R|Yeb{9+C8b>qi1k=@ccQLSiN0Tz%B%vc1?j@3l z8FVvAeMAxX86yLO7Yq*(q(*oTM7 zr?lQrp%9R)@rr9vnfF*mD`^m!Mj$T*+MaKwMqc`l^HW4xS^LETJ-yOy_FI)T#81&L z&NqN5xw1}Rr?DZ`H#C#fvW!$LgH?@SF{*?Jf97~%g+twD7!p|+gM<@|7tbU{O>pYQ zi&tU1(1q)@@$$?YF9_+i@lr0DoWPGgKZJN1FPgkCFl?^mPEi0c=~^A@o=09ykyi64 zml+HbR`;P^;aBK&D>NLrkM+UArHO;jN;>TD+Im7fsxIls${PO ze;Jr=wr}VT3o+7t^OIx>*iionB7R_@p&7*Xs)-rI5Fz|JD=7-i&>g)jb3V`Mxea+I z;tm_w_k9wr$erCA>kp@hV1Y~|tjeV7N#3QNaedilHK z+x1pMaW@CG8l(+wRXezq8?V}^z_u^*e^ANhT;H~@VS(h*flsjjpxI>5QXjkGzEjx$ z97x;oN;d?RN*IY>>LpAiYpC0%<+IQ{*EEt)s(fU-X5?CV0WzG$)VynMba@rB=H9T~ zhx~3Zpr+R(D=+rV*L21cKj{2;=AXHAn-xdCE^P_YQ!7prZZ|B>PS-*`-$*;nf4MEG zO2?J(F4YgGvBwJ&0E>IPXlP3&em3Sg1~Fv`sA`XwmqeJ1rd?0<}W0em)Y* zTvkat6fmhC#ME9HLQx{2)M{y>f9h1sWQ7#V_AT2+;2DOro3vC=CaLMCr8P~&JBS3` z)B?A3_nnq%gcNvkF6`gNUF-RzA!tJ@U{-`|=xa*bw1ZglqDZnl^~gy~TiQG;O_vTn zP7J@?Q!asl8=8I?RukgPp^yxZ>;*~4RuSKqz`eM&Fsl;;Re*^B1V#{;e?nN9sH~pi zAsknc^mE}&+{pcXWRy});E~Ro0aFcttHbs{PGl_aJfRCx3SCd_RJ0@Nf!I(g!WM^) zXUQq|i}TW&j#TOBut&_6-oY>SJ3BK{QyEE=W7!G4)Jl9Q@@`vt9EDPC>X-=EIM-zy zmc={ICzcruX2&ufT{#Dif0xv~5|JdjnZ~l7aoi;EG*>iuo*6v@?)?)W4dS`aO&W_6 zhAh>WBwBuP{wk`R)a*ppO%sa=i7SD`ly=0#Q8t2Sg{qc?+WJHBXyXh(WoW6NfRg1v znB6fVPm1JOX<`{MSFEH2hk`6CL9F<=Y?{lFJh?=D1|Zwds88;QIRt#%m0ye}1g{_h^b*lhQl?r@C=00_RDU4j9 zaNlYUd}_VF5~)&UHr0y(QC4o2ia*oPgVe`jKm2--sRvq&HCWZgR3iRL>}(z(%CmTe zg&FgilzN)YmgajYf1G+h`#_5Z|E!~!fw`(=B&MTdy&W#3cZBO${GmF^13lj|&(c8t zpu((9>^r7r%cbUZCo}?G49=IjHjFV!n6*BP_#D_O^GIJs=238sn9o_wK4-$j%K>a& zUy|-)!NVybw~m&Xf&x?zu)ILcjHZx`yiCIOs6mDDyLddxf63_nQm3jE;5O~Z_goAe z@TxR09NTrpoPbj9JYN?P7r-{FQvH;8zH~Z^QPb#mBRD#Y7BV}=T4+!Q?S6Hcz7jrG zn9b=%IA$@^7HCvq5>s*~i+#0v`#pGwc9UAu}~Ep~6Wz zvr&uy07&s-f60lZ@E=^8@KbBQ-RuL)Vgqa`zX415`{Ztl{|bT)T)_W{6%o1JfyDcx zYmp;*9V@fA8oA!>_2v3Ts%|Sce;5&p>LcWbQZS59ZPL%D0YLkr z*@VmVv(7`qD;YWGq54V{KO8%Yo-sY2y{PnS6{aGKQN*69k%QjbSmj{4*;spZ4VV?6 zyKPASrl%}mVt00y8Z9aKzKYVf{MgqcIVIL`TqjO!v94mN(yu<4tK={_4!x(Z^fNfY zyh{~)f05W0#YVNVuOs?8xGr&UXl^WF986E00jtfL0JFrgDk$Cgjiu9sY_;ih9x$r4 zuFja|>Z@ForU9HSuqv&%m1NGd7h#HaVtKqp#losLrxv8XnqzKNtfR98>G`9235Jc6 z!fw7ms#E7^p=qX;7`U$vT%3aq1G8D1D^H`je=-$cr>Z=fgDFvf=ic5pALC-BEQ#mQ zY*4ch^fe^N^P zW;Ud1!o|{w1;X`M(4-DfqyNlTRSRTQ++j0Q+P_Lx(B*ckxExSKi$`0pT_-5Vn&o+p z>-cg_#PZiD;P=J7& zc$#UNa{8FzYGx9MRZ$t$tt0-!R?Mn~21XysslFIw&tpJ!dnOi7NewjD!MX`N$*_xMm?_g+S>AWq zPHQ&|wZN9EcLauQ>5)_zu9EA;J2IV$-bO7%WLB=gh@|3b^$90_hTB%=&DGL9_lhbS zRaA^)n`vYeP7NpjB1jtU@VTVaS{^c(gH!=YM)0F_85j$+?*q)3!w>xmH?Vx5vwUNkLY zT$id;@s13gZ1hu2lj7PL6yCiFj&;UdU?pSGVcZ>hw@^M&lA>&2bO55-%f>ZNz~8YG zv$hy78894B#>hE~e?Y;+zr(>pRYa+WGCNR5m@-4~#a`HKy-Mk(Xf@FTS0=#b*<^eN z&rIV^X1qu(3s$}Qo^+~4wI5Of)QhtK6^oQiPR%Ibl9plS4k{nr+h~mb1E~WGGnbG9 z-L=b_fN&Lh6X;?9YtSjtE&gS@;2!bGS|=C+1E^5D>%Gx;f26AucE%jPjtZOeFG0g& zIQ$N}0=R)CKyIk53fd&uo=WTNx9?iV_cnx}GMs zTtVL>%Et+F^zkHCUz8cbIvfYunIx{te6`4SeR=>mH(w)gQ#%PEptHpJ z@?)Je+&qHgHKF;QE1~a0~4Q11yn|C z>t28s49|s0n0mfcgM3j?0mD(W{`KZ3Srr#%+R&)h3D(}asWfiGv`tSYY1;`r$2LUk zUK;ltCR)j4{s6ECb&AzDL@LepkI4sN6>thS5fFlMyf3{d;FK~51pUZUsLLNg=k(F{ za2p#oe_G}v(8LdF6@xV(xeTEFbtQ3ApJcE38r|D9K5s_7WwTM0ym-QGwF+iz(D^cdVa@9OPQJybrOH3Bi)?vHvYVa zR>%Z%c-YWIc0f@ck&#;iE>KeXx|2ALEhR~qvFArgAnuA?br5HV!3%J~JWcec;Sh+6 zf7DLOp-BXB2`Z@K9?@+%xk<9o82w+w&#l7qcsLb0@to;p(a=WX7KqpF#zzO7)MB>Q%zAf(lITZxblYQXy9yoB*z|}+foF8>uip$A0jL5|ScQGdxE!+AJ$h ze9uM$bvc$qO;%rpIrk^gOrSRH14u4l6VITJd=5q)aW28Bpoh*?s9SRVu8e}%{& zNF*-UCilu!xumkyQo)9hNkqlZ_YA{mEhsf69g0yEh!rNa)c~^u04KTYpyLX16diQY zGbFkaMZ!eB=5BqBjD?qp1E(Zm^@KQKexX{Fsi(da`fzpEDI7s1UE~N-yi;Y`ep(e1 zmhvU(js&EziNBoNwA0Fxva!%Ue^o3t3l4uuV`)XlGCW^Tq-36%Aixb|NpcgD5$ojU z=Y^m>qcs2~TSI|T=7r$HF%TY8)(HDzsxLSi%rk)n1K?rAe6fk3nviWn2HgE9sAf5H{uU%yG0fmuuke=Wj{!;Z5s z8XRcf5-$9hTI3x-}9Q6vN;IruJ;kik7d&lEqxi?EWCp#ILd6! ziR?whV!PiHzQ&z<@WN!@5n}UUb~**GAC+(!q`pq0;XE$gAPj6N17@kXREg7~vsaAM zvie&Y3ajI^#VxZ62Snq~3&FR@u$<)pE1T74f0J}YG5D8-^&WwP zNEa1K;;dDc5p*VQXD&R7*DLZcFhAg2)elPfM5X1LXVJw znA+#)*ylcF%_yf%b8o+Sb%rrQ@(CAL14;lwr{aI2hj8(SiW#b>SOs`OP3+w6d|d}) z7959csU*IeQD``pe|#*lsHnBz80- z@?2k97u8)e^ej!xf}R)L3$2S%9EqSWqsV10c$#Sx8L24;Wt_mXO*5AOoQ{V@B45g%-|hW&kkG5cw+JA@h<%|WZvdEr9TJlN@Xnhj_IzGVEr92T>yZ;o@idtFrPSOGGh3QFT4e3NPxFS ze~$))(9=6Cyv^Jr`nAp704h&AJ~Z$k5yS!nqwiGT|%JBGy#V%+48pBI8Gc> z@&+v3aMDuri+4($uNiA)S#jc;fi7jjS(@dznlEL-rH&cpmxTIKC1VvI$FZ(R0WBKy zDXtk{-H;oyN;$g6E(>F z00@WegTwviP+kq4;^8jZZ3V)Aus{6K+$=sn2uQo2*5~BSCBxv#53Wi;C?{{-(mX%G zV<^_-U5VQkF`Nb~LEC3f*K;YIe{y0o{Ll&`c@604BDTc=`Y$SMX-EH`y|3?)+&J_5 zD)br%c30Y+DpnPXTwy2RtFsU+3!_nhz!03?S!y-eneItXk0nKxAgz3M4sxvI62O3C zoG%9iIUxVYlGZnR*%fe~fc=fGirq8Q%^{mbviR1lwI$8YOp{elJ@55Af4>I+WF~G% z2S%yU!{y&I#Z4-spPW5BIy`7r%7yN&fKHI_!6e3n=>|G95XX-lf9C1goxL}&ap(WKs-jqXd^!tKhXP~=Nvs0m5yOpv%{#|} zIW&;KnYrqsekENs^-<`>0$g=7Zygfsg}^dyy;9s-h{((zdD3n*bH*=BmW3s}#(`gc z@hd8RVe)$cse+EBBMg&RMy4OQNbjUSD=t+vovo6<_9bxjeW`9@e_gw4$Qtjy+U|a? zH$PNo(=9t8FZsmUmVPUlG_6f^o3vSR(_Gx3&94x7yWH|Ne{BgnsaA{VJ~1tlNRH|x z0D+175{}e#h=Vpyt1r&ALqfEWxS)f{_}T=+N?G66&oh>f8Dj&ilyIq4Rct+Ll-teHqnb$aF!=Z#AoTOR=g$qD0WgUn{EfT zX@bQ40x=*!-qlR{j$5_@M^emM^;r!a&0dM`ei!;^auQBQv&l4X8Pd)1ePtGfHNh71 zV>$s6Oxg}P3R0rTAcnL5BMap4<9 zmOppKVJp{V+@b!w{e$)1)^ z5-%``n=DvRf9$<}w%sY86jfW$36SSns!}nRQj{3FMZ^XUY%Qglu2h^(X5qms%#G$+ zC{|>NLoz3C^|a7>a*z=BsPjl5*rG7bVEXNp%NVUtpxSoX%2 z`zW_>%fE8oo4lK}*3E7#E(Ki2#7~>MoLr*>E?MAsf31Mu2xvUra~&Vpi4HO3Se{4i zPUh0PRom3aOX@euXXDeu$Kyt9vaITq2F$?WxRIQDk0|of(R&NSm>Ur_WEsnJ9F(Rv z*XpSg)K|b$u0y;FXkh>;(H)dXfl{4$p02kJ?zUxdh*Gz$rxmtVuXb_k?%8zOpa#t) zL0ye2f3c^#7}WJFZ$^7v$0=nWmzurDdnjd+DEpriPoZ2fNf28sGC-YdCA!!$-%k~j zv_d+$EpA<_IxVb*hhm?&l729L6uwuCJk?)Zk2kxjjL)NQ`m4xRv8n}B7{WxyK|EV* z)vLCl2lPN7o4ZV3DixOTwE8vFFAt})v(ZtWe;78RhJHCYeAI$2+6zZVN0VG+hen*m zo42(48n{;TcKJ5`u4U15<$YgQgt>1KylyD0y2MX;Wodb<5K-F~P=UNCCs{$hkpt58 zA;B)Tu4ft4ZD)-dth2Z*keIq}lLRwBLNP*)K*~uO$F^DPdO66orxw?Ujdvzzq{1q1 ze`ITtU47nqH#UA>gCM&mRbybKA1VQphF5HZbws zM131ZzHJ68K+t_M^2Lu$LWNS+)3(;g_piULc5&|55w=khCX2=`chBul+{wxN4RhOW zBOZuY+9dCR%F&SBvQDT)Y>-5%M#KsNf0*cTQ--+2(|VDLmd5NKCAq!GMr!gX8jNwi zUJU)pR6OY-sOyM%y)XNS89?*q&?CWCsl*IzqwXN5!7>XhgZf9T4- z#!;rPAx;j92n!HXjx)cwhfb{O^0furjn$nt=D&QooXq(pZwp#`XSz;>1i21&5(r$>dD4_Rsill$^^GhX`Z}%`;lpGLdbH`9hhX2O zz~%{x70qJ=t^-X+;Ql~q9;JC!f1H@x+8g0$dhm|YI|bdCRH-Vm{lsu)@?0 zTw)}rxDw9<0mK5WILZoV%gMh_wU3K`$z;8nI9#YGUAj}T$6lYGkda&>e^BE7w8Msy znaIEJTf{^oOFg@4_s(>sX-6pCL8%RN-$(=WT@(3y0DI)6 zQ_tCn{$|^E8sF`3B<=J0e{T|j@J_13L#PfNM^99y01ul1Fa$8zR4Z0NhexQoxn-ZA zkhj$19-#-P!P!wYe@WKvd+IHesMg!AQsf^hdJBCkLN4Pi^su9gS4!!|GSUo+pPn;1->=D5dxOMmT$o$#_SUG(e3s&BO_nAoP_LxFxKrBWMs ziBhSxbkw)1Pp=IvX+WX=B%En1`81XXNVaX;Us?NB!6>U=t2W17F-s253k`~2gje>#^j2taA|Hdv-bT_0bh ze|LvP7cVrf@nbxaPxwqR0fkPG1A*ryP(KlJ2{u*GpcJ}N=%p39q|sPPpVvy2Hof$V z@nO|eI0`&BAo2WyRiE58T;c@WQ@`4d?_+OeZ0*|lU3{~r)15yQ8gLF+q~hEB`gaxb z$I=}@;d-}WMU&RO}p<*3sy zs@=#@iV3k-nV|3%`P<(dUmx4MdBXw^O~cIEsKC)L>kEQ*_wf7i=2a zww<)GZQFJl+sQAs?KHM+CykTFc4OPO-~Ybcb=NwN=k2V0_RQ=(lS=Z<`_jWjH~jFl zu%CbQ3|+CcZ;*dj%C&OE`@;q)R=l*G(U`1jlhWo-d7p^-ZbM8j6naChf0d$GfH~j%fsnL$wa7Qw^Lh&Qpcygp5o-q6qP=9Dw z8#Ho|e1BWgiKbemyv0byp|dxSSTNr2QgW-dz0B zO`RgBiUQ0>fB4SUCZu3Hb@&4v@Sq_Ibcmjdm4!CPdc@-LloCv;&>;x5UdPM&+jBrO z^?|vX*6ct7#_L=L=S59C3wAS8bA{Omb(3Hf5@y3tu_8I?l#C`*l&jCIx|h=YlL;gM zEHRudIo(ch>1+V1uQ8?GO$I-us9lV&#mQ_gbe;>>cs*n`=nP*D;qRPr6(fa}QdLfS zay*Ms*|uFp5sb(ORs+rP1i{M zT42JrOt8`Fp7fOj(&ONoX_>Aa*BFV0=f&w0$G-9~NO764H|aDG^)zFa6*a&%5C7rb z_ayZv+WKzeuKFW{+$I7*tlOI>b%C-4yR2O$fvp2MTb|SPZ?Wux+mXV!ke;|wg0r*Q zJ)}>#H;<+Vb={wXQS=wzlLdu~A2)}hzz?54SNg?&3x4x@RU&SdFxrFjxFGDbg;rKV z-p5$*93XBoS2Xo}Sll1MI&c@1*pmtDenX&#pj*h5K?vqum((=|XmjeMrAm;^y?39L zI1z}t`MvPD=N<0J{hV5LY!l*qgH2S4T~X$sOUu;PYg*P&qlk}#MAzH@IG;70+c;MR z5TJu_+62{Pn!ug*F<8a2!6S19u-Wuw)HLfhqcfH-X)fZf-;V4rY1SK4i`pm%Wm9)k z6to6Q*5`<|PgN!Y@)U2XS;yjR(lq_Q#ie6L$loL*36*LLaqKXH!wui9-l!QF6yew9 zLr>e1aZ zUzyh(wt=JxNT)4H_|t;%BuMyJrjB?K|3mZozMI&!N1SaMr18HVor*DtW?*Rl2tb3H zY7J5Ar7swDEY)huo3bK}^Vlbd2x5px#{WW5ZV*P5XyL#`G;dbhM;=^tNY>=F(J4nD}e; zzqtJS{08S>emcQ@CsyF=(5tZt4zOy^--rG#&ar34d?W-h1<0SA#ee%dtIqA;L|+Au zsFDDOn?T}+4l=k^ad}!T*V&XJqhW~x%TRC##K0AbDS~NsX`4meXPjS)(9{I}$6$r9 zG~Lb^HFw2qRExk#(Ar`H;i9A-6VSy9y84yRD|~*eWs4ouIZyx3@yl=<1#Ac z3d)MInfSn&N8|Mf-5<0W9_;28~8bol-f?)c_uM}`7y^%dTDH3y@DAGmF?9Da= zc$$un$P7Yv^#8*+H=2W}^qfs2{^B4gidz8t1hmK36qP%GI=#_&(&Sij8VHY6oX9md zp1|0*Ai^$|3JSR~nY8|M@^M82U||xALx80py~fCMk&F_^mW_?1Ny+DwLy~`zKw9m& z#nZrx@UcVe^cH^;%nEI6Jkj*_c5%V&DS*+d!^Jer$5h9v%Bl`l%~itA{#R8i(f_K- z$N_OLn)8m?+GMjo^pe5_@>hrL zKcklB<}Xt*K1R#^j_{RoZV?H{{Y$nbNN}MJS)b*+~^fV=H^PKYx% zWL`MXDd&wyo>C!JVxFqL*_4R);FNWXUc$Ev*vEQH0t1D~=Vk-a%Bo=kv=U2)XrG1h zrXMvOFy#j&Y8wk((t}>e{l;uKUPYpB?>66`?zY8e3XYa*442zF#%WhN6I1%IOpQ|C zBdMd1iXS82FrgI-e6evUZ_370@-)s^c?r0)F_w$$Ke8&vonxL7@l(A~ttr8VfQBNw z76TtPF^}+j^4*67$ybg|K?dr zMp?shvM)Z(wU4;9_+#?teVOl1=)vyp=~{HUi=}0_{s4f|sV_=#M4+XohazHz4Uv)m z%jXkj9UqP76YX<&`Fxpwm(KjlX976$slTzX5!s#*$oaY`n95QK86*c#K2m^S0?yJU ziWrkW479X8?UiC*zs26oJ_Em}?&xnj`#)m$pM|xBz27|#!$I^d4PbQ(v-PwQ?MbJ2 z$k;3@0N;Op!Mx3so+la9&G@}A8=&!!$$R(odr;X_Z{POj8i0l}+`}KW4rk;x8gzL% zbw$*^1nK|nG>-ZUw;yamWO3y+9`_^`t>8ADH~IUOC#IJ85;(F}$j-xGnnR@=I?Dgs8Gv-!@sR`-3A zn3o_H<@aQY6+pLlFt0DQlT)~-^2$WqU|@vL0_y!O>f`+`FeEJ=Qg?i{xBbz}t$peR zI68Amx5M(kB0V3PUW(K+gdMvjupm%I1&uy0(!0(`+A9?|I_o7|55d5)`?+pW7*;y* zrGNZdczuEMwJ;WpBL*K0_q4aCF|i&)mquztpPE%>mBO6ULr!FHXDZWe7i7_psI4I2 zCS7Nz)gqa%@ml}35_JR@h3`Fuc(hm#lz2rt4!Lit6nW;7su+HSMG(%{%2xFpZVhm? z-oe=iNIi}&OCzc9Hmnd$aR&AwRQWrtj`4t+{z%)FcE?kWHT+n{@&tv_lFep``*qzG z1gF8mb-DAW7y-w9tu(AKnmUTbGO&AUSRplGaq%ds5B#ubkzI6}>x{3eZYwU;XrW0%TthoPU|-rcj<7T5HJ3flr4#}1l{pmh^f@{V>!!J8n$iu-1|zG|7wRC zU+yJwABx_db;V$tpVwFbVNak^!tF5q;8tEmX8gdtL>FuK${y={P-znD^1>5;zQN;B zhXK(ruijuk|M2NfVfD#)<_Ycbu=o9Ikum#>rsVGVDhht#<^2wLxvT+vQd(!h5&k%F zyyh{*^cbreIrf@DtUS9hqdB-23RwIU>7g84A~-r7uLhHyRxL*K*H;a3_g^xAIXUcu zMqc;#*KhG`^MxSo-gxl>Z!bt&2D%Bm@u8k+yxN89+WZh&`=iaz4j`n|Q&nhNll=65 zbMVd7q0M&vW-GtY(%=BHR*zDCN~lcJUDdn>zGpR%Ga>2CB+_@MfS*`(D!e({_;K>y z8hppk3KlIr(A<-ie`Uhv4nZeJ!3S}31?$w{s$LPOk1)Ag1Fbjl=XONBoVI;)r0s?Hpq*B7_MYK`^+Nz|W7xl3@hN>;Z)&!e zBJiHYJbr%M^0~qv(ibCIT~ueucj8a6Z+jK@*oPP$*nZ^r1Vn^zix~QwC|ZWgTImpO zyr!aV>n`e83q(MeA0AuN%l1wi9!kIZ`7jgk@e}?`x)Exdp2MNkS!O629rO&98Q&x# zibaZ@CJec;nS}tR1CRY>EpZV=2hE3FUnxX8|9usE4`Ix-75@llyae?yrb~$64bM2) z$=g5+QhFH0AEE`Vt?w&yDuGhd@)_)7`;&6jybZDqCxP;)XFnqa4btg(*BDfSrPuW3vqB=O|MkeWiH2H{XV)UKLW zr?pp1TF43@n5xL`3r$4gc#UaCiK;eMr5Fk7BWzz9^<)%^xR9d?Gu#nf2^7N?^|lTt+&Q_B}C-;rdjPJ zI2R*^JDuvzm7O+MS3yLZ?LrHROT6M+0JDNvUaGwF9-4FvIdfQnrwL;Kc!u4?0TnUV zcjR#3E|p~SsJ+%FPFAPTC(f19HVi-K7x+`pnlmpp#+n0P18?2ZhN67fUjn6;{X>w5 z^+tC@h2eLmJ>?`#%N?v<;j(^Ykn?n5k!&96iht}9M62WHU9P^GW#SlVMQlZ>tLn-P z{d!PEfZ_hCTWPG-m-eXbYrFD%(C;{%9knswkGS-=yp_JEuuXwAm$5%C%y3BNFNKTR zW!is&`bq*e_w^-K-)9d?5jZk?eRbBex+Xv~a&j;W+OS7YlU}Isx$4kdeg;6^DVRK4 z#~Obo@2fh7PmnfAE(`ny?;~+p`FQ?V6u9-?A1Mus8k1{(kg3Ql;HnnS4$>QT$-G#>{W5PwD}LZPDDno)!3RGDn6(v!EEZb(v6GEIqJ?5 zMH7WwxhhX0?7aH%(u+lS9_6X`qJP~waP#0D1`e>2R`h1$tLJhX1cH0-9v@pKuH(|` zXxnc^zNvznVrq5RD;IH#;w48-x4@YIaL8aM(gAc3gmnTeN*$j)(6(xttH(>7 z^*3+0;H{$38M{2G7oD`zs;_i^4VXSC(6{U?jND{@F{)Bs{ZrVb_94oRr6E){8_Q1R zm82=mGa1F2i5OV%YbyYB!jQ)6BYOrJRQ>}sm@jqzZdXuUIH82ys>p5~Z(IRjMAX}t ztb*(H&13TE;e<8lCg6p5J!;Ng%rc(QHdKL$b+>LECz+}Jpk}&Q^8YI5zJLEI=ZPBl ztz~MtI_vhNx`sW$S8zv(<-4ydO=^r${3ocPdy!qDISK+cWfOgkSbaJE6Au;!Jwl# zthux~&wm+m!|xpDy+>ly35>46+?dP}6`Pk$3uc7ZZmSEMD?D2!r0ktEE>yzhg=o^M zVI_N8k8Q0ikGs33f9?-Dr_Vq7Pd<-H);0W=rO43RJgrx>I*}NOfz-@WVV&X=Ein;W zV(aGRuq2@ngAZv((EVVZ`0emo1`Ddi`fmYeNrDKI?c7a_0t{(sXHPzn>!0}^Vo35q zjfHm4V&im{i*(1yVm8CyEm0%{Coh$t+E>WCM>MNs>CK*oUZhvMZ90#L@+Lc&4ux>| z&7RfaiIAHhMcw^R0BY-573*KP?T1l!c)RCplu!s!w>2xS@b$dgEoBwE8n?L4a%l&y zUv6-JUXvU~F6;;Ya61smLX$zh&9Wj?*u}n;S7aiwVxTXW6D${Fi-cr>!E=bIM9<#o z>A5HWt(DT4@Xh@5p0o5`tw&8gyv;Pc{ZdI`2u{e{U)LEn1W>k-gtf(MdaM+!t+wmD z#(^Y6>>9#(T4isHh_qo-X_zPKOu4m{I&ZhoTRUD^$e%0>+NmyRG zWTBBABr(Lj+(Mm2SZTpuz6~Y7gPVdSA9CUqnKHLhHRr~(ZDD5ZbnGT^xv`!F(GmQ{ z&M^kFS$U2U4BR-lN)m{u!LUxz>z#(|R{tQ49A=V3)2RTZ&q~F&NSbrT?^#DQwWC8* z(g@A_?0V5_O*`|EIS!>G{_PkY;C({`t2ka)e+UJZ_pIk$fF_irID5skMmx7UC`vU9 zViHE(v+mN;70Y#{n?*CLJM(*M9nJ(BJ0R#EGwv9|1K88+6_=!2eMgILVpWe9z;rvRf^ zW4GWFCLK_}ty2XAfNcK`@>(i@&;_+Mnuka9Gxd08Ei)x9$xD78A6b5sipzR>>T zjJmm+Q_QVmtqkA0$bTqV8~WYI`^phz2M5O!tmBXa0OHy?*} z3Ct!0OD?*C14ZMiSv_;8YsdF(WX@LW*p$9;5~u}rnWutABtYnV*c$TqHU&Fl2UlYn zHUeEuLB`C2$8X9h&#_s z5(rcIVdDn0($^VjxEOt9_T@5#u};YSd%{8yBC9AZbb%A)0`WT9A51q!RnYhevWOeS4iVW?;c^wS{B4e?F|!`_i;I zIAXE5&KDZL?(L5Z>0fkVu+>;6hBM|;r`(aadJ60!JIk6@NL=KjZq*Lw5wh!&iC4SU zod`V&rFLC5-xjd={moXph!kr`b>tQOf_faKqdtG{yPK5ZKNtn@KL`gv;}?S}rSYZ+6X4DOy)gO8WTu_ddpT8 ze%#0jxi@D9FBhR)-VpCJzsGN1lxgrM5239Oyxx^Od}K-J#d3($E7}`j`Gw<|yST!; zS zl`3<2Yq$GUT?Xc<15njR!{zkJze$tP^Czw0UJ3J)nClU=;I)UR2d`enDU=kBj*{6j z^8=a!FZVH^6Kt-g?y#>S4uxU+L4}PH`EG?xw^E)~^i1walPYU@85cFRj33D1NV?07 z+$nB7oWb`PXN=5p>*uNyw;1cmai&G?jI8rX#J%gktcbpWb1$y;w!{e`{x<<*(i6Lk zAH%VCl8`LR`$cQNF)u$&NJv0PZgsNk4kS%8t}Il8WbmB!B zPi$59g`^p40oBrShG`tLP-KF8iq-uGWh=UVSdfjPLx zMTFMjWmn(4ouU23pzxJ!7^D(c4a2D-*4)yK@q_|5V!rF^({R5>~nYsnS~72 zr)W;_t!w~oZeCcPrT-2KDoVfY3{)|=qjBQ!Cz1-S?=U-L{ffYW$l{zmUb0E?YBRBr zC}EZOx8h*-*-GqVR_smC=LYWY2h5 zKHUIAOdHG_F45Ic!%=C|?${Do zy7)}bvPQnY>7n!2b7zI4`GXtLR5un@?2NaDJxL*Q7+SUGH4{`8uK<>-d%#wR#%5#Z zoc1{Tsb-n~D>(mk{(ALlsm7`E{G}-DbiD%gjb*JhCCl_wlP#Hp_X;)fpAZCI7Qw#D z{IBhd*qoS_@ujlrhy z@bAKWvf&C|eh8{!`oMSC32*X7J~|zM!AFCC+{q2*ZECs|_IxW5w`fstV{`qQ5v6jx z?#F$=X1NhID!ODpu@WCmoJj{sB7%E3T5TO0b8U40_bnzp7~yH z#Gmqo8%kDUp+zJ+?YVJYYfZT{_!Ir+%n+g#F{oU)1SZBOeqYQ4!f9EvivdUd@(9D2 z>w5cXSt#)RMdEfTBL_#d&b?F8>1=ULL~EST!r|Z3!;(`WJC9wuO>a=+ za0VjoP>~Lr(5!G87w0G!iPBepmCiqZUDy*>eI0PK2?)mKMT}WkBFxruacsEw3$MSa z8F9QEQZ=k-z+=O_Ad;>SIx&~MWN8yVKOH}+1d~CeQ3KA|D>i8v?`bBrVpX<8ZQPEp zdPaI`S~;OFx#gx1`^3vlV=XCx=)Yb&ukind;i~1JMws-sYYeEu=*anf=%CDqM(LPi z`m)G6H4`m5qzzC_@EgJb3R?r)9fK*UhA!Xq;BZo_Yw&cqD$?{(tp@Mw4?zln=FXs) zg!lcV3}DEdrJfk36T~ZYdoI|HFzfmvBE?IGzkVtgZqSX69v#F6wX=5_Fy5CXm=9jT zy)KIND>r-Di&qmSd5TQ0)$xJ|iMKz_lAZG+$f>0y9TE1O)LbUeAfoN_OR(&cy;kAZ zt|epDP9B7zFo-wvS|Os9w>X29o}Bkjy)+!%0gm#6-5al4;-%*|`&dCPh~kAw1dyRp z4^N9q&6OeTLnKPYZbMG~`I6!2w=c>E4zsXe4FbgSL%eW{>^ldTL3w`s+MG))Wz3l_ z2o+m8F~u1F;eIhvx%>9igtsQ+2>VI#xJYnu?eb1!v9|hrEsz(&5sZoo8CtU`BAWLv zt=9E%+U3@6bCmXA6=er!<-&l%o@D!*XYSRy`B$JqKYWISZ)Mo9-js%k$UqlpYh{^k z3TtG=$X1ixoRy7#0tBz17nRJ(8)iDa%0bgB*jfj6AejudS9pPT)hiA+;+*RrfjC|i z1iSZ5j4K9_=MO=5UF`c<*zQqF?r7XizN>mIEte){|yh}^odCc6bN5iV&s`@?} zENKCuDBSc{upSacieWf{AHj*ngH9mDhGh^KA7!&agm1t$+TNy{gx9aw;1W&F4#3v9 zf*TwYy!xOK9U;Z^?%*TjqkWYqi)@2lf?;#ubtxd2O)n(CXNFbQ-8vImR4On34b)Uy ze)g_Q2W@g$ldn$c73qnj3XpAMYnGsBXu*(tKV#6&F%H|vY zM#fWZ9e+8Obtc|HY%9d}`QbX(4cW$bc@HZO- z>VcD)tBn(G1Gs58SY4zOp_xw3${)qam4Z8GC1yyNI{Ag%?>&&grhN{wmS^kSe<>Wm zChlIb+}QJ2N?H^^JHvbdlW0}usk!&0}e^_Aq?q&Yv>NHg)!#d8-@a)s}p8nPE z^Jm@?AAswN;;Umie8Ou(9Hxk8ze|qmdR6bZS@1-Neb(3KCNY@ewCnG%E7u=6ds{!+ zy&=9r%FD`?Q@`@1i3@kZSaC{4wd=x~CCfE2DiU1`c@|Q>Y2XEvL>&bFc3RfEOZ4U> zk^UQK-5sf02j<-|%iw<~j8+)% z1x?_^&!$ABB6&i`?lW2kbL{!2GSX$FIx{4vSLAVFnv2_-wXe@xcjy81K`oc^%Qa5a;vWu?pVq9GfRn z)_H|ZY=e#JN%6kXjDbpA@$^CXv^u`CmdhUWD8H+F=^yX};fEvikYlH2!b7Jq;fHOEWxSsEW~%nDj@&!2-i~L1_I8 zh9t;;iQ;KD@C$6X&-{wJVM5$@SwWrM~%+{XRf9K60pK6f2GD!MUyDlg<> zCH7s6d9!76@#9JqjQvcAc%wIsd%*Sc9ll1sKT<(~qYArP_5YLmyW-K_zED8aK-8d~;nvm<2aE9kBLFuF zKPq=3mxoF5w>|G-4*Gu>6cu5Pu|QC89b#$8D&fJH({OZI+smaKNN==zw_d-gCkJ#@ zQ_U@WX9eZCp!2P38e+1qdV}w=dsRn*iaGy$cJOgu=E3 z{s-{u?ApOyo!5+CBLiY>8yihTD%;{KC>{4ZLh7;oiLO^0)<=n<{?(~&ZMO)?$c*W- zfLYZ`uA9^2_3^dgoS?TB8ATu6f`2e+FK}&YJPQxf#&|+2DTpCun3od*#o}2k+j;hc zg0m3_cAB;1-&x}gghDoA#m2@`LjAd)xs+paKr|*>Kc)3DqiBzMuqhOla2aK(?r{^f zxP6(9-H0gXYvgiBX(zMy)**t!j8yp5XVD1Kr+idlWz`1#^&~$&=MJvQ_~- zh-!)bGFa~8q-i~i9<)8#y1IX?>=lp(>o*oA{XqoLe?@|-O6lG9eN#IKTcdHH6`rPd zHUsO;O0hnngM@@7X7vtVr%vt@ticgHy*9f)5Dfnbyt)a#rv0%0CW-dO&MrxX#3A-p z7ATR*=Bw{r7f@*EgbC7Up6QQXO1J#!L7N`~$rnk^RVuqvXke!f(YxME{B zZg^Wp>})LxwPZtfe`4>F2|nd?nQ?OUJ}W81f=|G@ugz%vK6QHW9(f|1yL%(`q0EK2 zosuJ%AbXGTDm_eJEAbH_mqZzh7>@_v=J9kf#v1n*gQ0U{U2~ByM-l&5*dRwyO&ilT zP+l3l<$FR=FBs!HQ16|iit*LG(O6!O6ftwo7pd6jF!zaMp!q99_`JcPw+l&Z>dLj4r@uqez-z3{1KmUW|R-1lqDp{ z-k`x>vRO$O0TuE=R`8W$LAiP$7`64#*6y4;5!_;*c-;5<O+@HY(g?XrU!dY$o_$K6YZ z-&*qeL!o9#*%rB9fS*D(=P@7K>^haDXk$xB*V3~0$CigvHq!L1lHa4!l~#>7;CVIQ zuKHGRw7HGI;AK4Zhc(t`&Y6HT%QRX$Dwj}l_%^H;>L&=YFwJ0il8cP@gs3b_YMpJ= z3vC%`Ys()#LJKV4pezpeCt_xQvRq^N^mW|^c8(0$)C_wWrs19+bpuW?m3vhwYz4yx zvgpEzqw7me%3{_lwOna5@L{KI05T4!pRuQpGqV;a&69;6rYxsgl^G^ihtx9oLmZsC z?uAU2S_H2+{S^NBi_U6ZoN)xK+wHq)N?tfAyal4X7{z7 zD~3U12TN0=J>jJI*xx(T5FtKlTNxviz}sb9*x194v(aH3eirx8q}FYC0EPuxE?JdQ9wCh-p;!-S9-7TsfWG&%D zri~+2QXX4yq$-tj;!&tuqVF^d@hIJS4(pe%GoW;i`nm##>VNULc2C+dcKFPS@_{<& zvCzC-aCNVgdlK;E$L*;B-d=?unpmY-T^$&^8VbNLF6xVQs!UH+0_rAf`&y1ucwk$Nqg^C zw+fz;Nh=odbP=s8{3B!a54rdFhRY?b(+X7UeMY=tsqGu@+i>-F~6hdm*GAv6neITREnI*Tw&pdOkg z3d3FV&VSDtr#QKkz>SVUrl`4L&PV@aeXpV;mfT6;Lb@Ex>WlIF(VQ zl56~DswU<2O?d6?1UKUXvsK3{(c(ZG*>#vN^22} z)z8ff=x`i}FAbTPo1?Q|_s>&VvxfwKFHj8V*LU!MHe{EgDWrGZ=+t|7l4ef7x1*lV zh)f}RWTFJdzgtV(a>KeAfWO&ZXwnX`5fg_A5{JA*kMW-27ET!kW{yUnQ$MP*kSa33-TL>inzNGLw8UMip%6%71&Wdz)8DGHn48>w zwn_hLIM6o6-CyXJtBYCtCcHxA7SibgATyQ3RNp$fZ7kqREsc~VsmdQ1^1E`Rt_z?{PCKNQtEG* z987z=X;(e#*6EDb(Rx>ujQ~#=7o_!_?{^O{7T!p`M?g4@dzch8_v19zk}nt0IncaOZt2)56^ePY}XMcn10@Sz&R-Qse^%|OVV%nU8VcGmhj?`>M^EbS~iV7~RAMlgEkgl~x zaav0_nT#Rt3h?QcOxiQpWiVKxWu~8>bwy5+^O%tA#4n(iX?}!BSiEmZ-{OG3nq{^)4S3#Q$>5`99;>^pet+3Rt`By2VkMKkl3+qq`Mc9Yc$QGcM6R=AhaDywe+5v0fQutX=+bu9uvSuzBpX{ycaS7g(0AEgD0r zsmF1hh9906vL>cZfu?)HB+Vr}Hf-qgX%pYMP#vy=-U9A%1ifdLq z`OiVSNB`F-nOnbpO_cjX+<&d|B!s|6QKlB9jE6B|5Sv5-~u?YcCH;yELQO zGNgsASK9j_6iTIEt}kyV?(;+?_9b5|A8xNEH*fY}Zc!}udeazUOWym&V_ptAO-sBp zd!-6rwyzKO3d1PCgvqDl>)%_Xd7|&VnSMmNpDH&&SET~)2N!Tf`2$cXZQ4N=_U$A@ z`0uy->n^|+o&Z#rOSx*5<6>`%-|w-&hVz)#Es99%+*_f;r*5h#$g8I%i!O{4;hbKy zV>$%Q&-WItW!;eqHN%VLFdl-(FbcIJfv$9TEV}wbT!LF5JJAEUv0CtcY`}ttD&=Um zWSTQAQNk>)J}t5Lw>%1({~XpLJm1*sL&(NB?zFi5++jbfy;v4B@V+aG$^bLN9=Ae`L-hz)|?ENdTP!#ay(h;;GyB+;{CNMnhar-D92K z;LCN_0oN8tT8{=n3ev#JyPr`wx>jFCaOZ$&OkXaKOrnR^Nx7>SKg-&tD$DYxBAL6; zW>rp6ey|SNLr8jeF|Mjddfm#xXdC7TSHq@RVATD2)@4Tr1>fB^u9xEK{HJ^8XYUjI zU#dFt{_&q2D|aesKB?!%4%#u?Y&l=BrOu&O8z2lobgY@60W7Xu5-eH6C$05#Fsuxi zg~;(zVl1#4Ucyu($u5@A+YyOyvP_BKl>PMjv1<-Hgsnz+5vVBSVU+Jkxm0u5 zqWO!S^RBV10YezX>AHA9+hS}Dv4>}E9$T;WtqKt-=%iO+TNdbgAD#Hl2mmjK_cLh* zvfBW9?;CBpAC_!yhM)Hvl|Np;ZmIH(ty98OB4Jg}S=wVsqIR6@H?eQqtt+`b1d=v= zHMscn8{yz`_}v6h0J(xF(G^0+u2bq`IA^g2(SPoWJI>WyNY?>mnd(Ip<)8iGq&HhT+UL0M?3`H)u&;|_ zyboVI$mzAnqBMVKHG}?QKVQ%G1ZI66-S>X~Dn74oo-C-Y_n7~p4!k8r&+~JBQNzHc z|7$so9#MYoHj!r{Wo|P0=Arm*$7XuxmTa8*5C(DBRWAkd11jQL-v}|dW2!9PiCqEM zo!T)@hlbC>lx&EGe3s z@I0swm4aO<6VLPngKZtF!oaxeX?389Jx<=r@?IW%7)AhS=N>B`p}>i+a<=sYc4o?N zi&i>z3mC9>_H;052nFvC$InI(b;HB*1JGvJWK?lzYueE^aZflc5Fxm_d~U#;}&tR&nc)dMXpauow`+4xw~2K?hQ z{HJ^qYDRthIldBLXJ!c_fh54G%TYtOq;X0?bE5zCj)lWD3+gaRf?e2V&NaDuDB_4& zM}VQ395Y9Ox!VWyPb_gsq6-M5BSCM31L||4#}POrtW0>qdQIiz3zxO5-Ut%QortSL zKdgCzF!DLAV<`62s31o?O~ml(L?Jr<3#A{w4crI*r0eQJ@fTmPqdum-J(bt(}e8!xX!bie1D||%j zAhAJJxBThB%?0%~Iy0nl?soLR{$=^OZ9@bQeGrBc&3_4_m6` zRmQyzK`Y@+#B*{NA5!29+BFBZsACiQtU8xkp2tHXG~ULC*Jn;2ksDcT6w$tM!%MsG zhlE9KD%UWKF*O{5O!}F?EnpLReu^^4j$M z7)Iv7HGcF}uJk)d`l0@7U2#I|{mdA9!OtN<1UoRtsM7jv88EwqlHKpF_4zczmGyq* z13Qz|@W+d;MLNJ0+pNH%t_!49QKBXj;eNf$N9LLeCW9@j?T>PV3(jHT5pXJgS9f2IX`0Ldlt%m+M$A?$GoZwm z#5)Z%xUFbJuK|l#Knyy80>_zivGG8+UKGV_>#KqK`Up^1C%)*vgnBglxZ(7Du`=#n zH+4rcmM)fN4#?mrUdGzbH1*8u{&xZjTlaSw6^k27ue5_((&2N`LxUkobgg5#o;>=O zu}uE{q}aVM(Q!aE!!hak$j8jg^2?0D9(mNaRLnGmYdVv1a6var55JWQybQFv~A^t&Prclp|^GSZd+s14|Q(R*!ArdxMkhly%|0$ol`kaew) zZrq>B=r2tP4*Ml&D2<~Y>7MyXEbSO=R@F2*@#C2&SO_N}F<721{Pm(`bix7sdr(MV zcrx?Mmiwk{mUT{*U>>`5 z8jDy#mU0?P7S5{4M#>4-$a#Zvs%>c})}sTp=P!7XsVt^c;&Zc#xsSt9UYnO!>*jKy zxfn_t7ef-74NfFT7oSK&i2%S51vvs#H|J{j)I} zNQuen=@O_he!(=rAGa(}+tb>lQxWl-RdVnbBHNTAP5R-4yX12>5k$Q_;Eu{Fmp%P# zFHdvkDvA?IK4Qm#`^;TXOU7tqPbr*fwPvf@FwE-XRGVeS6Aq8Z=L`n&B``x(Jg6G; zJI1ncv-{UK_A2*mUHi=Co zzcJpQthx^^M|x7Z4n9~AXKO85fCZIn!>RRI7u-3~YW1dv_-vCg94-a=vgypSpYLvy z@z8nm%&niiW4+^={UR34oHPhrz^2{zW*9HjdAP zl`>Jb?3Q1ye(SzD;QU@>m7M3h;GJ5jwDsm9FM^d7UZyTOzwk7nH$Qtm?;`_WMFB~M zQ^I}b#_sIO<29KW?5P+IEWV4XRGB2dGPn1C5gSKi#D=V&h#62mncY&HGmxt>?a4!Z z^vLRy>9{w_`uz`km0z#~jUOb2u}06^J!ub)ABZ|lYPLEy(L>o|1>L+f3T>&muI{>? z0qX+Rt4kN+@vLh(q^Z=2(QiUIc6CFj^=57?~3Cu80g4{lu;Me|a6Qv+gde2pfP z-glcpMRx@QZ7?Dg%;aNGB;K`cDBD|65^2o?9tLyPAae2$QPt4jS7IIJW{nCuG*J(4 z)Chg_s*f|)k3i=6S!L1yHwQSG#a9*aET>pJysry06;4sNcxvZQRQ23RrAP+;G-Qe% z$j8Eh35ta_1kQ=K7jlF0Xn5<*qzqVaTjNCDga1?2S4QO#G;8wW?(Xgcm!QGjU4y%O zunF!E^u;B(yF-8w+#z^ycXwO9dw1{d&it4@r_br?o>NmjPgV6(%Qfpww)7)Qp{Y27 zUzpr5`lt~@@2?yMnZ_|FDWdn3Hdrw?AH~RRdT;r6PB=`zEVEhNNmcR8?r{{(0`<2nsY7%YawKm<_BAHFdti=M>V4%Z!w9;i>?u2{H;oNs`EZ#SGbH&b zD_6SqP)?kGBVy#YNr&o9bdu6fF61katX}n!fmV3as8y3q)@#gFksjpSuL(E$JE@<4 zmMxoaHV7T;2U{iWHv>3*XGSjeI`=}j7gF)`!t9; z)Ivih=MjN3I+0_94zECzX=kVH>(eV%!jD90`r`*Fyp8&E=n^rHj)Iwh1^xVLZt>;A zdbL-*c_$T*#x|t^N{kr(?3}XPu2JT}@648zo zVF6FQ!C^L>kJswIlS!B`-r^vN613XmD5=50}5m3yV`h5Cg<*nIo%VpvW@{A-qzPGIeT9P>%Q4>@Vnejur^docJhtSmV6!S zYJ2ce{k85Jztk(qFZ=aFuFm)0-#1IO12U}EclXr4U6**RWcvE+F7~dVZJ!wWd>#{d z9li{nHW+L7z2xsEwDjuxc7G>@h-=2Zoi5Z|2aL_M@V-02;?&gJr1GL5F>zf)4AhZZ zu7OaZODud6P{Nfq(G8VoS*7WgygnGGel3$wcb-p#!_7uFe&zCKXJGsM$a75cEj&k4 z;Vty-qprznIdKjtr{Ev3g9TaEn}t@AFv*PBjGPWS&>ow~=W zJIP3V1~{DZ9k{f9sYL`fx6L&xFHJazfSpUOxQpt-mMX&qR-5M`MRtvowav;-0hMpp z)WZ1LTng(GohzAW0d`Dj%?CHYpsWNYAW2c%l4%c{&#AxUtqGs43cpDWeS1{sb8144TBHV_ z8wA&w84+5W<6|h&Y$62t7=TF+X$x&@-ZQgCPVvEXMRlRjK9GvhsW^mTf&3_O(!}bL zrgW{XD|(Q0vco4d{#!ORfHTRYr0JKbbyBeQGQK$O_7CVfGFMnZ6(}?=fGnRJDkUT# zgt|DRwZKl{@7gQeoG>aEs1Q<3eoEnb*w}rUSq)s7F}u~c@XXP{f8n#niFK&$clvFz ztJnQTxy|b{;maP!v2Hf3ri2-pXeYjL=O6C?9)fNsxIa~K5kYl75QbD;k@={+GpQ)e z5)faZv)tz~3nH)wkF2}J0pUt&n&7l>{8KOgh=NHGVDlnAbdh~QL9%srIt8UNY3Z?_ zZG6QSu38+AzI0bKT-TsUT8)3qYj zDc|{lEt4vl+zUgLAC2S@6^dK-MWZMs{gJJ$7Z@{hzcvPkwIsZ-w-ckXUdi@B*2-CI zQzGz%r!~_qHL&y}WN3$gXLnvGyKVI_as-=}TwSPX?)>TDe0bRn)hq8FP;=m5aP{YsT&ve=)0N2zAOBv|N?=Rou{Q&zj-_PHoR5kn8X*NiqdxgsBJTB{HAPi{|$(4+C8g|xP#|_2a z5#e0~B|&Zt5B!)vyG75c-$>5(y|g!M@*J5-gB6Z6mW8pk<(>Y#U)NHMxWRbpPP|}| z@=u|4207RP#oc;*9{G=bl$&!e!aO0QYcn-KiDQ{4wVLw2G|C)l?|!{ z0j=H7_d3yKni`QhaMe+9=pUKeX}M9Wh-x$4t8e^OH&FFy9ajtvA@B?RV4*3rlUYRy z_AGgXG10Nk+ij!PJLdG-2qSUk7ax!eOkrxCjV}Aq3g+K#{QVr#ueddhkldIENDR;# z5T)`eUX@Q=G-KM-5Xv=XJp{cg1ig@z-e5ES4;LUD$6x$%u_da&1n6)^Xhr)Um2|oR zp9z|RssL>dQ#@uyPt-3WrhiMG4dMIa*ps6u3C{0}Ovkmscsh*P)Y(SMgo|+E9^XFx zx64O4G0-KFlp5q-FWx)_bRf*ujtxJk6KIt8htLdQ@q zcpM$kNNnW2X>yFQ|q^4Q4KY6-UT57C!YCs%+0YxL;wk~X0 z3%yR-4ViwRbJFs)hml8o$kaD{I!C_zauFGmj#!$0&8x14678PpCLCycI}Ts}`d;*K zuT1uKvAJI5QyaW?dEAZ5@z8QiR{eh8*A1LiAPc{2KE*G*t6SVeH>Ja19?Q7%W7mS> zVI}m^Jv;DhBy}-O7(AI~Mn(d*_+l%6j^~|K-SmoH6Mlf;BxWHe9Z;O5$I~F*67~2X zR>8~OInQrc#sY}FrMIT&NJpN>l^>!^Ved=0VQXaZ#W*!`4A zG%qj_ZoItI2;J}SdRY`#qi9FJ75ygG$?);`UyBW0i)-V8T6pbnF8J_21JPqj_gZ4B z^#U~BgyU$;e7g+Eif3OmdH9EEmw;gxpN!CAnFo8RJbTMfyyoy*l=F1_@nV9HqM}M% zT|KJ?I<|eM98$@2w%v*#{mO($1xYK#djaOW4$0+=dj?Hzb|)*Lw(FJ?;ic-tFXy2P zE5(9i{B~QTM7Z*B^Gi=Dw-x&pK7T`a*4FkPFcNd_yY@lMD+r?*Di?FBuYlP~)}4?` z7#`i6$?SF`Vv-cS76@wPY_+k~W*mO4x|Go*=C@>9^{!LZGK!9S`Jw-~Kv03zWF_Pq zUlC;t#bHBodMvFOwp5k`$*;&V&s8Y1vf0(EI}Q}^I&X-*eN2c{L=?o8+Bt2dWj|EK zU&c%Yg35iA;)Wn8t)iIPd4OV;Kenf~B|K)YB8LGv+Q)ZF+)IZWJevd`x8 zRd8f$Nq=9IaI&c`=;S_n-F+FbSqIy{az7sQwRFZ(PE)Ul=2vqjWzJ;n}@JhckBXdE>SOyyh+dop0yIBEVJRb1ghNil32%2Ca&z zyN|%((!pbmkqGuV7a-LAKs`TJ#20U5Ka|4Tx#_w18XfK>_fM>yd@BCCQKvwga$|H# zwtQHM6whF9rfxPFrzRv=<1(^-Qbf3*f2q%c6_-(<>j0v zYxU-vHy3_4UxTgd5+Tn*p2Znu6c#PE_-b}!&Ztc*F%H~74dB+W?(v!6+TVZ!OBTCd zW)WZD-h{T92Q4UK%L_9tT(`pN@Wx&MOB5dy;geT48^+^wzc(L#>||yR3}b>q>s-^6 z;^glwRL)duGNylWi>*Auyn8hf zNa5bswiGbX16Eo1tCf`o8$70U;lR?N4z_bycn<7}XCby86b1B3AJkEC?yJ3zV2C}R zo|n;qUIp~nE$ZdErn;!HRgGx~F4iCR+tzzgVRe{1z&93w_F1NyDP5Wylz6&N>{k|^ zw@b%eb1fbtg|&hkxA4ZC|5sSr-~j zbT>juBiL;`m<}CX9|kl(Gw+$s8vl;{uG!Tg!haLd$R5F-@L&+a6WM3RN)T4C+1Ox$Wl7!# zfMCA+a?xX2jM5=rEJN%v?Eqla>cledt%ZWPfMysxX)7E1mPc?He+>0eb4$-%Ti50~ zK>XF`)qMv=s(%z23|5}8_6^jZmT*&Y{Rj=g*R~B zuc3vBpO-`23_m#W_8il4l*R2onFoFKW|gm63tg3q@4VPb%o2_(jt*^Z9fP5WC}z zBFnM+lxtwAwO}nvIFMLLQqlpwcBoQtDTUuB|0k8=*rz_4ML2g-((zuMVw43gh#vJ* z=Un=CU{H8bMH(bpTtZPwS`~f5D_99kQI9pSMV3@ zCpm`~Ne{KVE)@xN=44Zg4ehXjStf1fZxRvien{E zL-v4urXRP~YwhZFD?@Ta`}-%P-Lcr7vWnt8h0Sl%`$T(|P8Hi96z(CY7^p+bqR~AK zJq;_nx^$s_%s%I}kOPjjz{x=zsm@cJ@q~HD;B!Ep<&-G7k&s%*@Fcf zzYVvcYg7TMRF!D)f>wo2Zb17F1YGRE^v3D_mXYNQ$21;GQF>*|`%-W9ii~U3JP(N; z8C~%5a)`7FHna>Cm1A1Sd>QXam3BN5bAO8YxyDUx8;^sIq;P2n;QWcAAKkmTKoBW) zizNX^Cu(%QlDS_EiPWYR8e-Hl*`imilcgC_-lasqQTsEN8xDGtr>u_-nX!NAFJbK1 zI6AiwfmMP~wfq{7MegfOw(PwcL>r6$#-3tH#s-LmM2wBt9^DOP7@;sY38v^xTI+7n zFizD8@GyEEiNJ#qVgP4lQV$*dcZp+tRlP@73v3Qb{0CRE)oP8!*kl;yJ?QSH(#8={4b`W~}!+v`8= zCsf;!*L+B*Tp&^)qwoCQdI$!eaCXQg%M%X!lEe< zHmW1GD-QbHa(%qovrIVlzc&ZTxM*9SG?nrfbge@E98NdR?$H(p-%Im!v(!E2z~Q6T zJ+ZkiIM2BsbO90hLAp$Vr>^e?TC16>k}8`8u+IFtS}9oMc9je4EF4^H?^HNq%#1eqP6ijqqr z=m!?r$g*Jjnx@V~M$LR!p9;HD-c4WygMFSJQB&FcKv^7m_z1LDh~+LVPLMH-MM zB?lgu5MCro0y$8mNziICiy? zjK0cT^PMSeZicjppN?|wnL^MPOh#PF2p(w4W5EP&%Z!Tnfe|Ev?*ojp_-NZ9STG1E zU(B*g>h|o-Z!dMeDZ^dpSdb=B;3}}wr|1s4Nj>o_xj-kWghBtKi~WR|qSmCR#fT*h z%~=g%_b981Rg6>p`Uf8P`@t5hcm_&ZWg!*y#^gj?ICAjd48nhYiEu7gn)#+?@ju;h81xbKdNK8K17gvBoFSH6}4y3zVtj_SF;&t|76UsS(Rjjc%@S8?ntL%qu(JNd-?{79K z>YQ`7{45)FwT*yq@kl-n>3C&+!S@GPk{rv|mj_2vX5Xv!2b$}$4Gr>czuk^YzDe4e zdawQ&o}*0g#23KK@8nxjuqgZ8@FH zG)Skt%Zu1wV~}H2@N)1Dlaz;mgD^3ko9zz?0g;=O6HW-YEwiEj@+y88El^(}FeQRV z$w^Zn#G(!7QV?_Og4c(onJ-90-dy(z{W>Kb7LxAzWqIzbCHGEz^syglayrVkuQ0;d zdCN>fl2V-(7b76c&})K?BQ+vG0yptI->4`VxMT35j5qq^U=!mi~n#i@ZossPtS6} zp{k|PsGoALMZ<=V5}MyG(`X6SY|k?ukd=s54ilyVxEJV8HtBz^6CaNw0)g+8s6U7K zLVgE~XCTliG={FvWn}NcmN-EjyrJgd4n}fL*Q>A)3ZR}!3G(Wksdj@ZFu&c~?(uP; z$^YDdxuWjWg)bWxgp(pC2&$&KZy2D$=lLk?#xdvEr`Cw7O&#xS#dZV}mupw-6|Nc_yKQ zUc{x)`;;k8JUQme=|p>XvuUW+8%D(R#e$ktih3hT^wVE{D!?c;SO8N;T2qNhMUYD0 zak%efKi(z@7eXm;o97Fv#jI3AO!CAb7cvV|TcIaC45x8E;4BWy5%Lo~CLASAP~j(^ zZFeJRpsGK_t(@m?B1!hk7;FZUJFYRcM=STSirTf-F{s||=ubsy$O@&G`^xMWDcgb> zl78c_Kf((QMLUY5)8wx_f56o0x$Z8<p#<(QdJ07PhTFi z6EGt?IDbYr0@MQ50?p?%19I5oKBYyJEK+@9*j&%@r%6Qgka?+^C+6lQ1!Bn`W%3pl zQ1)8_^~e_gc-S-DHt%0aKO-4*P>{(tEZ|%lsKwH$)Vnun86Vh%;%p8E=EWJD>tIv!ia8Aqwg` zG1BNpp^p9RxLshapf%wDkFXO#gf_|+*hIrYfKd;A9b60GgY{8j&hEFeS|P z$-{jFan2pHQmU3LJ1gjIbhx+fTSA#L3PBAjQs{8GmUxJ!Id(!IPeo#23&#s?V<0+E zs;HEQNtp#RVP|pvTbObxocvqOQew;mi-OhJ@ z-bG{h{osjeMx;oN$17^aSH=JO3_9<`f%o zq2dDm&^b76!lM2A-KxBBQ4Zr_Yvqc-{-p!mMWmFUzB#YR)<;T#GLehgOnPyQZ^s+b z|JH`!gt(T3I8YND0&QI@#uFR_L_b(L6+{bIbKfJGeM5pWu2));wQYI^kt4{_Z~ulQ zAC_Z$&w&+9OZ7{0y^=7Va93XM=>2wo4KDuW!}y$kw7i1z9$8gA;<<8Ke)r~i`|NbN zTvZ)bXYD1q+O&ImR79*L(*3?owkA{)?n-R4;w;I$Y_e+aq>Z-it+W0Qc_qA_AuJbY z7hl3`J%1|3KWysmwuySX-rn?C;SM*g}`8w zvCe5Fl6U5|aQ;i}CBhr4H~+kOm+c1-oZ*8}YdZ;7agOgV^i0S9T)35hli=p*_oU_e z+RcvcgpYh1Z_Oc2R-yRy#w{!BuXXb=+P%X9US`J6#J_Enky_^r%H-d=Y)a7Fgo;v}JR z>ZrZ&a$7umrTX?!ddZ^W`D_;@ccB6)Q#-_sGAH+JuaGve*?OqH2J=?Eg^5mH=x#1v z0HEa43yw~L*yk)eISJd{)K+r>mPYaSd6boX6b=YXf^2d`CFFM5V^jax#?T)sV_e~~ z+ec>eM(pzUM__>`E*U4;V;8`!G;-#Mlx0na(>V~b9^YlmDWqa9sDp8L6^5Z_4DQhI zm}Md{NT`LS>;ITKs?mYmW@p0HDSt`E)P0u7x?l{HLFZ`uUdsI24O;yZ5SW97O-bsb z^aI5Y5u;2q1QXsy4W^4FW^Uf-OFgn%gVz4XVY7Y6Cuu&L)SvgTm$bY(JWfdv{)}pt z_+yv}2m~fKn2C(`En|B+WDGH5#1hy^d_+YQ!D5OuRYden?x`gY#L9sYld|5VtRIPw z%%Y~=hz{hzxOjyVLoRH1fO#@|pJ%ilK0aI&5*9@)B_e22HR@Z|?Fb=GzHrpmxVS!( zG!1DkR%vpdUXdCVb1J!+YzTWfN77F1S?N$~=)N_rI;hP?sSdtD)vXUoDny1QhLNQ) zUWLro4P!q@ikKh9SA$yhNv6?q=&)PmHwYG#cP2v7L47~${(A^sVX zBC_{w*t~ISUMdZH7T?Adg@!HaGaNT}MmbG!9an)d0x{Yme~7_B^6#ai2F-KTrHA3(mZ2j)4O&TkuC%HC)>FUBKW_4gT75m_TLzn*vye=P z(l*Q=e!=c(IwkX|pOJIPW#}#%iN+`BKb^gl1d+h#X3jM9LTCY`Q{2*s z&0zsH2bWkhbKrOfGZDr*yGJ*U8^xdwS;};Szpo7)8is8?yqx}xmE2kmwz8}!5It8s z7m1Kc!xSfGZ6jtdg_T;)tLs{|{KQM$PQ%pVyT zhaYM}GI@A28b{FcKe(DOy&AY0FttayY~woIq}I>9F@cd*57cEAtRu0K@q-SdFH0P< zyO=(o)Ujc8AXyTTEoG&GdHd?81qo}5rDP4H5r&~smk)?1QwbF5@vL1L>lXRjF7P_h zV-@mS+$>?LcS0l#SlpCOq4ntYIriAZTxIhiZikDST4(pP@X_eP|D}(aW#k3@R#PY8 zO`|P>4g;3b_8I%I0!TxDFUiP+y|;`Na3Q3U%f)jt$vF_*prIT`_H#)|*|%6*M5yGZ zu^k%U#z&ezMAN`xxC};!Rv^oxw~fcwxp9j3J$sG&v|psZN#y35F2re%DJ1^D`xl(uG8v~>4crB?z3gC!TioQMHaiG&SEgP zzY*tXM*2Ld5vs*k?bH30xrIR+|MfYKdxNup&)e%P<5KvfQR3<23yRoAtDVm60AY2` z{4V&?Q}e9c#e&W}@`9F! z9uO@E7+2b6L;rp*^NgBsUY4CKB5Cu(Q#!=YJmQ%etQ|D*%!G+Z;l zm{QiTuq5Up&1%J%TDE-CMUW0KX+4>RvT20*fV`b%P@M@_MTPSsGcivWP^zmfLv?8WQH*ubPNjM|Q8q8+1lx|v_eNOhV0b4Tq;|Hij@FE1Lt=~R zL9Ejrbp_`!2R-HGuyeJd{_hxXZXabgUu@~kg_vOJFFL}1f z1Ab#%D*8ubLLGR#Ugv?nuF<>OS8K0stSDWyM@wJ(DjB(X*Jeir2YT69l5csJb7u4} z+?8U5?z9CldVmQIV8ZWl1NUqksEIwtQgxbfW;&8iMA?QtymIHhY8KiEB-5Nh^)&oU z_Vy$sETOCLvx_aNFD+)9erZh+zO7V%^yG9MK3WrQo#-FDB+zGOa&JZK*07<$l+n%X#x%MO ze}`xp6QGCjUCw6&uwjBcX9W&q2;}M*TMRXkHpkB|T`Y$_ksUKG1z(RG&ydgt(ciklHC<2v$aXQw z19Oylhs}SJixQnJcEnNmr(7~77zAObV6d&4>8MGzP08NCjcgo8*Itjklw?+)|2AWS z9tL%EV-c}zrF>aO711@TZ8z{{5nz3is`_yS$tLkn(K~pnFZ}rBCkam3^iM;uIE?Yw zT>=s~_%CW(=C$OazLV^cCA$v*nHlq42 zB>a`^vugz=_ieD3GVQ4(VVF*!SS5D@r`J(EQ79+8Su~Pc(V~Thj19Kt@UpJbsB=TY z7rSVdkV-;O3+0bvaJA>*1~Y5MTlS={N#46Na>ua>{7XaoqA0Y~bD9tUcqJ_Tf|TF~ z4eM$#n786Tc45H5L|D5%O7>A;R(}090Z?15;1D|CI7@2MAo8rAnOV{LiS<;_1GRa> zD0FoIG4eXSaB0V{6)hNlB@Yjg*jXfRt+)CTwK|HmCC>eV;~_&p9(PDI7k$d{~T=l@q}7q z0)a8mK)B#P;~+*zZVvFpe|j&Sz?>5xI_m#HSfmgT82?w|M~kun1mWf6YR>8gj-LV% zfzu~Igpl$b;HC+X0HoI>_-Xu9U2o7SV delta 37652 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 z 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