// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include <stddef.h>
#include <stdint.h>
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/context_state.h"
#include "gpu/command_buffer/service/gl_surface_mock.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
#include "gpu/command_buffer/service/mocks.h"
#include "gpu/command_buffer/service/program_manager.h"
#include "gpu/command_buffer/service/test_helper.h"
#include "gpu/config/gpu_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_mock.h"
#include "ui/gl/gl_surface_stub.h"
#if !defined(GL_DEPTH24_STENCIL8)
#define GL_DEPTH24_STENCIL8 0x88F0
#endif
using ::gl::MockGLInterface;
using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::MatcherCast;
using ::testing::Mock;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SetArrayArgument;
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::StrictMock;
namespace gpu {
namespace gles2 {
TEST_P(GLES2DecoderWithShaderTest, GetProgramInfoCHROMIUMValidArgs) {
const uint32_t kBucketId = 123;
cmds::GetProgramInfoCHROMIUM cmd;
cmd.Init(client_program_id_, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
EXPECT_GT(bucket->size(), 0u);
}
TEST_P(GLES2DecoderWithShaderTest, GetProgramInfoCHROMIUMInvalidArgs) {
const uint32_t kBucketId = 123;
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
EXPECT_TRUE(bucket == nullptr);
cmds::GetProgramInfoCHROMIUM cmd;
cmd.Init(kInvalidClientId, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(sizeof(ProgramInfoHeader), bucket->size());
ProgramInfoHeader* info =
bucket->GetDataAs<ProgramInfoHeader*>(0, sizeof(ProgramInfoHeader));
ASSERT_TRUE(info != 0);
EXPECT_EQ(0u, info->link_status);
EXPECT_EQ(0u, info->num_attribs);
EXPECT_EQ(0u, info->num_uniforms);
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformBlocksCHROMIUMValidArgs) {
const uint32_t kBucketId = 123;
cmds::GetUniformBlocksCHROMIUM 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_UNIFORM_BLOCKS, _))
.WillOnce(SetArgPointee<2>(0))
.RetiresOnSaturation();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
EXPECT_EQ(sizeof(UniformBlocksHeader), bucket->size());
UniformBlocksHeader* header =
bucket->GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
EXPECT_TRUE(header != nullptr);
EXPECT_EQ(0u, header->num_uniform_blocks);
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformBlocksCHROMIUMInvalidArgs) {
const uint32_t kBucketId = 123;
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
EXPECT_TRUE(bucket == nullptr);
cmds::GetUniformBlocksCHROMIUM cmd;
cmd.Init(kInvalidClientId, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(sizeof(UniformBlocksHeader), bucket->size());
UniformBlocksHeader* header =
bucket->GetDataAs<UniformBlocksHeader*>(0, sizeof(UniformBlocksHeader));
ASSERT_TRUE(header != nullptr);
EXPECT_EQ(0u, header->num_uniform_blocks);
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformsES3CHROMIUMValidArgs) {
const uint32_t kBucketId = 123;
cmds::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();
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 != nullptr);
EXPECT_EQ(0u, header->num_uniforms);
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformsES3CHROMIUMInvalidArgs) {
const uint32_t kBucketId = 123;
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
EXPECT_TRUE(bucket == nullptr);
cmds::GetUniformsES3CHROMIUM cmd;
cmd.Init(kInvalidClientId, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(sizeof(UniformsES3Header), bucket->size());
UniformsES3Header* header =
bucket->GetDataAs<UniformsES3Header*>(0, sizeof(UniformsES3Header));
ASSERT_TRUE(header != nullptr);
EXPECT_EQ(0u, header->num_uniforms);
}
TEST_P(GLES3DecoderWithShaderTest,
GetTransformFeedbackVaryingsCHROMIUMValidArgs) {
const uint32_t kBucketId = 123;
cmds::GetTransformFeedbackVaryingsCHROMIUM cmd;
cmd.Init(client_program_id_, kBucketId);
EXPECT_CALL(*(gl_.get()),
GetProgramiv(kServiceProgramId,
GL_TRANSFORM_FEEDBACK_BUFFER_MODE,
_))
.WillOnce(SetArgPointee<2>(GL_INTERLEAVED_ATTRIBS))
.RetiresOnSaturation();
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();
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 != nullptr);
EXPECT_EQ(static_cast<uint32_t>(GL_INTERLEAVED_ATTRIBS),
header->transform_feedback_buffer_mode);
EXPECT_EQ(0u, header->num_transform_feedback_varyings);
}
TEST_P(GLES3DecoderWithShaderTest,
GetTransformFeedbackVaryingsCHROMIUMInvalidArgs) {
const uint32_t kBucketId = 123;
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
EXPECT_TRUE(bucket == nullptr);
cmds::GetTransformFeedbackVaryingsCHROMIUM cmd;
cmd.Init(kInvalidClientId, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(sizeof(TransformFeedbackVaryingsHeader), bucket->size());
TransformFeedbackVaryingsHeader* header =
bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(
0, sizeof(TransformFeedbackVaryingsHeader));
ASSERT_TRUE(header != nullptr);
EXPECT_EQ(0u, header->num_transform_feedback_varyings);
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformivSucceeds) {
auto* result =
static_cast<cmds::GetUniformiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformiv cmd;
cmd.Init(client_program_id_, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformiv(kServiceProgramId, kUniform2RealLocation, _))
.Times(1);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GLES2Util::GetElementCountForUniformType(kUniform2Type),
static_cast<uint32_t>(result->GetNumResults()));
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformivArrayElementSucceeds) {
auto* result =
static_cast<cmds::GetUniformiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformiv cmd;
cmd.Init(client_program_id_, kUniform2ElementFakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_,
GetUniformiv(kServiceProgramId, kUniform2ElementRealLocation, _))
.Times(1);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GLES2Util::GetElementCountForUniformType(kUniform2Type),
static_cast<uint32_t>(result->GetNumResults()));
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformivBadProgramFails) {
auto* result =
static_cast<cmds::GetUniformiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformiv cmd;
// non-existant program
cmd.Init(kInvalidClientId, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformiv(_, _, _)).Times(0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// Valid id that is not a program. The GL spec requires a different error for
// this case.
#if GLES2_TEST_SHADER_VS_PROGRAM_IDS
result->size = kInitialResult;
cmd.Init(client_shader_id_, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS
// Unlinked program
EXPECT_CALL(*gl_, CreateProgram())
.Times(1)
.WillOnce(Return(kNewServiceId))
.RetiresOnSaturation();
cmds::CreateProgram cmd2;
cmd2.Init(kNewClientId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
result->size = kInitialResult;
cmd.Init(kNewClientId, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformivBadLocationFails) {
auto* result =
static_cast<cmds::GetUniformiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformiv cmd;
// invalid location
cmd.Init(client_program_id_, kInvalidUniformLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformiv(_, _, _)).Times(0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformivBadSharedMemoryFails) {
cmds::GetUniformiv cmd;
cmd.Init(client_program_id_,
kUniform2FakeLocation,
kInvalidSharedMemoryId,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformiv(_, _, _)).Times(0);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, kUniform2FakeLocation, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformuivSucceeds) {
auto* result =
static_cast<cmds::GetUniformuiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformuiv cmd;
cmd.Init(client_program_id_, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformuiv(kServiceProgramId, kUniform2RealLocation, _))
.Times(1);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GLES2Util::GetElementCountForUniformType(kUniform2Type),
static_cast<uint32_t>(result->GetNumResults()));
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformuivArrayElementSucceeds) {
auto* result =
static_cast<cmds::GetUniformuiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformuiv cmd;
cmd.Init(client_program_id_, kUniform2ElementFakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_,
GetUniformuiv(kServiceProgramId, kUniform2ElementRealLocation, _))
.Times(1);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GLES2Util::GetElementCountForUniformType(kUniform2Type),
static_cast<uint32_t>(result->GetNumResults()));
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformuivBadProgramFails) {
auto* result =
static_cast<cmds::GetUniformuiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformuiv cmd;
// non-existant program
cmd.Init(kInvalidClientId, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformuiv(_, _, _)).Times(0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// Valid id that is not a program. The GL spec requires a different error for
// this case.
#if GLES2_TEST_SHADER_VS_PROGRAM_IDS
result->size = kInitialResult;
cmd.Init(client_shader_id_, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS
// Unlinked program
EXPECT_CALL(*gl_, CreateProgram())
.Times(1)
.WillOnce(Return(kNewServiceId))
.RetiresOnSaturation();
cmds::CreateProgram cmd2;
cmd2.Init(kNewClientId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
result->size = kInitialResult;
cmd.Init(kNewClientId, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformuivBadLocationFails) {
auto* result =
static_cast<cmds::GetUniformuiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformuiv cmd;
// invalid location
cmd.Init(client_program_id_, kInvalidUniformLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformuiv(_, _, _)).Times(0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformuivBadSharedMemoryFails) {
cmds::GetUniformuiv cmd;
cmd.Init(client_program_id_,
kUniform2FakeLocation,
kInvalidSharedMemoryId,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformuiv(_, _, _)).Times(0);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, kUniform2FakeLocation, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformfvSucceeds) {
auto* result =
static_cast<cmds::GetUniformfv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformfv cmd;
cmd.Init(client_program_id_, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformfv(kServiceProgramId, kUniform2RealLocation, _))
.Times(1);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GLES2Util::GetElementCountForUniformType(kUniform2Type),
static_cast<uint32_t>(result->GetNumResults()));
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformfvArrayElementSucceeds) {
auto* result =
static_cast<cmds::GetUniformfv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformfv cmd;
cmd.Init(client_program_id_, kUniform2ElementFakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_,
GetUniformfv(kServiceProgramId, kUniform2ElementRealLocation, _))
.Times(1);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GLES2Util::GetElementCountForUniformType(kUniform2Type),
static_cast<uint32_t>(result->GetNumResults()));
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformfvBadProgramFails) {
auto* result =
static_cast<cmds::GetUniformfv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformfv cmd;
// non-existant program
cmd.Init(kInvalidClientId, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformfv(_, _, _)).Times(0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// Valid id that is not a program. The GL spec requires a different error for
// this case.
#if GLES2_TEST_SHADER_VS_PROGRAM_IDS
result->size = kInitialResult;
cmd.Init(client_shader_id_, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS
// Unlinked program
EXPECT_CALL(*gl_, CreateProgram())
.Times(1)
.WillOnce(Return(kNewServiceId))
.RetiresOnSaturation();
cmds::CreateProgram cmd2;
cmd2.Init(kNewClientId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
result->size = kInitialResult;
cmd.Init(kNewClientId, kUniform2FakeLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformfvBadLocationFails) {
auto* result =
static_cast<cmds::GetUniformfv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetUniformfv cmd;
// invalid location
cmd.Init(client_program_id_, kInvalidUniformLocation, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformfv(_, _, _)).Times(0);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformfvBadSharedMemoryFails) {
cmds::GetUniformfv cmd;
cmd.Init(client_program_id_,
kUniform2FakeLocation,
kInvalidSharedMemoryId,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformfv(_, _, _)).Times(0);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, kUniform2FakeLocation, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersSucceeds) {
cmds::GetAttachedShaders cmd;
using Result = cmds::GetAttachedShaders::Result;
auto* result = static_cast<Result*>(shared_memory_address_);
result->size = 0;
EXPECT_CALL(*gl_, GetAttachedShaders(kServiceProgramId, 1, _, _)).WillOnce(
DoAll(SetArgPointee<2>(1), SetArgPointee<3>(kServiceShaderId)));
cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_,
Result::ComputeSize(1).ValueOrDie());
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1, result->GetNumResults());
EXPECT_EQ(client_shader_id_, result->GetData()[0]);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersResultNotInitFail) {
cmds::GetAttachedShaders cmd;
using Result = cmds::GetAttachedShaders::Result;
auto* result = static_cast<Result*>(shared_memory_address_);
result->size = 1;
EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)).Times(0);
cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_,
Result::ComputeSize(1).ValueOrDie());
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersBadProgramFails) {
cmds::GetAttachedShaders cmd;
using Result = cmds::GetAttachedShaders::Result;
auto* result = static_cast<Result*>(shared_memory_address_);
result->size = 0;
EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)).Times(0);
cmd.Init(kInvalidClientId, shared_memory_id_, shared_memory_offset_,
Result::ComputeSize(1).ValueOrDie());
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0U, result->size);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetAttachedShadersBadSharedMemoryFails) {
cmds::GetAttachedShaders cmd;
using Result = cmds::GetAttachedShaders::Result;
cmd.Init(client_program_id_, kInvalidSharedMemoryId, shared_memory_offset_,
Result::ComputeSize(1).ValueOrDie());
EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)).Times(0);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, shared_memory_id_, kInvalidSharedMemoryOffset,
Result::ComputeSize(1).ValueOrDie());
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderManualInitTest, GetShaderPrecisionFormatSucceeds) {
// Force ES underlying implementation to ensure we check the shader precision
// format.
InitState init;
init.gl_version = "OpenGL ES 2.0";
init.bind_generates_resource = true;
InitDecoder(init);
cmds::GetShaderPrecisionFormat cmd;
auto* result = static_cast<cmds::GetShaderPrecisionFormat::Result*>(
shared_memory_address_);
result->success = 0;
const GLint range[2] = {62, 62};
const GLint precision = 16;
EXPECT_CALL(*gl_, GetShaderPrecisionFormat(_, _, _, _))
.WillOnce(DoAll(SetArrayArgument<2>(range, range + 2),
SetArgPointee<3>(precision)))
.RetiresOnSaturation();
cmd.Init(GL_VERTEX_SHADER,
GL_HIGH_FLOAT,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_NE(0, result->success);
EXPECT_EQ(range[0], result->min_range);
EXPECT_EQ(range[1], result->max_range);
EXPECT_EQ(precision, result->precision);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatResultNotInitFails) {
cmds::GetShaderPrecisionFormat cmd;
auto* result = static_cast<cmds::GetShaderPrecisionFormat::Result*>(
shared_memory_address_);
result->success = 1;
// NOTE: GL might not be called. There is no Desktop OpenGL equivalent
cmd.Init(GL_VERTEX_SHADER,
GL_HIGH_FLOAT,
shared_memory_id_,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatBadArgsFails) {
auto* result = static_cast<cmds::GetShaderPrecisionFormat::Result*>(
shared_memory_address_);
result->success = 0;
cmds::GetShaderPrecisionFormat cmd;
cmd.Init(
GL_TEXTURE_2D, GL_HIGH_FLOAT, shared_memory_id_, shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
result->success = 0;
cmd.Init(GL_VERTEX_SHADER,
GL_TEXTURE_2D,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest,
GetShaderPrecisionFormatBadSharedMemoryFails) {
cmds::GetShaderPrecisionFormat cmd;
cmd.Init(GL_VERTEX_SHADER,
GL_HIGH_FLOAT,
kInvalidSharedMemoryId,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(GL_VERTEX_SHADER,
GL_TEXTURE_2D,
shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformSucceeds) {
const GLuint kUniformIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetActiveUniform cmd;
auto* result =
static_cast<cmds::GetActiveUniform::Result*>(shared_memory_address_);
result->success = 0;
cmd.Init(client_program_id_,
kUniformIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_NE(0, result->success);
EXPECT_EQ(kUniform2Size, result->size);
EXPECT_EQ(kUniform2Type, result->type);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(
0,
memcmp(
bucket->GetData(0, bucket->size()), kUniform2Name, bucket->size()));
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformResultNotInitFails) {
const GLuint kUniformIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetActiveUniform cmd;
auto* result =
static_cast<cmds::GetActiveUniform::Result*>(shared_memory_address_);
result->success = 1;
cmd.Init(client_program_id_,
kUniformIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBadProgramFails) {
const GLuint kUniformIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetActiveUniform cmd;
auto* result =
static_cast<cmds::GetActiveUniform::Result*>(shared_memory_address_);
result->success = 0;
cmd.Init(kInvalidClientId,
kUniformIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
#if GLES2_TEST_SHADER_VS_PROGRAM_IDS
result->success = 0;
cmd.Init(client_shader_id_,
kUniformIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBadIndexFails) {
const uint32_t kBucketId = 123;
cmds::GetActiveUniform cmd;
auto* result =
static_cast<cmds::GetActiveUniform::Result*>(shared_memory_address_);
result->success = 0;
cmd.Init(client_program_id_,
kBadUniformIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBadSharedMemoryFails) {
const GLuint kUniformIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetActiveUniform cmd;
cmd.Init(client_program_id_,
kUniformIndex,
kBucketId,
kInvalidSharedMemoryId,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_,
kUniformIndex,
kBucketId,
shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformBlockNameSucceeds) {
const uint32_t kBucketId = 123;
cmds::GetActiveUniformBlockName cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockName::Result*>(
shared_memory_address_);
*result = 0;
cmd.Init(client_program_id_,
0,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
.WillOnce(SetArgPointee<2>(GL_TRUE))
.RetiresOnSaturation();
const char kName[] = "HolyCow";
const GLsizei kMaxLength = strlen(kName) + 1;
EXPECT_CALL(*gl_,
GetProgramiv(kServiceProgramId,
GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, _))
.WillOnce(SetArgPointee<2>(kMaxLength))
.RetiresOnSaturation();
EXPECT_CALL(*gl_,
GetActiveUniformBlockName(kServiceProgramId, 0, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(strlen(kName)),
SetArrayArgument<4>(kName, kName + strlen(kName) + 1)))
.RetiresOnSaturation();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_NE(0, *result);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(0,
memcmp(bucket->GetData(0, bucket->size()), kName, bucket->size()));
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformBlockNameUnlinkedProgram) {
const uint32_t kBucketId = 123;
cmds::GetActiveUniformBlockName cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockName::Result*>(
shared_memory_address_);
*result = 0;
cmd.Init(client_program_id_,
0,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
.WillOnce(SetArgPointee<2>(GL_FALSE))
.RetiresOnSaturation();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, *result);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest,
GetActiveUniformBlockNameResultNotInitFails) {
const uint32_t kBucketId = 123;
cmds::GetActiveUniformBlockName cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockName::Result*>(
shared_memory_address_);
*result = 1;
cmd.Init(client_program_id_,
0,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformBlockNameBadProgramFails) {
const uint32_t kBucketId = 123;
cmds::GetActiveUniformBlockName cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockName::Result*>(
shared_memory_address_);
*result = 0;
cmd.Init(kInvalidClientId,
0,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, *result);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest,
GetActiveUniformBlockNameBadSharedMemoryFails) {
const uint32_t kBucketId = 123;
cmds::GetActiveUniformBlockName cmd;
cmd.Init(client_program_id_,
0,
kBucketId,
kInvalidSharedMemoryId,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_,
0,
kBucketId,
shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformBlockivSucceeds) {
cmds::GetActiveUniformBlockiv cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockiv::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 < std::size(kPname); ++ii) {
result->SetNumResults(0);
cmd.Init(client_program_id_,
0,
kPname[ii],
shared_memory_id_,
shared_memory_offset_);
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();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1, result->GetNumResults());
EXPECT_EQ(GL_NO_ERROR, GetGLError());
EXPECT_EQ(1976, result->GetData()[0]);
}
}
TEST_P(GLES3DecoderWithShaderTest,
GetActiveUniformBlockivSucceedsZeroUniforms) {
cmds::GetActiveUniformBlockiv cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockiv::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))
.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();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformBlockivUnlinkedProgram) {
cmds::GetActiveUniformBlockiv cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockiv::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();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest,
GetActiveUniformBlockivResultNotInitFails) {
cmds::GetActiveUniformBlockiv cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockiv::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_);
EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
.WillOnce(SetArgPointee<2>(GL_TRUE))
.RetiresOnSaturation();
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformBlockivBadProgramFails) {
cmds::GetActiveUniformBlockiv cmd;
auto* result = static_cast<cmds::GetActiveUniformBlockiv::Result*>(
shared_memory_address_);
result->SetNumResults(0);
cmd.Init(kInvalidClientId,
0,
GL_UNIFORM_BLOCK_BINDING,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest,
GetActiveUniformBlockivBadSharedMemoryFails) {
cmds::GetActiveUniformBlockiv cmd;
EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
.WillOnce(SetArgPointee<2>(GL_TRUE))
.WillOnce(SetArgPointee<2>(GL_TRUE))
.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_t kBucketId = 123;
cmds::GetActiveAttrib cmd;
auto* result =
static_cast<cmds::GetActiveAttrib::Result*>(shared_memory_address_);
result->success = 0;
cmd.Init(client_program_id_,
kAttribIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_NE(0, result->success);
EXPECT_EQ(kAttrib2Size, result->size);
EXPECT_EQ(kAttrib2Type, result->type);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(
0,
memcmp(bucket->GetData(0, bucket->size()), kAttrib2Name, bucket->size()));
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribResultNotInitFails) {
const GLuint kAttribIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetActiveAttrib cmd;
auto* result =
static_cast<cmds::GetActiveAttrib::Result*>(shared_memory_address_);
result->success = 1;
cmd.Init(client_program_id_,
kAttribIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribBadProgramFails) {
const GLuint kAttribIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetActiveAttrib cmd;
auto* result =
static_cast<cmds::GetActiveAttrib::Result*>(shared_memory_address_);
result->success = 0;
cmd.Init(kInvalidClientId,
kAttribIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
#if GLES2_TEST_SHADER_VS_PROGRAM_IDS
result->success = 0;
cmd.Init(client_shader_id_,
kAttribIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribBadIndexFails) {
const uint32_t kBucketId = 123;
cmds::GetActiveAttrib cmd;
auto* result =
static_cast<cmds::GetActiveAttrib::Result*>(shared_memory_address_);
result->success = 0;
cmd.Init(client_program_id_,
kBadAttribIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribBadSharedMemoryFails) {
const GLuint kAttribIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetActiveAttrib cmd;
cmd.Init(client_program_id_,
kAttribIndex,
kBucketId,
kInvalidSharedMemoryId,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_,
kAttribIndex,
kBucketId,
shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformIndicesSucceeds) {
const uint32_t kBucketId = 123;
const char kName0[] = "Cow";
const char kName1[] = "Chicken";
const char* kNames[] = { kName0, kName1 };
const size_t kCount = std::size(kNames);
const char kValidStrEnd = 0;
const GLuint kIndices[] = { 1, 2 };
SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
auto* result =
static_cast<cmds::GetUniformIndices::Result*>(shared_memory_address_);
cmds::GetUniformIndices cmd;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
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();
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());
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformIndicesBadProgramFails) {
const uint32_t kBucketId = 123;
const char kName0[] = "Cow";
const char kName1[] = "Chicken";
const char* kNames[] = { kName0, kName1 };
const size_t kCount = std::size(kNames);
const char kValidStrEnd = 0;
SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
auto* result =
static_cast<cmds::GetUniformIndices::Result*>(shared_memory_address_);
cmds::GetUniformIndices cmd;
// None-existant program
cmd.Init(kInvalidClientId, kBucketId, shared_memory_id_, 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, shared_memory_id_,
kSharedMemoryOffset);
result->size = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformIndicesBadParamsFails) {
const uint32_t kBucketId = 123;
const char kName0[] = "Cow";
const char kName1[] = "Chicken";
const char* kNames[] = { kName0, kName1 };
const size_t kCount = std::size(kNames);
const char kValidStrEnd = 0;
const GLuint kIndices[] = { 1, 2 };
SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
auto* result =
static_cast<cmds::GetUniformIndices::Result*>(shared_memory_address_);
cmds::GetUniformIndices cmd;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
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();
result->size = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformIndicesResultNotInitFails) {
const uint32_t kBucketId = 123;
const char kName0[] = "Cow";
const char kName1[] = "Chicken";
const char* kNames[] = { kName0, kName1 };
const size_t kCount = std::size(kNames);
const char kValidStrEnd = 0;
SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
auto* result =
static_cast<cmds::GetUniformIndices::Result*>(shared_memory_address_);
cmds::GetUniformIndices cmd;
result->size = 1976; // Any value other than 0.
cmd.Init(kInvalidClientId, kBucketId, shared_memory_id_, kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformIndicesBadSharedMemoryFails) {
const uint32_t kBucketId = 123;
const char kName0[] = "Cow";
const char kName1[] = "Chicken";
const char* kNames[] = { kName0, kName1 };
const size_t kCount = std::size(kNames);
const char kValidStrEnd = 0;
SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
auto* result =
static_cast<cmds::GetUniformIndices::Result*>(shared_memory_address_);
cmds::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, shared_memory_id_,
kInvalidSharedMemoryOffset);
result->size = 0;
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformsivSucceeds) {
const uint32_t kBucketId = 123;
const GLuint kIndices[] = { 1, 2 };
const GLint kResults[] = { 1976, 321 };
const size_t kCount = std::size(kIndices);
SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
auto* result =
static_cast<cmds::GetActiveUniformsiv::Result*>(shared_memory_address_);
cmds::GetActiveUniformsiv cmd;
cmd.Init(client_program_id_, kBucketId, GL_UNIFORM_TYPE, shared_memory_id_,
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();
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());
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformsivBadProgramFails) {
const uint32_t kBucketId = 123;
const GLuint kIndices[] = { 1, 2 };
const size_t kCount = std::size(kIndices);
SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
auto* result =
static_cast<cmds::GetActiveUniformsiv::Result*>(shared_memory_address_);
cmds::GetActiveUniformsiv cmd;
// None-existant program
cmd.Init(kInvalidClientId, kBucketId, GL_UNIFORM_TYPE, shared_memory_id_,
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, shared_memory_id_,
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(GLES3DecoderWithShaderTest, GetActiveUniformsivBadParamsFails) {
const uint32_t kBucketId = 123;
const GLuint kIndices[] = { 1, 100 };
const size_t kCount = std::size(kIndices);
SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
auto* result =
static_cast<cmds::GetActiveUniformsiv::Result*>(shared_memory_address_);
cmds::GetActiveUniformsiv cmd;
cmd.Init(client_program_id_, kBucketId, GL_UNIFORM_TYPE, shared_memory_id_,
kSharedMemoryOffset);
result->size = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformsivBadPnameFails) {
const uint32_t kBucketId = 123;
const GLuint kIndices[] = { 1, 2 };
const size_t kCount = std::size(kIndices);
SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
auto* result =
static_cast<cmds::GetActiveUniformsiv::Result*>(shared_memory_address_);
cmds::GetActiveUniformsiv cmd;
// GL_UNIFORM_BLOCK_NAME_LENGTH should not be supported.
cmd.Init(client_program_id_, kBucketId, GL_UNIFORM_BLOCK_NAME_LENGTH,
shared_memory_id_, kSharedMemoryOffset);
result->size = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
// Invalid pname
cmd.Init(client_program_id_, kBucketId, 1, shared_memory_id_,
kSharedMemoryOffset);
result->size = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->GetNumResults());
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformsivResultNotInitFails) {
const uint32_t kBucketId = 123;
const GLuint kIndices[] = { 1, 2 };
const size_t kCount = std::size(kIndices);
SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
auto* result =
static_cast<cmds::GetActiveUniformsiv::Result*>(shared_memory_address_);
cmds::GetActiveUniformsiv cmd;
cmd.Init(client_program_id_, kBucketId, GL_UNIFORM_TYPE, shared_memory_id_,
kSharedMemoryOffset);
result->size = 1976; // Any value other than 0.
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetActiveUniformsivBadSharedMemoryFails) {
const uint32_t kBucketId = 123;
const GLuint kIndices[] = { 1, 2 };
const size_t kCount = std::size(kIndices);
SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
auto* result =
static_cast<cmds::GetActiveUniformsiv::Result*>(shared_memory_address_);
cmds::GetActiveUniformsiv cmd;
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, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogValidArgs) {
const uint32_t kBucketId = 123;
const char kSource0[] = "void main() { gl_Position = vec4(1.0); }";
const char* kSource[] = {kSource0};
const char kValidStrEnd = 0;
SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd);
cmds::ShaderSourceBucket bucket_cmd;
bucket_cmd.Init(client_shader_id_, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(bucket_cmd));
ClearSharedMemory();
const char* kInfo = "hello";
cmds::CompileShader compile_cmd;
cmds::GetShaderInfoLog cmd;
EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _));
EXPECT_CALL(*gl_, CompileShader(kServiceShaderId));
EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _))
.WillOnce(SetArgPointee<2>(GL_FALSE))
.RetiresOnSaturation();
EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_INFO_LOG_LENGTH, _))
.WillOnce(SetArgPointee<2>(strlen(kInfo) + 1))
.RetiresOnSaturation();
EXPECT_CALL(*gl_, GetShaderInfoLog(kServiceShaderId, strlen(kInfo) + 1, _, _))
.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);
EXPECT_EQ(error::kNoError, ExecuteCmd(compile_cmd));
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(strlen(kInfo) + 1, bucket->size());
EXPECT_EQ(0,
memcmp(bucket->GetData(0, bucket->size()), kInfo, bucket->size()));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogInvalidArgs) {
const uint32_t kBucketId = 123;
cmds::GetShaderInfoLog cmd;
cmd.Init(kInvalidClientId, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetTransformFeedbackVaryingSucceeds) {
const GLuint kIndex = 1;
const uint32_t kBucketId = 123;
const char kName[] = "HolyCow";
const GLsizei kNumVaryings = 2;
const GLsizei kBufferSize = static_cast<GLsizei>(strlen(kName) + 1);
const GLsizei kSize = 2;
const GLenum kType = GL_FLOAT_VEC2;
cmds::GetTransformFeedbackVarying cmd;
auto* result = static_cast<cmds::GetTransformFeedbackVarying::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_VARYINGS, _))
.WillOnce(SetArgPointee<2>(kNumVaryings))
.RetiresOnSaturation();
EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId,
GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, _))
.WillOnce(SetArgPointee<2>(kBufferSize))
.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_);
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 != nullptr);
EXPECT_EQ(
0, memcmp(bucket->GetData(0, bucket->size()), kName, bucket->size()));
}
TEST_P(GLES3DecoderWithShaderTest, GetTransformFeedbackVaryingNotInitFails) {
const GLuint kIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetTransformFeedbackVarying cmd;
auto* result = static_cast<cmds::GetTransformFeedbackVarying::Result*>(
shared_memory_address_);
result->success = 1;
cmd.Init(client_program_id_,
kIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetTransformFeedbackVaryingBadProgramFails) {
const GLuint kIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetTransformFeedbackVarying cmd;
auto* result = static_cast<cmds::GetTransformFeedbackVarying::Result*>(
shared_memory_address_);
result->success = 0;
cmd.Init(kInvalidClientId,
kIndex,
kBucketId,
shared_memory_id_,
shared_memory_offset_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, GetTransformFeedbackVaryingBadParamsFails) {
const GLuint kIndex = 1;
const uint32_t kBucketId = 123;
const GLsizei kNumVaryings = 1;
cmds::GetTransformFeedbackVarying cmd;
auto* result = static_cast<cmds::GetTransformFeedbackVarying::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_VARYINGS, _))
.WillOnce(SetArgPointee<2>(kNumVaryings))
.RetiresOnSaturation();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0, result->success);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest,
GetTransformFeedbackVaryingBadSharedMemoryFails) {
const GLuint kIndex = 1;
const uint32_t kBucketId = 123;
cmds::GetTransformFeedbackVarying cmd;
auto* result = static_cast<cmds::GetTransformFeedbackVarying::Result*>(
shared_memory_address_);
result->success = 0;
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) {
// ShaderSource should not actually call any GL calls yet.
const uint32_t kInBucketId = 123;
const char kSource0[] = "void main() { gl_Position = vec4(1.0); }";
const char* kSource[] = {kSource0};
const char kValidStrEnd = 0;
SetBucketAsCStrings(kInBucketId, 1, kSource, 1, kValidStrEnd);
cmds::ShaderSourceBucket bucket_cmd;
bucket_cmd.Init(client_shader_id_, kInBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(bucket_cmd));
ClearSharedMemory();
// Compile shader should not actually call any GL calls yet.
cmds::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(SetArgPointee<2>(GL_TRUE))
.RetiresOnSaturation();
EXPECT_CALL(*gl_, GetError())
.WillOnce(Return(GL_NO_ERROR))
.WillOnce(Return(GL_NO_ERROR))
.RetiresOnSaturation();
auto* result =
static_cast<cmds::GetShaderiv::Result*>(shared_memory_address_);
result->size = 0;
cmds::GetShaderiv status_cmd;
status_cmd.Init(client_shader_id_, GL_COMPILE_STATUS, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(status_cmd));
EXPECT_EQ(GL_TRUE, *result->GetData());
}
TEST_P(GLES2DecoderTest, CompileShaderInvalidArgs) {
cmds::CompileShader cmd;
cmd.Init(kInvalidClientId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
#if GLES2_TEST_SHADER_VS_PROGRAM_IDS
cmd.Init(client_program_id_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS
}
TEST_P(GLES2DecoderTest, ShaderSourceBucketAndGetShaderSourceValidArgs) {
const uint32_t kInBucketId = 123;
const uint32_t kOutBucketId = 125;
const char kSource0[] = "hello";
const char* kSource[] = { kSource0 };
const char kValidStrEnd = 0;
SetBucketAsCStrings(kInBucketId, 1, kSource, 1, kValidStrEnd);
cmds::ShaderSourceBucket cmd;
cmd.Init(client_shader_id_, kInBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
ClearSharedMemory();
cmds::GetShaderSource get_cmd;
get_cmd.Init(client_shader_id_, kOutBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(get_cmd));
CommonDecoder::Bucket* bucket = decoder_->GetBucket(kOutBucketId);
ASSERT_TRUE(bucket != nullptr);
EXPECT_EQ(sizeof(kSource0), bucket->size());
EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()),
kSource0, bucket->size()));
}
#if GLES2_TEST_SHADER_VS_PROGRAM_IDS
TEST_P(GLES2DecoderTest, ShaderSourceBucketWithProgramId) {
const uint32_t kBucketId = 123;
const char kSource0[] = "hello";
const char* kSource[] = { kSource0 };
const char kValidStrEnd = 0;
SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd);
cmds::ShaderSourceBucket cmd;
cmd.Init(client_program_id_, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS
TEST_P(GLES2DecoderTest, ShaderSourceStripComments) {
const uint32_t kInBucketId = 123;
const char kSource0[] = "hello/*te\ast*/world//a\ab";
const char* kSource[] = { kSource0 };
const char kValidStrEnd = 0;
SetBucketAsCStrings(kInBucketId, 1, kSource, 1, kValidStrEnd);
cmds::ShaderSourceBucket cmd;
cmd.Init(client_shader_id_, kInBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, Uniform1iValidArgs) {
EXPECT_CALL(*gl_, Uniform1i(kUniform1RealLocation, 2));
cmds::Uniform1i cmd;
cmd.Init(kUniform1FakeLocation, 2);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, Uniform1uiValidArgs) {
EXPECT_CALL(*gl_, Uniform1uiv(kUniform4RealLocation, 1, _));
cmds::Uniform1ui cmd;
cmd.Init(kUniform4FakeLocation, 2);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, Uniform1ivImmediateValidArgs) {
auto& cmd = *GetImmediateAs<cmds::Uniform1ivImmediate>();
GLint temp[1] = {
0,
};
EXPECT_CALL(*gl_,
Uniform1iv(kUniform1RealLocation, 1, PointsToArray(temp, 1)));
cmd.Init(kUniform1FakeLocation, 1, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
}
TEST_P(GLES2DecoderWithShaderTest, Uniform1ivImmediateInvalidValidArgs) {
EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0);
auto& cmd = *GetImmediateAs<cmds::Uniform1ivImmediate>();
GLint temp[1 * 2] = {
0,
};
cmd.Init(kUniform1FakeLocation, 2, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, Uniform1ivZeroCount) {
EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0);
auto& cmd = *GetImmediateAs<cmds::Uniform1ivImmediate>();
GLint temp = 0;
cmd.Init(kUniform1FakeLocation, 0, &temp);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, Uniform1iSamplerIsLmited) {
EXPECT_CALL(*gl_, Uniform1i(_, _)).Times(0);
cmds::Uniform1i cmd;
cmd.Init(kUniform1FakeLocation, kNumTextureUnits);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, Uniform1ivSamplerIsLimited) {
EXPECT_CALL(*gl_, Uniform1iv(_, _, _)).Times(0);
auto& cmd = *GetImmediateAs<cmds::Uniform1ivImmediate>();
GLint temp[] = {kNumTextureUnits};
cmd.Init(kUniform1FakeLocation, 1, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, Uniform1ivArray) {
auto& cmd = *GetImmediateAs<cmds::Uniform1ivImmediate>();
GLint temp[3] = {
0, 1, 2,
};
EXPECT_CALL(*gl_,
Uniform1iv(kUniform8RealLocation, 2, PointsToArray(temp, 2)));
cmd.Init(kUniform8FakeLocation, 2, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
EXPECT_CALL(*gl_,
Uniform1iv(kUniform8RealLocation, 2, PointsToArray(temp, 2)));
cmd.Init(kUniform8FakeLocation, 3, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform1uivImmediateValidArgs) {
auto& cmd = *GetImmediateAs<cmds::Uniform1uivImmediate>();
GLuint temp[1] = {
0,
};
EXPECT_CALL(*gl_,
Uniform1uiv(kUniform4RealLocation, 1, PointsToArray(temp, 1)));
cmd.Init(kUniform4FakeLocation, 1, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform1uivImmediateInvalidType) {
EXPECT_CALL(*gl_, Uniform1uiv(_, _, _)).Times(0);
auto& cmd = *GetImmediateAs<cmds::Uniform1uivImmediate>();
GLuint temp[1 * 2] = {
0,
};
// uniform1 is SAMPLER type.
cmd.Init(kUniform1FakeLocation, 1, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform1uivZeroCount) {
EXPECT_CALL(*gl_, Uniform1uiv(_, _, _)).Times(0);
auto& cmd = *GetImmediateAs<cmds::Uniform1uivImmediate>();
GLuint temp = 0;
cmd.Init(kUniform4FakeLocation, 0, &temp);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform2uiValidArgs) {
EXPECT_CALL(*gl_, Uniform2uiv(kUniform5RealLocation, 1, _));
cmds::Uniform2ui cmd;
cmd.Init(kUniform5FakeLocation, 2, 3);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform2uivImmediateValidArgs) {
auto& cmd = *GetImmediateAs<cmds::Uniform2uivImmediate>();
GLuint temp[2 * 1] = {
0,
};
EXPECT_CALL(*gl_,
Uniform2uiv(kUniform5RealLocation, 1, PointsToArray(temp, 2)));
cmd.Init(kUniform5FakeLocation, 1, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform3uiValidArgs) {
EXPECT_CALL(*gl_, Uniform3uiv(kUniform6RealLocation, 1, _));
cmds::Uniform3ui cmd;
cmd.Init(kUniform6FakeLocation, 2, 3, 4);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform3uivImmediateValidArgs) {
auto& cmd = *GetImmediateAs<cmds::Uniform3uivImmediate>();
GLuint temp[3 * 1] = {
0,
};
EXPECT_CALL(*gl_,
Uniform3uiv(kUniform6RealLocation, 1, PointsToArray(temp, 3)));
cmd.Init(kUniform6FakeLocation, 1, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform4uiValidArgs) {
EXPECT_CALL(*gl_, Uniform4uiv(kUniform7RealLocation, 1, _));
cmds::Uniform4ui cmd;
cmd.Init(kUniform7FakeLocation, 2, 3, 4, 5);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES3DecoderWithShaderTest, Uniform4uivImmediateValidArgs) {
auto& cmd = *GetImmediateAs<cmds::Uniform4uivImmediate>();
GLuint temp[4 * 1] = {
0,
};
EXPECT_CALL(*gl_,
Uniform4uiv(kUniform7RealLocation, 1, PointsToArray(temp, 4)));
cmd.Init(kUniform7FakeLocation, 1, &temp[0]);
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderTest, BindAttribLocationBucket) {
const uint32_t kBucketId = 123;
const GLint kLocation = 2;
const char* kName = "testing";
SetBucketAsCString(kBucketId, kName);
cmds::BindAttribLocationBucket cmd;
cmd.Init(client_program_id_, kLocation, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderTest, BindAttribLocationBucketInvalidArgs) {
const uint32_t kBucketId = 123;
const GLint kLocation = 2;
const char* kName = "testing";
EXPECT_CALL(*gl_, BindAttribLocation(_, _, _)).Times(0);
cmds::BindAttribLocationBucket cmd;
// check bucket does not exist.
cmd.Init(client_program_id_, kLocation, kBucketId);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
// check bucket is empty.
SetBucketAsCString(kBucketId, nullptr);
cmd.Init(client_program_id_, kLocation, kBucketId);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
// Check bad program id
SetBucketAsCString(kBucketId, kName);
cmd.Init(kInvalidClientId, kLocation, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, GetAttribLocation) {
const uint32_t kBucketId = 123;
const char* kNonExistentName = "foobar";
auto* result = GetSharedMemoryAs<cmds::GetAttribLocation::Result*>();
SetBucketAsCString(kBucketId, kAttrib2Name);
*result = -1;
cmds::GetAttribLocation cmd;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(kAttrib2Location, *result);
SetBucketAsCString(kBucketId, kNonExistentName);
*result = -1;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
}
TEST_P(GLES2DecoderWithShaderTest, GetAttribLocationInvalidArgs) {
const uint32_t kBucketId = 123;
auto* result = GetSharedMemoryAs<cmds::GetAttribLocation::Result*>();
*result = -1;
cmds::GetAttribLocation cmd;
// Check no bucket
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
// Check bad program id.
SetBucketAsCString(kBucketId, kAttrib2Name);
cmd.Init(kInvalidClientId, kBucketId, shared_memory_id_, kSharedMemoryOffset);
*result = -1;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// Check bad memory
cmd.Init(client_program_id_,
kBucketId,
kInvalidSharedMemoryId,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetFragDataLocation) {
const uint32_t kBucketId = 123;
auto* result = GetSharedMemoryAs<cmds::GetFragDataLocation::Result*>();
SetBucketAsCString(kBucketId, kOutputVariable1NameESSL3);
*result = -1;
cmds::GetFragDataLocation cmd;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(static_cast<GLint>(kOutputVariable1ColorName), *result);
}
TEST_P(GLES3DecoderWithShaderTest, GetFragDataLocationInvalidArgs) {
const uint32_t kBucketId = 123;
auto* result = GetSharedMemoryAs<cmds::GetFragDataLocation::Result*>();
*result = -1;
cmds::GetFragDataLocation cmd;
// Check no bucket
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
// Check bad program id.
const char* kName = "color";
SetBucketAsCString(kBucketId, kName);
cmd.Init(kInvalidClientId, kBucketId, shared_memory_id_, kSharedMemoryOffset);
*result = -1;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// Check bad memory
cmd.Init(client_program_id_,
kBucketId,
kInvalidSharedMemoryId,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformBlockIndex) {
const uint32_t kBucketId = 123;
const GLuint kIndex = 10;
const char* kName = "color";
auto* result = GetSharedMemoryAs<cmds::GetUniformBlockIndex::Result*>();
SetBucketAsCString(kBucketId, kName);
*result = GL_INVALID_INDEX;
cmds::GetUniformBlockIndex cmd;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_CALL(*gl_, GetUniformBlockIndex(kServiceProgramId, StrEq(kName)))
.WillOnce(Return(kIndex))
.RetiresOnSaturation();
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(kIndex, *result);
}
TEST_P(GLES3DecoderWithShaderTest, GetUniformBlockIndexInvalidArgs) {
const uint32_t kBucketId = 123;
auto* result = GetSharedMemoryAs<cmds::GetUniformBlockIndex::Result*>();
*result = GL_INVALID_INDEX;
cmds::GetUniformBlockIndex cmd;
// Check no bucket
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_INDEX, *result);
// Check bad program id.
const char* kName = "color";
SetBucketAsCString(kBucketId, kName);
cmd.Init(kInvalidClientId, kBucketId, shared_memory_id_, kSharedMemoryOffset);
*result = GL_INVALID_INDEX;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_INDEX, *result);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// Check bad memory
cmd.Init(client_program_id_,
kBucketId,
kInvalidSharedMemoryId,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformLocation) {
const uint32_t kBucketId = 123;
const char* kNonExistentName = "foobar";
auto* result = GetSharedMemoryAs<cmds::GetUniformLocation::Result*>();
SetBucketAsCString(kBucketId, kUniform2Name);
*result = -1;
cmds::GetUniformLocation cmd;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(kUniform2FakeLocation, *result);
SetBucketAsCString(kBucketId, kNonExistentName);
*result = -1;
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
}
TEST_P(GLES2DecoderWithShaderTest, GetUniformLocationInvalidArgs) {
const uint32_t kBucketId = 123;
auto* result = GetSharedMemoryAs<cmds::GetUniformLocation::Result*>();
*result = -1;
cmds::GetUniformLocation cmd;
// Check no bucket
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
// Check bad program id.
SetBucketAsCString(kBucketId, kUniform2Name);
cmd.Init(kInvalidClientId, kBucketId, shared_memory_id_, kSharedMemoryOffset);
*result = -1;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(-1, *result);
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// Check bad memory
cmd.Init(client_program_id_,
kBucketId,
kInvalidSharedMemoryId,
kSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(client_program_id_, kBucketId, shared_memory_id_,
kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_P(GLES3DecoderWithShaderTest, Basic) {
// Make sure the setup is correct for ES3.
EXPECT_TRUE(feature_info()->IsWebGL2OrES3Context());
EXPECT_TRUE(feature_info()->validators()->texture_bind_target.IsValid(
GL_TEXTURE_3D));
}
TEST_P(GLES3DecoderWithShaderTest, UniformBlockBindingValidArgs) {
EXPECT_CALL(*gl_, UniformBlockBinding(kServiceProgramId, 1, 3));
SpecializedSetup<cmds::UniformBlockBinding, 0>(true);
cmds::UniformBlockBinding cmd;
cmd.Init(client_program_id_, 1, 3);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, BindUniformLocationCHROMIUMBucket) {
const uint32_t kBucketId = 123;
const GLint kLocation = 2;
const char* kName = "testing";
const char* kBadName1 = "gl_testing";
const char* kBadName2 = "testing[1]";
SetBucketAsCString(kBucketId, kName);
cmds::BindUniformLocationCHROMIUMBucket cmd;
cmd.Init(client_program_id_,
kLocation,
kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
// check negative location
SetBucketAsCString(kBucketId, kName);
cmd.Init(client_program_id_, -1, kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// check highest location
SetBucketAsCString(kBucketId, kName);
GLint kMaxLocation =
(kMaxFragmentUniformVectors + kMaxVertexUniformVectors) * 4 - 1;
cmd.Init(client_program_id_,
kMaxLocation,
kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
// check too high location
SetBucketAsCString(kBucketId, kName);
cmd.Init(client_program_id_,
kMaxLocation + 1,
kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
// check bad name "gl_..."
SetBucketAsCString(kBucketId, kBadName1);
cmd.Init(client_program_id_,
kLocation,
kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
// check bad name "name[1]" non zero
SetBucketAsCString(kBucketId, kBadName2);
cmd.Init(client_program_id_,
kLocation,
kBucketId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
TEST_P(GLES2DecoderWithShaderTest, UseDeletedProgram) {
DoDeleteProgram(client_program_id_, kServiceProgramId);
{
cmds::UseProgram cmd;
cmd.Init(client_program_id_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
EXPECT_CALL(*gl_, DeleteProgram(kServiceProgramId)).Times(1);
}
TEST_P(GLES2DecoderWithShaderTest, DetachDeletedShader) {
DoDeleteShader(client_fragment_shader_id_, kServiceFragmentShaderId);
{
EXPECT_CALL(*gl_, DetachShader(kServiceProgramId, kServiceFragmentShaderId))
.Times(1)
.RetiresOnSaturation();
cmds::DetachShader cmd;
cmd.Init(client_program_id_, client_fragment_shader_id_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
}
// TODO(gman): DeleteProgram
// TODO(gman): UseProgram
// TODO(gman): DeleteShader
} // namespace gles2
} // namespace gpu