Refactored all tests to derive from a common PreprocessorTest. This avoids some code duplication.
Review URL: https://codereview.appspot.com/6257048

git-svn-id: https://angleproject.googlecode.com/svn/trunk@1097 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/tests/build_tests.gyp b/tests/build_tests.gyp
index 69e10b8..dceb61e 100644
--- a/tests/build_tests.gyp
+++ b/tests/build_tests.gyp
@@ -54,6 +54,7 @@
         'preprocessor_tests/number_test.cpp',
         'preprocessor_tests/operator_test.cpp',
         'preprocessor_tests/pragma_test.cpp',
+        'preprocessor_tests/PreprocessorTest.h',
         'preprocessor_tests/space_test.cpp',
         'preprocessor_tests/token_test.cpp',
         'preprocessor_tests/version_test.cpp',
diff --git a/tests/preprocessor_tests/PreprocessorTest.h b/tests/preprocessor_tests/PreprocessorTest.h
new file mode 100644
index 0000000..9dbfd7b
--- /dev/null
+++ b/tests/preprocessor_tests/PreprocessorTest.h
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "gtest/gtest.h"
+
+#include "MockDiagnostics.h"
+#include "MockDirectiveHandler.h"
+#include "Preprocessor.h"
+
+#ifndef PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
+#define PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
+
+class PreprocessorTest : public testing::Test
+{
+  protected:
+    PreprocessorTest() : mPreprocessor(&mDiagnostics, &mDirectiveHandler) { }
+
+    MockDiagnostics mDiagnostics;
+    MockDirectiveHandler mDirectiveHandler;
+    pp::Preprocessor mPreprocessor;
+};
+
+#endif  // PREPROCESSOR_TESTS_PREPROCESSOR_TEST_H_
diff --git a/tests/preprocessor_tests/char_test.cpp b/tests/preprocessor_tests/char_test.cpp
index 5095f42..cce0cd7 100644
--- a/tests/preprocessor_tests/char_test.cpp
+++ b/tests/preprocessor_tests/char_test.cpp
@@ -7,16 +7,13 @@
 #include <algorithm>
 #include <climits>
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
 #if GTEST_HAS_PARAM_TEST
 
-class CharTest : public testing::TestWithParam<int>
+class CharTest : public PreprocessorTest,
+                 public testing::WithParamInterface<int>
 {
 };
 
@@ -50,12 +47,9 @@
     const char* cstr = str.c_str();
     int length = 1;
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
     // Note that we pass the length param as well because the invalid
     // string may contain the null character.
-    ASSERT_TRUE(preprocessor.init(1, &cstr, &length));
+    ASSERT_TRUE(mPreprocessor.init(1, &cstr, &length));
 
     int expectedType = pp::Token::LAST;
     std::string expectedValue;
@@ -89,12 +83,12 @@
     {
         // Everything else is invalid.
         using testing::_;
-        EXPECT_CALL(diagnostics,
+        EXPECT_CALL(mDiagnostics,
             print(pp::Diagnostics::INVALID_CHARACTER, _, str));
     }
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(expectedType, token.type);
     EXPECT_EQ(expectedValue, token.value);
 };
diff --git a/tests/preprocessor_tests/comment_test.cpp b/tests/preprocessor_tests/comment_test.cpp
index 9a8409a..d32c790 100644
--- a/tests/preprocessor_tests/comment_test.cpp
+++ b/tests/preprocessor_tests/comment_test.cpp
@@ -4,14 +4,13 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-class CommentTest : public testing::TestWithParam<const char*>
+#if GTEST_HAS_PARAM_TEST
+
+class CommentTest : public PreprocessorTest,
+                    public testing::WithParamInterface<const char*>
 {
 };
 
@@ -19,13 +18,10 @@
 {
     const char* str = GetParam();
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
+    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(pp::Token::LAST, token.type);
 }
 
@@ -44,34 +40,34 @@
                                         "/***/",     // With lone '*'.
                                         "/*\"*/"));  // Invalid character.
 
-TEST(BlockComment, CommentReplacedWithSpace)
+#endif  // GTEST_HAS_PARAM_TEST
+
+class BlockCommentTest : public PreprocessorTest
+{
+};
+
+TEST_F(BlockCommentTest, CommentReplacedWithSpace)
 {
     const char* str = "/*foo*/bar";
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
+    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
     EXPECT_EQ("bar", token.value);
     EXPECT_TRUE(token.hasLeadingSpace());
 }
 
-TEST(BlockComment, UnterminatedComment)
+TEST_F(BlockCommentTest, UnterminatedComment)
 {
     const char* str = "/*foo";
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
+    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
 
     using testing::_;
-    EXPECT_CALL(diagnostics, print(pp::Diagnostics::EOF_IN_COMMENT, _, _));
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_COMMENT, _, _));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
 }
diff --git a/tests/preprocessor_tests/error_test.cpp b/tests/preprocessor_tests/error_test.cpp
index c577385..08ed672 100644
--- a/tests/preprocessor_tests/error_test.cpp
+++ b/tests/preprocessor_tests/error_test.cpp
@@ -4,48 +4,38 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-class ErrorTest : public testing::Test
+class ErrorTest : public PreprocessorTest
 {
   protected:
-    ErrorTest() : mPreprocessor(&mDiagnostics, &mDirectiveHandler) { }
-
-    void lex()
+    void preprocess(const char* str)
     {
+        ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
+
         pp::Token token;
         mPreprocessor.lex(&token);
         EXPECT_EQ(pp::Token::LAST, token.type);
         EXPECT_EQ("", token.value);
     }
-
-    MockDiagnostics mDiagnostics;
-    MockDirectiveHandler mDirectiveHandler;
-    pp::Preprocessor mPreprocessor;
 };
 
 TEST_F(ErrorTest, Empty)
 {
     const char* str = "#error\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler, handleError(pp::SourceLocation(0, 1), ""));
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(ErrorTest, OneTokenMessage)
 {
     const char* str = "#error foo\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -53,13 +43,12 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(ErrorTest, TwoTokenMessage)
 {
     const char* str = "#error foo bar\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -67,7 +56,7 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(ErrorTest, Comments)
@@ -83,7 +72,6 @@
                       "/*foo*/"
                       "//foo"
                       "\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -91,13 +79,12 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(ErrorTest, MissingNewline)
 {
     const char* str = "#error foo";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     // Directive successfully parsed.
@@ -106,5 +93,5 @@
     // Error reported about EOF.
     EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
 
-    lex();
+    preprocess(str);
 }
diff --git a/tests/preprocessor_tests/extension_test.cpp b/tests/preprocessor_tests/extension_test.cpp
index 7f523ff..c2f3a75 100644
--- a/tests/preprocessor_tests/extension_test.cpp
+++ b/tests/preprocessor_tests/extension_test.cpp
@@ -4,35 +4,26 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-class ExtensionTest : public testing::Test
+class ExtensionTest : public PreprocessorTest
 {
 protected:
-    ExtensionTest() : mPreprocessor(&mDiagnostics, &mDirectiveHandler) { }
-
-    void lex()
+    void preprocess(const char* str)
     {
+        ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
+
         pp::Token token;
         mPreprocessor.lex(&token);
         EXPECT_EQ(pp::Token::LAST, token.type);
         EXPECT_EQ("", token.value);
     }
-
-    MockDiagnostics mDiagnostics;
-    MockDirectiveHandler mDirectiveHandler;
-    pp::Preprocessor mPreprocessor;
 };
 
 TEST_F(ExtensionTest, Valid)
 {
     const char* str = "#extension foo : bar\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -40,7 +31,7 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(ExtensionTest, Comments)
@@ -58,7 +49,6 @@
                       "/*foo*/"
                       "//foo"
                       "\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -66,13 +56,12 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(ExtensionTest, MissingNewline)
 {
     const char* str = "#extension foo : bar";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     // Directive successfully parsed.
@@ -81,9 +70,11 @@
     // Error reported about EOF.
     EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
 
-    lex();
+    preprocess(str);
 }
 
+#if GTEST_HAS_PARAM_TEST
+
 struct ExtensionTestParam
 {
     const char* str;
@@ -99,7 +90,6 @@
 TEST_P(InvalidExtensionTest, Identified)
 {
     ExtensionTestParam param = GetParam();
-    ASSERT_TRUE(mPreprocessor.init(1, &param.str, NULL));
 
     using testing::_;
     // No handleExtension call.
@@ -107,7 +97,7 @@
     // Invalid extension directive call.
     EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
 
-    lex();
+    preprocess(param.str);
 }
 
 static const ExtensionTestParam kParams[] = {
@@ -119,3 +109,5 @@
     {"#extension foo : bar baz\n", pp::Diagnostics::UNEXPECTED_TOKEN}
 };
 INSTANTIATE_TEST_CASE_P(All, InvalidExtensionTest, testing::ValuesIn(kParams));
+
+#endif  // GTEST_HAS_PARAM_TEST
\ No newline at end of file
diff --git a/tests/preprocessor_tests/identifier_test.cpp b/tests/preprocessor_tests/identifier_test.cpp
index d4b1dab..5e7037c 100644
--- a/tests/preprocessor_tests/identifier_test.cpp
+++ b/tests/preprocessor_tests/identifier_test.cpp
@@ -4,132 +4,145 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-static void PreprocessAndVerifyIdentifier(const char* str)
+class IdentifierTest : public PreprocessorTest
 {
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
+protected:
+    void preprocess(const std::string& str)
+    {
+        const char* cstr = str.c_str();
+        ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
 
-    pp::Token token;
-    preprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ(str, token.value);
+        pp::Token token;
+        mPreprocessor.lex(&token);
+        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+        EXPECT_EQ(str, token.value);
+    }
+};
+
+#if GTEST_HAS_PARAM_TEST
+
+#define CLOSED_RANGE(x, y) testing::Range(x, static_cast<char>((y) + 1))
+
+class SingleLetterIdentifierTest : public IdentifierTest,
+                                   public testing::WithParamInterface<char>
+{
+};
+
+// This test covers identifier names of form [_a-zA-Z].
+TEST_P(SingleLetterIdentifierTest, Identified)
+{
+    std::string str(1, GetParam());
+    preprocess(str);
 }
 
+// Test string: '_'
+INSTANTIATE_TEST_CASE_P(Underscore,
+                        SingleLetterIdentifierTest,
+                        testing::Values('_'));
+
+// Test string: [a-z]
+INSTANTIATE_TEST_CASE_P(a_z,
+                        SingleLetterIdentifierTest,
+                        CLOSED_RANGE('a', 'z'));
+
+// Test string: [A-Z]
+INSTANTIATE_TEST_CASE_P(A_Z,
+                        SingleLetterIdentifierTest,
+                        CLOSED_RANGE('A', 'Z'));
+
+#endif  // GTEST_HAS_PARAM_TEST
+
 #if GTEST_HAS_COMBINE
 
 typedef std::tr1::tuple<char, char> IdentifierParams;
-class IdentifierTest : public testing::TestWithParam<IdentifierParams>
+class DoubleLetterIdentifierTest :
+    public IdentifierTest,
+    public testing::WithParamInterface<IdentifierParams>
 {
 };
 
-// This test covers identifier names of form [_a-zA-Z][_a-zA-Z0-9]?.
-TEST_P(IdentifierTest, IdentifierIdentified)
+// This test covers identifier names of form [_a-zA-Z][_a-zA-Z0-9].
+TEST_P(DoubleLetterIdentifierTest, Identified)
 {
-    std::string str(1, std::tr1::get<0>(GetParam()));
-    char c = std::tr1::get<1>(GetParam());
-    if (c != '\0') str.push_back(c);
+    std::string str;
+    str.push_back(std::tr1::get<0>(GetParam()));
+    str.push_back(std::tr1::get<1>(GetParam()));
 
-    PreprocessAndVerifyIdentifier(str.c_str());
+    preprocess(str);
 }
 
-#define CLOSED_RANGE(x, y) testing::Range(x, static_cast<char>((y) + 1))
-
-// Test string: '_'
-INSTANTIATE_TEST_CASE_P(SingleLetter_Underscore,
-                        IdentifierTest,
-                        testing::Combine(testing::Values('_'),
-                                         testing::Values('\0')));
-
-// Test string: [a-z]
-INSTANTIATE_TEST_CASE_P(SingleLetter_a_z,
-                        IdentifierTest,
-                        testing::Combine(CLOSED_RANGE('a', 'z'),
-                                         testing::Values('\0')));
-
-// Test string: [A-Z]
-INSTANTIATE_TEST_CASE_P(SingleLetter_A_Z,
-                        IdentifierTest,
-                        testing::Combine(CLOSED_RANGE('A', 'Z'),
-                                         testing::Values('\0')));
-
 // Test string: "__"
-INSTANTIATE_TEST_CASE_P(DoubleLetter_Underscore_Underscore,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(Underscore_Underscore,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(testing::Values('_'),
                                          testing::Values('_')));
 
 // Test string: "_"[a-z]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_Underscore_a_z,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(Underscore_a_z,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(testing::Values('_'),
                                          CLOSED_RANGE('a', 'z')));
 
 // Test string: "_"[A-Z]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_Underscore_A_Z,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(Underscore_A_Z,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(testing::Values('_'),
                                          CLOSED_RANGE('A', 'Z')));
 
 // Test string: "_"[0-9]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_Underscore_0_9,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(Underscore_0_9,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(testing::Values('_'),
                                          CLOSED_RANGE('0', '9')));
 
 // Test string: [a-z]"_"
-INSTANTIATE_TEST_CASE_P(DoubleLetter_a_z_Underscore,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(a_z_Underscore,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('a', 'z'),
                                          testing::Values('_')));
 
 // Test string: [a-z][a-z]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_a_z_a_z,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(a_z_a_z,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('a', 'z'),
                                          CLOSED_RANGE('a', 'z')));
 
 // Test string: [a-z][A-Z]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_a_z_A_Z,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(a_z_A_Z,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('a', 'z'),
                                          CLOSED_RANGE('A', 'Z')));
 
 // Test string: [a-z][0-9]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_a_z_0_9,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(a_z_0_9,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('a', 'z'),
                                          CLOSED_RANGE('0', '9')));
 
 // Test string: [A-Z]"_"
-INSTANTIATE_TEST_CASE_P(DoubleLetter_A_Z_Underscore,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(A_Z_Underscore,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('A', 'Z'),
                                          testing::Values('_')));
 
 // Test string: [A-Z][a-z]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_A_Z_a_z,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(A_Z_a_z,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('A', 'Z'),
                                          CLOSED_RANGE('a', 'z')));
 
 // Test string: [A-Z][A-Z]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_A_Z_A_Z,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(A_Z_A_Z,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('A', 'Z'),
                                          CLOSED_RANGE('A', 'Z')));
 
 // Test string: [A-Z][0-9]
-INSTANTIATE_TEST_CASE_P(DoubleLetter_A_Z_0_9,
-                        IdentifierTest,
+INSTANTIATE_TEST_CASE_P(A_Z_0_9,
+                        DoubleLetterIdentifierTest,
                         testing::Combine(CLOSED_RANGE('A', 'Z'),
                                          CLOSED_RANGE('0', '9')));
 
@@ -137,7 +150,7 @@
 
 // The tests above cover one-letter and various combinations of two-letter
 // identifier names. This test covers all characters in a single string.
-TEST(IdentifierTestAllCharacters, IdentifierIdentified)
+TEST_F(IdentifierTest, AllLetters)
 {
     std::string str;
     for (int c = 'a'; c <= 'z'; ++c)
@@ -153,5 +166,5 @@
     for (int c = '0'; c <= '9'; ++c)
         str.push_back(c);
 
-    PreprocessAndVerifyIdentifier(str.c_str());
+    preprocess(str);
 }
diff --git a/tests/preprocessor_tests/input_test.cpp b/tests/preprocessor_tests/input_test.cpp
index 3692375..3a4aec2 100644
--- a/tests/preprocessor_tests/input_test.cpp
+++ b/tests/preprocessor_tests/input_test.cpp
@@ -4,39 +4,30 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-TEST(InputTest, NegativeCount)
+class InitTest : public PreprocessorTest
 {
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    EXPECT_FALSE(preprocessor.init(-1, NULL, NULL));
+};
+
+TEST_F(InitTest, NegativeCount)
+{
+    EXPECT_FALSE(mPreprocessor.init(-1, NULL, NULL));
 }
 
-TEST(InputTest, ZeroCount)
+TEST_F(InitTest, ZeroCount)
 {
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    EXPECT_TRUE(preprocessor.init(0, NULL, NULL));
+    EXPECT_TRUE(mPreprocessor.init(0, NULL, NULL));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(pp::Token::LAST, token.type);
 }
 
-TEST(InputTest, NullString)
+TEST_F(InitTest, NullString)
 {
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    EXPECT_FALSE(preprocessor.init(1, NULL, NULL));
+    EXPECT_FALSE(mPreprocessor.init(1, NULL, NULL));
 }
 
 TEST(InputTest, DefaultConstructor)
diff --git a/tests/preprocessor_tests/location_test.cpp b/tests/preprocessor_tests/location_test.cpp
index 275e0dd..ccce7bb 100644
--- a/tests/preprocessor_tests/location_test.cpp
+++ b/tests/preprocessor_tests/location_test.cpp
@@ -4,33 +4,30 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-static void PreprocessAndVerifyLocation(int count,
-                                        const char* const string[],
-                                        const int length[],
-                                        const pp::SourceLocation& location)
+class LocationTest : public PreprocessorTest
 {
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(count, string, length));
+protected:
+    void preprocess(int count,
+                    const char* const string[],
+                    const int length[],
+                    const pp::SourceLocation& location)
+    {
+        ASSERT_TRUE(mPreprocessor.init(count, string, length));
 
-    pp::Token token;
-    preprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ("foo", token.value);
+        pp::Token token;
+        mPreprocessor.lex(&token);
+        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+        EXPECT_EQ("foo", token.value);
 
-    EXPECT_EQ(location.file, token.location.file);
-    EXPECT_EQ(location.line, token.location.line);
-}
+        EXPECT_EQ(location.file, token.location.file);
+        EXPECT_EQ(location.line, token.location.line);
+    }
+};
 
-TEST(LocationTest, String0_Line1)
+TEST_F(LocationTest, String0_Line1)
 {
     const char* str = "foo";
     pp::SourceLocation loc;
@@ -38,10 +35,10 @@
     loc.line = 1;
 
     SCOPED_TRACE("String0_Line1");
-    PreprocessAndVerifyLocation(1, &str, 0, loc);
+    preprocess(1, &str, 0, loc);
 }
 
-TEST(LocationTest, String0_Line2)
+TEST_F(LocationTest, String0_Line2)
 {
     const char* str = "\nfoo";
     pp::SourceLocation loc;
@@ -49,10 +46,10 @@
     loc.line = 2;
 
     SCOPED_TRACE("String0_Line2");
-    PreprocessAndVerifyLocation(1, &str, 0, loc);
+    preprocess(1, &str, 0, loc);
 }
 
-TEST(LocationTest, String1_Line1)
+TEST_F(LocationTest, String1_Line1)
 {
     const char* const str[] = {"\n\n", "foo"};
     pp::SourceLocation loc;
@@ -60,10 +57,10 @@
     loc.line = 1;
 
     SCOPED_TRACE("String1_Line1");
-    PreprocessAndVerifyLocation(2, str, 0, loc);
+    preprocess(2, str, 0, loc);
 }
 
-TEST(LocationTest, String1_Line2)
+TEST_F(LocationTest, String1_Line2)
 {
     const char* const str[] = {"\n\n", "\nfoo"};
     pp::SourceLocation loc;
@@ -71,10 +68,10 @@
     loc.line = 2;
 
     SCOPED_TRACE("String1_Line2");
-    PreprocessAndVerifyLocation(2, str, 0, loc);
+    preprocess(2, str, 0, loc);
 }
 
-TEST(LocationTest, NewlineInsideCommentCounted)
+TEST_F(LocationTest, NewlineInsideCommentCounted)
 {
     const char* str = "/*\n\n*/foo";
     pp::SourceLocation loc;
@@ -82,30 +79,26 @@
     loc.line = 3;
 
     SCOPED_TRACE("NewlineInsideCommentCounted");
-    PreprocessAndVerifyLocation(1, &str, 0, loc);
+    preprocess(1, &str, 0, loc);
 }
 
-TEST(LocationTest, ErrorLocationAfterComment)
+TEST_F(LocationTest, ErrorLocationAfterComment)
 {
     const char* str = "/*\n\n*/@";
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
-
-    pp::Diagnostics::ID id(pp::Diagnostics::INVALID_CHARACTER);
-    pp::SourceLocation loc(0, 3);
-    EXPECT_CALL(diagnostics, print(id, loc, "@"));
+    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::INVALID_CHARACTER,
+                                    pp::SourceLocation(0, 3),
+                                    "@"));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
 }
 
 // The location of a token straddling two or more strings is that of the
 // first character of the token.
 
-TEST(LocationTest, TokenStraddlingTwoStrings)
+TEST_F(LocationTest, TokenStraddlingTwoStrings)
 {
     const char* const str[] = {"f", "oo"};
     pp::SourceLocation loc;
@@ -113,10 +106,10 @@
     loc.line = 1;
 
     SCOPED_TRACE("TokenStraddlingTwoStrings");
-    PreprocessAndVerifyLocation(2, str, 0, loc);
+    preprocess(2, str, 0, loc);
 }
 
-TEST(LocationTest, TokenStraddlingThreeStrings)
+TEST_F(LocationTest, TokenStraddlingThreeStrings)
 {
     const char* const str[] = {"f", "o", "o"};
     pp::SourceLocation loc;
@@ -124,7 +117,7 @@
     loc.line = 1;
 
     SCOPED_TRACE("TokenStraddlingThreeStrings");
-    PreprocessAndVerifyLocation(3, str, 0, loc);
+    preprocess(3, str, 0, loc);
 }
 
 // TODO(alokp): Add tests for #line directives.
diff --git a/tests/preprocessor_tests/number_test.cpp b/tests/preprocessor_tests/number_test.cpp
index 4ccf5ab..e579d7b 100644
--- a/tests/preprocessor_tests/number_test.cpp
+++ b/tests/preprocessor_tests/number_test.cpp
@@ -4,33 +4,26 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
 #if GTEST_HAS_PARAM_TEST
 
-class InvalidNumberTest : public testing::TestWithParam<const char*>
+class InvalidNumberTest : public PreprocessorTest,
+                          public testing::WithParamInterface<const char*>
 {
 };
 
 TEST_P(InvalidNumberTest, InvalidNumberIdentified)
 {
     const char* str = GetParam();
-
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
+    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
 
     using testing::_;
-    EXPECT_CALL(diagnostics, print(pp::Diagnostics::INVALID_NUMBER, _, str));
+    EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::INVALID_NUMBER, _, str));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
 }
 
 INSTANTIATE_TEST_CASE_P(InvalidIntegers, InvalidNumberTest,
@@ -45,23 +38,21 @@
 #if GTEST_HAS_COMBINE
 
 typedef std::tr1::tuple<const char*, char> IntegerParams;
-class IntegerTest : public testing::TestWithParam<IntegerParams>
+class IntegerTest : public PreprocessorTest,
+                    public testing::WithParamInterface<IntegerParams>
 {
 };
 
-TEST_P(IntegerTest, IntegerIdentified)
+TEST_P(IntegerTest, Identified)
 {
     std::string str(std::tr1::get<0>(GetParam()));  // prefix.
     str.push_back(std::tr1::get<1>(GetParam()));  // digit.
     const char* cstr = str.c_str();
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &cstr, 0));
+    ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(pp::Token::CONST_INT, token.type);
     EXPECT_EQ(str, token.value);
 }
@@ -93,21 +84,25 @@
                         testing::Combine(testing::Values("0x"),
                                          CLOSED_RANGE('A', 'F')));
 
-static void PreprocessAndVerifyFloat(const char* str)
+class FloatTest : public PreprocessorTest
 {
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
+  protected:
+    void preprocess(const std::string& str)
+    {
+        const char* cstr = str.c_str();
+        ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
 
-    pp::Token token;
-    preprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::CONST_FLOAT, token.type);
-    EXPECT_EQ(str, token.value);
-}
+        pp::Token token;
+        mPreprocessor.lex(&token);
+        EXPECT_EQ(pp::Token::CONST_FLOAT, token.type);
+        EXPECT_EQ(str, token.value);
+    }
+};
 
 typedef std::tr1::tuple<char, char, const char*, char> FloatScientificParams;
-class FloatScientificTest : public testing::TestWithParam<FloatScientificParams>
+class FloatScientificTest :
+    public FloatTest,
+    public testing::WithParamInterface<FloatScientificParams>
 {
 };
 
@@ -121,7 +116,7 @@
     str.push_back(std::tr1::get<3>(GetParam()));  // exponent [0-9].
 
     SCOPED_TRACE("FloatScientificTest");
-    PreprocessAndVerifyFloat(str.c_str());
+    preprocess(str);
 }
 
 INSTANTIATE_TEST_CASE_P(FloatScientific,
@@ -132,7 +127,9 @@
                                          CLOSED_RANGE('0', '9')));
 
 typedef std::tr1::tuple<char, char> FloatFractionParams;
-class FloatFractionTest : public testing::TestWithParam<FloatFractionParams>
+class FloatFractionTest :
+    public FloatTest,
+    public testing::WithParamInterface<FloatFractionParams>
 {
 };
 
@@ -152,7 +149,7 @@
         str.push_back(fraction);
 
     SCOPED_TRACE("FloatFractionTest");
-    PreprocessAndVerifyFloat(str.c_str());
+    preprocess(str);
 }
 
 INSTANTIATE_TEST_CASE_P(FloatFraction_X_X,
@@ -174,9 +171,8 @@
 
 // In the tests above we have tested individual parts of a float separately.
 // This test has all parts of a float.
-
-TEST(FloatFractionScientificTest, FloatIdentified)
+TEST_F(FloatTest, FractionScientific)
 {
-    SCOPED_TRACE("FloatFractionScientificTest");
-    PreprocessAndVerifyFloat("0.1e+2");
+    SCOPED_TRACE("FractionScientific");
+    preprocess("0.1e+2");
 }
diff --git a/tests/preprocessor_tests/operator_test.cpp b/tests/preprocessor_tests/operator_test.cpp
index 61a3d32..fb0bf39 100644
--- a/tests/preprocessor_tests/operator_test.cpp
+++ b/tests/preprocessor_tests/operator_test.cpp
@@ -4,11 +4,7 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
 #if GTEST_HAS_PARAM_TEST
@@ -19,7 +15,8 @@
     int op;
 };
 
-class OperatorTest : public testing::TestWithParam<OperatorTestParam>
+class OperatorTest : public PreprocessorTest,
+                     public testing::WithParamInterface<OperatorTestParam>
 {
 };
 
@@ -27,13 +24,10 @@
 {
     OperatorTestParam param = GetParam();
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &param.str, 0));
+    ASSERT_TRUE(mPreprocessor.init(1, &param.str, 0));
 
     pp::Token token;
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(param.op, token.type);
     EXPECT_EQ(param.str, token.value);
 }
diff --git a/tests/preprocessor_tests/pragma_test.cpp b/tests/preprocessor_tests/pragma_test.cpp
index 0189e2c..bd5c559 100644
--- a/tests/preprocessor_tests/pragma_test.cpp
+++ b/tests/preprocessor_tests/pragma_test.cpp
@@ -4,35 +4,26 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-class PragmaTest : public testing::Test
+class PragmaTest : public PreprocessorTest
 {
 protected:
-    PragmaTest() : mPreprocessor(&mDiagnostics, &mDirectiveHandler) { }
-
-    void lex()
+    void preprocess(const char* str)
     {
+        ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
+
         pp::Token token;
         mPreprocessor.lex(&token);
         EXPECT_EQ(pp::Token::LAST, token.type);
         EXPECT_EQ("", token.value);
     }
-
-    MockDiagnostics mDiagnostics;
-    MockDirectiveHandler mDirectiveHandler;
-    pp::Preprocessor mPreprocessor;
 };
 
 TEST_F(PragmaTest, EmptyName)
 {
     const char* str = "#pragma\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     // No handlePragma calls.
@@ -40,13 +31,12 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(PragmaTest, EmptyValue)
 {
     const char* str = "#pragma foo\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -54,13 +44,12 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(PragmaTest, NameValue)
 {
     const char* str = "#pragma foo(bar)\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -68,7 +57,7 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(PragmaTest, Comments)
@@ -88,7 +77,6 @@
                       "/*foo*/"
                       "//foo"
                       "\n";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     EXPECT_CALL(mDirectiveHandler,
@@ -96,13 +84,12 @@
     // No error or warning.
     EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
 
-    lex();
+    preprocess(str);
 }
 
 TEST_F(PragmaTest, MissingNewline)
 {
     const char* str = "#pragma foo(bar)";
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     // Pragma successfully parsed.
@@ -111,9 +98,11 @@
     // Error reported about EOF.
     EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::EOF_IN_DIRECTIVE, _, _));
 
-    lex();
+    preprocess(str);
 }
 
+#if GTEST_HAS_PARAM_TEST
+
 class InvalidPragmaTest : public PragmaTest,
                           public testing::WithParamInterface<const char*>
 {
@@ -122,7 +111,6 @@
 TEST_P(InvalidPragmaTest, Identified)
 {
     const char* str = GetParam();
-    ASSERT_TRUE(mPreprocessor.init(1, &str, NULL));
 
     using testing::_;
     // No handlePragma calls.
@@ -132,7 +120,7 @@
                 print(pp::Diagnostics::UNRECOGNIZED_PRAGMA,
                       pp::SourceLocation(0, 1), _));
 
-    lex();
+    preprocess(str);
 }
 
 INSTANTIATE_TEST_CASE_P(All, InvalidPragmaTest, testing::Values(
@@ -142,3 +130,5 @@
     "#pragma foo(bar\n",         // Missing right paren.
     "#pragma foo bar\n",         // Missing parens.
     "#pragma foo(bar) baz\n"));  // Extra tokens.
+
+#endif  // GTEST_HAS_PARAM_TEST
\ No newline at end of file
diff --git a/tests/preprocessor_tests/space_test.cpp b/tests/preprocessor_tests/space_test.cpp
index 021bcf3..b365f9a 100644
--- a/tests/preprocessor_tests/space_test.cpp
+++ b/tests/preprocessor_tests/space_test.cpp
@@ -4,13 +4,27 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
+class SpaceTest : public PreprocessorTest
+{
+  protected:
+    void preprocess(const std::string& str)
+    {
+        const char* cstr = str.c_str();
+        ASSERT_TRUE(mPreprocessor.init(1, &cstr, 0));
+
+        pp::Token token;
+        // "foo" is returned after ignoring the whitespace characters.
+        mPreprocessor.lex(&token);
+        EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
+        EXPECT_EQ("foo", token.value);
+        // The whitespace character is however recorded with the next token.
+        EXPECT_TRUE(token.hasLeadingSpace());
+    }
+};
+
 // Whitespace characters allowed in GLSL.
 // Note that newline characters (\n) will be tested separately.
 static const char kSpaceChars[] = {' ', '\t', '\v', '\f'};
@@ -20,30 +34,18 @@
 // This test fixture tests the processing of a single whitespace character.
 // All tests in this fixture are ran with all possible whitespace character
 // allowed in GLSL.
-class SpaceCharTest : public testing::TestWithParam<char>
+class SpaceCharTest : public SpaceTest,
+                      public testing::WithParamInterface<char>
 {
 };
 
 TEST_P(SpaceCharTest, SpaceIgnored)
 {
     // Construct test string with the whitespace char before "foo".
-    const char* identifier = "foo";
     std::string str(1, GetParam());
-    str.append(identifier);
-    const char* cstr = str.c_str();
-
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &cstr, 0));
-
-    pp::Token token;
-    // Identifier "foo" is returned after ignoring the whitespace characters.
-    preprocessor.lex(&token);
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ(identifier, token.value);
-    // The whitespace character is however recorded with the next token.
-    EXPECT_TRUE(token.hasLeadingSpace());
+    str.append("foo");
+    
+    preprocess(str);
 }
 
 INSTANTIATE_TEST_CASE_P(SingleSpaceChar,
@@ -58,32 +60,21 @@
 // whitespace characters. All tests in this fixture are ran with all possible
 // combinations of whitespace characters allowed in GLSL.
 typedef std::tr1::tuple<char, char, char> SpaceStringParams;
-class SpaceStringTest : public testing::TestWithParam<SpaceStringParams>
+class SpaceStringTest : public SpaceTest,
+                        public testing::WithParamInterface<SpaceStringParams>
 {
 };
 
 TEST_P(SpaceStringTest, SpaceIgnored)
 {
     // Construct test string with the whitespace char before "foo".
-    const char* identifier = "foo";
-    std::string str(1, std::tr1::get<0>(GetParam()));
+    std::string str;
+    str.push_back(std::tr1::get<0>(GetParam()));
     str.push_back(std::tr1::get<1>(GetParam()));
     str.push_back(std::tr1::get<2>(GetParam()));
-    str.append(identifier);
-    const char* cstr = str.c_str();
+    str.append("foo");
 
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &cstr, 0));
-
-    pp::Token token;
-    preprocessor.lex(&token);
-    // Identifier "foo" is returned after ignoring the whitespace characters.
-    EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
-    EXPECT_EQ(identifier, token.value);
-    // The whitespace character is however recorded with the next token.
-    EXPECT_TRUE(token.hasLeadingSpace());
+    preprocess(str);
 }
 
 INSTANTIATE_TEST_CASE_P(SpaceCharCombination,
@@ -97,30 +88,26 @@
 // The tests above make sure that the space char is recorded in the
 // next token. This test makes sure that a token is not incorrectly marked
 // to have leading space.
-TEST(SpaceTest, LeadingSpace)
+TEST_F(SpaceTest, LeadingSpace)
 {
     const char* str = " foo+ -bar";
+    ASSERT_TRUE(mPreprocessor.init(1, &str, 0));
 
     pp::Token token;
-    MockDiagnostics diagnostics;
-    MockDirectiveHandler directiveHandler;
-    pp::Preprocessor preprocessor(&diagnostics, &directiveHandler);
-    ASSERT_TRUE(preprocessor.init(1, &str, 0));
-
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
     EXPECT_EQ("foo", token.value);
     EXPECT_TRUE(token.hasLeadingSpace());
 
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ('+', token.type);
     EXPECT_FALSE(token.hasLeadingSpace());
 
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ('-', token.type);
     EXPECT_TRUE(token.hasLeadingSpace());
 
-    preprocessor.lex(&token);
+    mPreprocessor.lex(&token);
     EXPECT_EQ(pp::Token::IDENTIFIER, token.type);
     EXPECT_EQ("bar", token.value);
     EXPECT_FALSE(token.hasLeadingSpace());
diff --git a/tests/preprocessor_tests/version_test.cpp b/tests/preprocessor_tests/version_test.cpp
index 329153c..84ade01 100644
--- a/tests/preprocessor_tests/version_test.cpp
+++ b/tests/preprocessor_tests/version_test.cpp
@@ -4,18 +4,12 @@
 // found in the LICENSE file.
 //
 
-#include "gtest/gtest.h"
-
-#include "MockDiagnostics.h"
-#include "MockDirectiveHandler.h"
-#include "Preprocessor.h"
+#include "PreprocessorTest.h"
 #include "Token.h"
 
-class VersionTest : public testing::Test
+class VersionTest : public PreprocessorTest
 {
-protected:
-    VersionTest() : mPreprocessor(&mDiagnostics, &mDirectiveHandler) { }
-
+  protected:
     void lex()
     {
         pp::Token token;
@@ -23,10 +17,6 @@
         EXPECT_EQ(pp::Token::LAST, token.type);
         EXPECT_EQ("", token.value);
     }
-
-    MockDiagnostics mDiagnostics;
-    MockDirectiveHandler mDirectiveHandler;
-    pp::Preprocessor mPreprocessor;
 };
 
 TEST_F(VersionTest, Valid)
@@ -80,6 +70,8 @@
     lex();
 }
 
+#if GTEST_HAS_PARAM_TEST
+
 struct VersionTestParam
 {
     const char* str;
@@ -112,3 +104,5 @@
 };
 
 INSTANTIATE_TEST_CASE_P(All, InvalidVersionTest, testing::ValuesIn(kParams));
+
+#endif // GTEST_HAS_PARAM_TEST
\ No newline at end of file