| Index: gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
 | 
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
 | 
| index c0e23649fc29fc965553f229d965371d737a7b82..afb9fc76558dac8a15fc15b2c4b612aa6b2a950a 100644
 | 
| --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
 | 
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
 | 
| @@ -43,7 +43,6 @@ using ::testing::Pointee;
 | 
|  using ::testing::Return;
 | 
|  using ::testing::SaveArg;
 | 
|  using ::testing::SetArrayArgument;
 | 
| -using ::testing::SetArgumentPointee;
 | 
|  using ::testing::SetArgPointee;
 | 
|  using ::testing::StrEq;
 | 
|  using ::testing::StrictMock;
 | 
| @@ -122,6 +121,93 @@ TEST_P(GLES2DecoderWithShaderTest, GetUniformBlocksCHROMIUMInvalidArgs) {
 | 
|    EXPECT_EQ(0u, header->num_uniform_blocks);
 | 
|  }
 | 
|  
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetUniformsES3CHROMIUMValidArgs) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  GetUniformsES3CHROMIUM cmd;
 | 
| +  cmd.Init(client_program_id_, kBucketId);
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORMS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(0))
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
 | 
| +  EXPECT_EQ(sizeof(UniformsES3Header), bucket->size());
 | 
| +  UniformsES3Header* header =
 | 
| +      bucket->GetDataAs<UniformsES3Header*>(0, sizeof(UniformsES3Header));
 | 
| +  EXPECT_TRUE(header != NULL);
 | 
| +  EXPECT_EQ(0u, header->num_uniforms);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(false);
 | 
| +  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetUniformsES3CHROMIUMInvalidArgs) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
 | 
| +  EXPECT_TRUE(bucket == NULL);
 | 
| +  GetUniformsES3CHROMIUM cmd;
 | 
| +  cmd.Init(kInvalidClientId, kBucketId);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +  bucket = decoder_->GetBucket(kBucketId);
 | 
| +  ASSERT_TRUE(bucket != NULL);
 | 
| +  EXPECT_EQ(sizeof(UniformsES3Header), bucket->size());
 | 
| +  UniformsES3Header* header =
 | 
| +      bucket->GetDataAs<UniformsES3Header*>(0, sizeof(UniformsES3Header));
 | 
| +  ASSERT_TRUE(header != NULL);
 | 
| +  EXPECT_EQ(0u, header->num_uniforms);
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest,
 | 
| +       GetTransformFeedbackVaryingsCHROMIUMValidArgs) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  GetTransformFeedbackVaryingsCHROMIUM cmd;
 | 
| +  cmd.Init(client_program_id_, kBucketId);
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetProgramiv(
 | 
| +                  kServiceProgramId, GL_TRANSFORM_FEEDBACK_VARYINGS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(0))
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
 | 
| +  EXPECT_EQ(sizeof(TransformFeedbackVaryingsHeader), bucket->size());
 | 
| +  TransformFeedbackVaryingsHeader* header =
 | 
| +      bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(
 | 
| +          0, sizeof(TransformFeedbackVaryingsHeader));
 | 
| +  EXPECT_TRUE(header != NULL);
 | 
| +  EXPECT_EQ(0u, header->num_transform_feedback_varyings);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(false);
 | 
| +  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest,
 | 
| +       GetTransformFeedbackVaryingsCHROMIUMInvalidArgs) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
 | 
| +  EXPECT_TRUE(bucket == NULL);
 | 
| +  GetTransformFeedbackVaryingsCHROMIUM cmd;
 | 
| +  cmd.Init(kInvalidClientId, kBucketId);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +  bucket = decoder_->GetBucket(kBucketId);
 | 
| +  ASSERT_TRUE(bucket != NULL);
 | 
| +  EXPECT_EQ(sizeof(TransformFeedbackVaryingsHeader), bucket->size());
 | 
| +  TransformFeedbackVaryingsHeader* header =
 | 
| +      bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(
 | 
| +          0, sizeof(TransformFeedbackVaryingsHeader));
 | 
| +  ASSERT_TRUE(header != NULL);
 | 
| +  EXPECT_EQ(0u, header->num_transform_feedback_varyings);
 | 
| +}
 | 
| +
 | 
|  TEST_P(GLES2DecoderWithShaderTest, GetUniformivSucceeds) {
 | 
|    GetUniformiv::Result* result =
 | 
|        static_cast<GetUniformiv::Result*>(shared_memory_address_);
 | 
| @@ -344,7 +430,7 @@ TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersSucceeds) {
 | 
|    Result* result = static_cast<Result*>(shared_memory_address_);
 | 
|    result->size = 0;
 | 
|    EXPECT_CALL(*gl_, GetAttachedShaders(kServiceProgramId, 1, _, _)).WillOnce(
 | 
| -      DoAll(SetArgumentPointee<2>(1), SetArgumentPointee<3>(kServiceShaderId)));
 | 
| +      DoAll(SetArgPointee<2>(1), SetArgPointee<3>(kServiceShaderId)));
 | 
|    cmd.Init(client_program_id_,
 | 
|             shared_memory_id_,
 | 
|             shared_memory_offset_,
 | 
| @@ -409,7 +495,7 @@ TEST_P(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatSucceeds) {
 | 
|    const GLint precision = 16;
 | 
|    EXPECT_CALL(*gl_, GetShaderPrecisionFormat(_, _, _, _))
 | 
|        .WillOnce(DoAll(SetArrayArgument<2>(range, range + 2),
 | 
| -                      SetArgumentPointee<3>(precision)))
 | 
| +                      SetArgPointee<3>(precision)))
 | 
|        .RetiresOnSaturation();
 | 
|    cmd.Init(GL_VERTEX_SHADER,
 | 
|             GL_HIGH_FLOAT,
 | 
| @@ -681,6 +767,175 @@ TEST_P(GLES2DecoderWithShaderTest,
 | 
|    EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
|  }
 | 
|  
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockivSucceeds) {
 | 
| +  GetActiveUniformBlockiv cmd;
 | 
| +  typedef GetActiveUniformBlockiv::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  GLenum kPname[] {
 | 
| +    GL_UNIFORM_BLOCK_BINDING,
 | 
| +    GL_UNIFORM_BLOCK_DATA_SIZE,
 | 
| +    GL_UNIFORM_BLOCK_NAME_LENGTH,
 | 
| +    GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
 | 
| +    GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
 | 
| +    GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
 | 
| +    GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
 | 
| +  };
 | 
| +  for (size_t ii = 0; ii < arraysize(kPname); ++ii) {
 | 
| +    result->SetNumResults(0);
 | 
| +    cmd.Init(client_program_id_,
 | 
| +             0,
 | 
| +             kPname[ii],
 | 
| +             shared_memory_id_,
 | 
| +             shared_memory_offset_);
 | 
| +    EXPECT_CALL(*gl_, GetError())
 | 
| +        .WillOnce(Return(GL_NO_ERROR))
 | 
| +        .WillOnce(Return(GL_NO_ERROR))
 | 
| +        .RetiresOnSaturation();
 | 
| +    EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +        .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +        .RetiresOnSaturation();
 | 
| +    if (kPname[ii] == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
 | 
| +      EXPECT_CALL(*gl_, GetError())
 | 
| +          .WillOnce(Return(GL_NO_ERROR))
 | 
| +          .RetiresOnSaturation();
 | 
| +      EXPECT_CALL(*gl_,
 | 
| +                  GetActiveUniformBlockiv(kServiceProgramId, 0,
 | 
| +                      GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _))
 | 
| +          .WillOnce(SetArgPointee<3>(1))
 | 
| +          .RetiresOnSaturation();
 | 
| +    }
 | 
| +    EXPECT_CALL(*gl_,
 | 
| +                GetActiveUniformBlockiv(
 | 
| +                    kServiceProgramId, 0, kPname[ii], _))
 | 
| +        .WillOnce(SetArgPointee<3>(1976))
 | 
| +        .RetiresOnSaturation();
 | 
| +    decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +    EXPECT_EQ(1, result->GetNumResults());
 | 
| +    EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +    EXPECT_EQ(1976, result->GetData()[0]);
 | 
| +    decoder_->set_unsafe_es3_apis_enabled(false);
 | 
| +    EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest,
 | 
| +       GetActiveUniformBlockivSucceedsZeroUniforms) {
 | 
| +  GetActiveUniformBlockiv cmd;
 | 
| +  typedef GetActiveUniformBlockiv::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->SetNumResults(0);
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           0,
 | 
| +           GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetActiveUniformBlockiv(
 | 
| +                  kServiceProgramId, 0, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _))
 | 
| +      .WillOnce(SetArgPointee<3>(0))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetActiveUniformBlockiv(kServiceProgramId, 0,
 | 
| +                  GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, _))
 | 
| +      .Times(1)
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockivUnlinkedProgram) {
 | 
| +  GetActiveUniformBlockiv cmd;
 | 
| +  typedef GetActiveUniformBlockiv::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->SetNumResults(0);
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           0,
 | 
| +           GL_UNIFORM_BLOCK_BINDING,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_FALSE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest,
 | 
| +       GetActiveUniformBlockivResultNotInitFails) {
 | 
| +  GetActiveUniformBlockiv cmd;
 | 
| +  typedef GetActiveUniformBlockiv::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->SetNumResults(1);  // Should be initialized to 0.
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           0,
 | 
| +           GL_UNIFORM_BLOCK_BINDING,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockivBadProgramFails) {
 | 
| +  GetActiveUniformBlockiv cmd;
 | 
| +  typedef GetActiveUniformBlockiv::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->SetNumResults(0);
 | 
| +  cmd.Init(kInvalidClientId,
 | 
| +           0,
 | 
| +           GL_UNIFORM_BLOCK_BINDING,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest,
 | 
| +       GetActiveUniformBlockivBadSharedMemoryFails) {
 | 
| +  GetActiveUniformBlockiv cmd;
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .RetiresOnSaturation();
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           0,
 | 
| +           GL_UNIFORM_BLOCK_BINDING,
 | 
| +           kInvalidSharedMemoryId,
 | 
| +           shared_memory_offset_);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           0,
 | 
| +           GL_UNIFORM_BLOCK_BINDING,
 | 
| +           shared_memory_id_,
 | 
| +           kInvalidSharedMemoryOffset);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
|  TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribSucceeds) {
 | 
|    const GLuint kAttribIndex = 1;
 | 
|    const uint32 kBucketId = 123;
 | 
| @@ -782,6 +1037,306 @@ TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribBadSharedMemoryFails) {
 | 
|    EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
|  }
 | 
|  
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesSucceeds) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const char kName0[] = "Cow";
 | 
| +  const char kName1[] = "Chicken";
 | 
| +  const char* kNames[] = { kName0, kName1 };
 | 
| +  const size_t kCount = arraysize(kNames);
 | 
| +  const char kValidStrEnd = 0;
 | 
| +  const GLuint kIndices[] = { 1, 2 };
 | 
| +  SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
 | 
| +  GetUniformIndices::Result* result =
 | 
| +      static_cast<GetUniformIndices::Result*>(shared_memory_address_);
 | 
| +  GetUniformIndices cmd;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  EXPECT_CALL(*gl_, GetUniformIndices(kServiceProgramId, kCount, _, _))
 | 
| +      .WillOnce(SetArrayArgument<3>(kIndices, kIndices + kCount))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(kCount, static_cast<size_t>(result->GetNumResults()));
 | 
| +  for (size_t ii = 0; ii < kCount; ++ii) {
 | 
| +    EXPECT_EQ(kIndices[ii], result->GetData()[ii]);
 | 
| +  }
 | 
| +  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(false);
 | 
| +  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesBadProgramFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const char kName0[] = "Cow";
 | 
| +  const char kName1[] = "Chicken";
 | 
| +  const char* kNames[] = { kName0, kName1 };
 | 
| +  const size_t kCount = arraysize(kNames);
 | 
| +  const char kValidStrEnd = 0;
 | 
| +  SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
 | 
| +  GetUniformIndices::Result* result =
 | 
| +      static_cast<GetUniformIndices::Result*>(shared_memory_address_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  GetUniformIndices cmd;
 | 
| +  // None-existant program
 | 
| +  cmd.Init(kInvalidClientId,
 | 
| +           kBucketId,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
| +  // Unlinked program.
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_FALSE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesBadParamsFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const char kName0[] = "Cow";
 | 
| +  const char kName1[] = "Chicken";
 | 
| +  const char* kNames[] = { kName0, kName1 };
 | 
| +  const size_t kCount = arraysize(kNames);
 | 
| +  const char kValidStrEnd = 0;
 | 
| +  const GLuint kIndices[] = { 1, 2 };
 | 
| +  SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
 | 
| +  GetUniformIndices::Result* result =
 | 
| +      static_cast<GetUniformIndices::Result*>(shared_memory_address_);
 | 
| +  GetUniformIndices cmd;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  EXPECT_CALL(*gl_, GetUniformIndices(kServiceProgramId, kCount, _, _))
 | 
| +      .WillOnce(SetArrayArgument<3>(kIndices, kIndices + kCount))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_INVALID_VALUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesResultNotInitFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const char kName0[] = "Cow";
 | 
| +  const char kName1[] = "Chicken";
 | 
| +  const char* kNames[] = { kName0, kName1 };
 | 
| +  const size_t kCount = arraysize(kNames);
 | 
| +  const char kValidStrEnd = 0;
 | 
| +  SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
 | 
| +  GetUniformIndices::Result* result =
 | 
| +      static_cast<GetUniformIndices::Result*>(shared_memory_address_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  GetUniformIndices cmd;
 | 
| +  result->size = 1976;  // Any value other than 0.
 | 
| +  cmd.Init(kInvalidClientId,
 | 
| +           kBucketId,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesBadSharedMemoryFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const char kName0[] = "Cow";
 | 
| +  const char kName1[] = "Chicken";
 | 
| +  const char* kNames[] = { kName0, kName1 };
 | 
| +  const size_t kCount = arraysize(kNames);
 | 
| +  const char kValidStrEnd = 0;
 | 
| +  SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
 | 
| +  GetUniformIndices::Result* result =
 | 
| +      static_cast<GetUniformIndices::Result*>(shared_memory_address_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  GetUniformIndices cmd;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           kInvalidSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           kSharedMemoryId,
 | 
| +           kInvalidSharedMemoryOffset);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivSucceeds) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const GLuint kIndices[] = { 1, 2 };
 | 
| +  const GLint kResults[] = { 1976, 321 };
 | 
| +  const size_t kCount = arraysize(kIndices);
 | 
| +  SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
 | 
| +  GetActiveUniformsiv::Result* result =
 | 
| +      static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
 | 
| +  GetActiveUniformsiv cmd;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           GL_UNIFORM_TYPE,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetActiveUniformsiv(
 | 
| +                  kServiceProgramId, kCount, _, GL_UNIFORM_TYPE, _))
 | 
| +      .WillOnce(SetArrayArgument<4>(kResults, kResults + kCount))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(kCount, static_cast<size_t>(result->GetNumResults()));
 | 
| +  for (size_t ii = 0; ii < kCount; ++ii) {
 | 
| +    EXPECT_EQ(kResults[ii], result->GetData()[ii]);
 | 
| +  }
 | 
| +  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(false);
 | 
| +  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivBadProgramFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const GLuint kIndices[] = { 1, 2 };
 | 
| +  const size_t kCount = arraysize(kIndices);
 | 
| +  SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
 | 
| +  GetActiveUniformsiv::Result* result =
 | 
| +      static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  GetActiveUniformsiv cmd;
 | 
| +  // None-existant program
 | 
| +  cmd.Init(kInvalidClientId,
 | 
| +           kBucketId,
 | 
| +           GL_UNIFORM_TYPE,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
| +  // Unlinked program.
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           GL_UNIFORM_TYPE,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_FALSE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivBadParamsFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const GLuint kIndices[] = { 1, 2 };
 | 
| +  const GLint kResults[] = { 1976, 321 };
 | 
| +  const size_t kCount = arraysize(kIndices);
 | 
| +  SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
 | 
| +  GetActiveUniformsiv::Result* result =
 | 
| +      static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
 | 
| +  GetActiveUniformsiv cmd;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           GL_UNIFORM_TYPE,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetActiveUniformsiv(
 | 
| +                  kServiceProgramId, kCount, _, GL_UNIFORM_TYPE, _))
 | 
| +      .WillOnce(SetArrayArgument<4>(kResults, kResults + kCount))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_INVALID_VALUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  result->size = 0;
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->GetNumResults());
 | 
| +  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivResultNotInitFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const GLuint kIndices[] = { 1, 2 };
 | 
| +  const size_t kCount = arraysize(kIndices);
 | 
| +  SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
 | 
| +  GetActiveUniformsiv::Result* result =
 | 
| +      static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
 | 
| +  GetActiveUniformsiv cmd;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           GL_UNIFORM_TYPE,
 | 
| +           kSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  result->size = 1976;  // Any value other than 0.
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivBadSharedMemoryFails) {
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const GLuint kIndices[] = { 1, 2 };
 | 
| +  const size_t kCount = arraysize(kIndices);
 | 
| +  SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
 | 
| +  GetActiveUniformsiv::Result* result =
 | 
| +      static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
 | 
| +  GetActiveUniformsiv cmd;
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  result->size = 0;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           GL_UNIFORM_TYPE,
 | 
| +           kInvalidSharedMemoryId,
 | 
| +           kSharedMemoryOffset);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +  result->size = 0;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kBucketId,
 | 
| +           GL_UNIFORM_TYPE,
 | 
| +           kSharedMemoryId,
 | 
| +           kInvalidSharedMemoryOffset);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
|  TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogValidArgs) {
 | 
|    const char* kInfo = "hello";
 | 
|    const uint32 kBucketId = 123;
 | 
| @@ -790,13 +1345,13 @@ TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogValidArgs) {
 | 
|    EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _));
 | 
|    EXPECT_CALL(*gl_, CompileShader(kServiceShaderId));
 | 
|    EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _))
 | 
| -      .WillOnce(SetArgumentPointee<2>(GL_FALSE))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_FALSE))
 | 
|        .RetiresOnSaturation();
 | 
|    EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_INFO_LOG_LENGTH, _))
 | 
| -      .WillOnce(SetArgumentPointee<2>(strlen(kInfo) + 1))
 | 
| +      .WillOnce(SetArgPointee<2>(strlen(kInfo) + 1))
 | 
|        .RetiresOnSaturation();
 | 
|    EXPECT_CALL(*gl_, GetShaderInfoLog(kServiceShaderId, strlen(kInfo) + 1, _, _))
 | 
| -      .WillOnce(DoAll(SetArgumentPointee<2>(strlen(kInfo)),
 | 
| +      .WillOnce(DoAll(SetArgPointee<2>(strlen(kInfo)),
 | 
|                        SetArrayArgument<3>(kInfo, kInfo + strlen(kInfo) + 1)));
 | 
|    compile_cmd.Init(client_shader_id_);
 | 
|    cmd.Init(client_shader_id_, kBucketId);
 | 
| @@ -818,15 +1373,168 @@ TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogInvalidArgs) {
 | 
|    EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
|  }
 | 
|  
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingSucceeds) {
 | 
| +  const GLuint kIndex = 1;
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const char kName[] = "HolyCow";
 | 
| +  const GLsizei kBufferSize = static_cast<GLsizei>(strlen(kName) + 1);
 | 
| +  const GLsizei kSize = 2;
 | 
| +  const GLenum kType = GL_FLOAT_VEC2;
 | 
| +  GetTransformFeedbackVarying cmd;
 | 
| +  typedef GetTransformFeedbackVarying::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->success = 0;
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId,
 | 
| +                                 GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, _))
 | 
| +      .WillOnce(SetArgPointee<2>(kBufferSize))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetTransformFeedbackVarying(
 | 
| +                  kServiceProgramId, kIndex, _, _, _, _, _))
 | 
| +      .WillOnce(DoAll(SetArgPointee<3>(kBufferSize - 1),
 | 
| +                      SetArgPointee<4>(kSize),
 | 
| +                      SetArgPointee<5>(kType),
 | 
| +                      SetArrayArgument<6>(kName, kName + kBufferSize)))
 | 
| +      .RetiresOnSaturation();
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kIndex,
 | 
| +           kBucketId,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_NE(0, result->success);
 | 
| +  EXPECT_EQ(kSize, static_cast<GLsizei>(result->size));
 | 
| +  EXPECT_EQ(kType, static_cast<GLenum>(result->type));
 | 
| +  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +  CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
 | 
| +  ASSERT_TRUE(bucket != NULL);
 | 
| +  EXPECT_EQ(
 | 
| +      0, memcmp(bucket->GetData(0, bucket->size()), kName, bucket->size()));
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(false);
 | 
| +  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingNotInitFails) {
 | 
| +  const GLuint kIndex = 1;
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  GetTransformFeedbackVarying cmd;
 | 
| +  typedef GetTransformFeedbackVarying::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->success = 1;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kIndex,
 | 
| +           kBucketId,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingBadProgramFails) {
 | 
| +  const GLuint kIndex = 1;
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  GetTransformFeedbackVarying cmd;
 | 
| +  typedef GetTransformFeedbackVarying::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->success = 0;
 | 
| +  cmd.Init(kInvalidClientId,
 | 
| +           kIndex,
 | 
| +           kBucketId,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->success);
 | 
| +  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingBadParamsFails) {
 | 
| +  const GLuint kIndex = 1;
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  const GLsizei kBufferSize = 10;
 | 
| +  GetTransformFeedbackVarying cmd;
 | 
| +  typedef GetTransformFeedbackVarying::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->success = 0;
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kIndex,
 | 
| +           kBucketId,
 | 
| +           shared_memory_id_,
 | 
| +           shared_memory_offset_);
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId,
 | 
| +                                 GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, _))
 | 
| +      .WillOnce(SetArgPointee<2>(kBufferSize))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +      .WillOnce(Return(GL_NO_ERROR))
 | 
| +      .WillOnce(Return(GL_INVALID_VALUE))
 | 
| +      .RetiresOnSaturation();
 | 
| +  EXPECT_CALL(*gl_,
 | 
| +              GetTransformFeedbackVarying(
 | 
| +                  kServiceProgramId, kIndex, _, _, _, _, _))
 | 
| +      .Times(1)
 | 
| +      .RetiresOnSaturation();
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(0, result->success);
 | 
| +  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 | 
| +}
 | 
| +
 | 
| +TEST_P(GLES2DecoderWithShaderTest,
 | 
| +       GetTransformFeedbackVaryingBadSharedMemoryFails) {
 | 
| +  const GLuint kIndex = 1;
 | 
| +  const uint32 kBucketId = 123;
 | 
| +  GetTransformFeedbackVarying cmd;
 | 
| +  typedef GetTransformFeedbackVarying::Result Result;
 | 
| +  Result* result = static_cast<Result*>(shared_memory_address_);
 | 
| +  result->success = 0;
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kIndex,
 | 
| +           kBucketId,
 | 
| +           kInvalidSharedMemoryId,
 | 
| +           shared_memory_offset_);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +  cmd.Init(client_program_id_,
 | 
| +           kIndex,
 | 
| +           kBucketId,
 | 
| +           shared_memory_id_,
 | 
| +           kInvalidSharedMemoryOffset);
 | 
| +  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
|  TEST_P(GLES2DecoderTest, CompileShaderValidArgs) {
 | 
| +  // Compile shader should not actually call any GL calls yet.
 | 
| +  CompileShader cmd;
 | 
| +  cmd.Init(client_shader_id_);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +
 | 
| +  // Getting the shader compilation state should trigger the actual GL calls.
 | 
|    EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _));
 | 
|    EXPECT_CALL(*gl_, CompileShader(kServiceShaderId));
 | 
|    EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _))
 | 
| -      .WillOnce(SetArgumentPointee<2>(GL_TRUE))
 | 
| +      .WillOnce(SetArgPointee<2>(GL_TRUE))
 | 
|        .RetiresOnSaturation();
 | 
| -  CompileShader cmd;
 | 
| -  cmd.Init(client_shader_id_);
 | 
| -  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_CALL(*gl_, GetError())
 | 
| +        .WillOnce(Return(GL_NO_ERROR))
 | 
| +        .WillOnce(Return(GL_NO_ERROR))
 | 
| +        .RetiresOnSaturation();
 | 
| +
 | 
| +  GetShaderiv status_cmd;
 | 
| +  status_cmd.Init(client_shader_id_, GL_COMPILE_STATUS,
 | 
| +                  kSharedMemoryId, kSharedMemoryOffset);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(status_cmd));
 | 
|  }
 | 
|  
 | 
|  TEST_P(GLES2DecoderTest, CompileShaderInvalidArgs) {
 | 
| @@ -1178,6 +1886,18 @@ TEST_P(GLES2DecoderWithShaderTest, GetUniformLocationInvalidArgs) {
 | 
|    EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
 | 
|  }
 | 
|  
 | 
| +TEST_P(GLES2DecoderWithShaderTest, UniformBlockBindingValidArgs) {
 | 
| +  EXPECT_CALL(*gl_, UniformBlockBinding(kServiceProgramId, 2, 3));
 | 
| +  SpecializedSetup<cmds::UniformBlockBinding, 0>(true);
 | 
| +  cmds::UniformBlockBinding cmd;
 | 
| +  cmd.Init(client_program_id_, 2, 3);
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(true);
 | 
| +  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 | 
| +  EXPECT_EQ(GL_NO_ERROR, GetGLError());
 | 
| +  decoder_->set_unsafe_es3_apis_enabled(false);
 | 
| +  EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
 | 
| +}
 | 
| +
 | 
|  TEST_P(GLES2DecoderWithShaderTest, BindUniformLocationCHROMIUMBucket) {
 | 
|    const uint32 kBucketId = 123;
 | 
|    const GLint kLocation = 2;
 | 
| 
 |