Add Program Binary test for reinitialization.

This test tears down and recreates GL and re-uses the binary in
a new GL context. Was meant to reproduce a bug in ANGLE, but the
bug had been fixed previously.

BUG=angleproject:2010

Change-Id: Ic3a31ac044ef4d794dae14608877b6958452b55e
Reviewed-on: https://chromium-review.googlesource.com/519463
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/tests/gl_tests/ProgramBinaryTest.cpp b/src/tests/gl_tests/ProgramBinaryTest.cpp
index 8c69f2c..9ab10ff 100644
--- a/src/tests/gl_tests/ProgramBinaryTest.cpp
+++ b/src/tests/gl_tests/ProgramBinaryTest.cpp
@@ -79,6 +79,25 @@
         return formatCount;
     }
 
+    bool supported() const
+    {
+        if (!extensionEnabled("GL_OES_get_program_binary"))
+        {
+            std::cout << "Test skipped because GL_OES_get_program_binary is not available."
+                      << std::endl;
+            return false;
+        }
+
+        if (getAvailableProgramBinaryFormatCount() == 0)
+        {
+            std::cout << "Test skipped because no program binary formats are available."
+                      << std::endl;
+            return false;
+        }
+
+        return true;
+    }
+
     GLuint mProgram;
     GLuint mBuffer;
 };
@@ -87,16 +106,8 @@
 // should not internally cause a vertex shader recompile (for conversion).
 TEST_P(ProgramBinaryTest, FloatDynamicShaderSize)
 {
-    if (!extensionEnabled("GL_OES_get_program_binary"))
+    if (!supported())
     {
-        std::cout << "Test skipped because GL_OES_get_program_binary is not available."
-                  << std::endl;
-        return;
-    }
-
-    if (getAvailableProgramBinaryFormatCount() == 0)
-    {
-        std::cout << "Test skipped because no program binary formats are available." << std::endl;
         return;
     }
 
@@ -146,16 +157,8 @@
 // This tests the ability to successfully save and load a program binary.
 TEST_P(ProgramBinaryTest, SaveAndLoadBinary)
 {
-    if (!extensionEnabled("GL_OES_get_program_binary"))
+    if (!supported())
     {
-        std::cout << "Test skipped because GL_OES_get_program_binary is not available."
-                  << std::endl;
-        return;
-    }
-
-    if (getAvailableProgramBinaryFormatCount() == 0)
-    {
-        std::cout << "Test skipped because no program binary formats are available." << std::endl;
         return;
     }
 
@@ -215,6 +218,39 @@
     }
 }
 
+// Ensures that we init the compiler before calling ProgramBinary.
+TEST_P(ProgramBinaryTest, CallProgramBinaryBeforeLink)
+{
+    if (!supported())
+    {
+        return;
+    }
+
+    // Initialize a simple program.
+    glUseProgram(mProgram);
+
+    GLsizei length = 0;
+    glGetProgramiv(mProgram, GL_PROGRAM_BINARY_LENGTH, &length);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GT(length, 0);
+
+    GLsizei readLength  = 0;
+    GLenum binaryFormat = GL_NONE;
+    std::vector<uint8_t> binaryBlob(length);
+    glGetProgramBinaryOES(mProgram, length, &readLength, &binaryFormat, binaryBlob.data());
+    ASSERT_GL_NO_ERROR();
+
+    // Shutdown and restart GL entirely.
+    TearDown();
+    SetUp();
+
+    ANGLE_GL_BINARY_OES_PROGRAM(binaryProgram, binaryBlob, binaryFormat);
+    ASSERT_GL_NO_ERROR();
+
+    drawQuad(binaryProgram, "inputAttribute", 0.5f);
+    ASSERT_GL_NO_ERROR();
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(ProgramBinaryTest,
                        ES2_D3D9(),