Chromium Code Reviews| Index: gpu/command_buffer/service/gpu_tracer_unittest.cc |
| diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..401fe63780540e8df13663b0daf4e961f4aec537 |
| --- /dev/null |
| +++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc |
| @@ -0,0 +1,221 @@ |
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <map> |
| +#include <set> |
| + |
| +#include "gpu/command_buffer/service/gpu_tracer.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "ui/gl/gl_mock.h" |
| + |
| +namespace gpu { |
| +namespace gles2 { |
| + |
| +using ::gfx::MockGLInterface; |
| +using ::testing::InvokeWithoutArgs; |
| +using ::testing::Return; |
| +using ::testing::ReturnRef; |
| +using ::testing::ReturnPointee; |
| +using ::testing::NotNull; |
| +using ::testing::ElementsAreArray; |
| +using ::testing::ElementsAre; |
| +using ::testing::SetArrayArgument; |
| +using ::testing::AtLeast; |
| +using ::testing::SetArgPointee; |
| +using ::testing::Pointee; |
| +using ::testing::Unused; |
| +using ::testing::Invoke; |
| +using ::testing::_; |
| + |
| +class MockOutputter : public Outputter { |
| + public: |
| + MockOutputter() {} |
| + MOCK_METHOD3(Trace, void(const std::string& name, int64 start_time, |
| + int64 end_time)); |
| + |
| + protected: |
| + ~MockOutputter() {} |
| +}; |
| + |
| +class GlFakeQueries { |
| + public: |
| + GlFakeQueries() { |
| + } |
| + |
| + void Reset() { |
| + current_time_ = 0; |
| + next_query_id_ = 23; |
| + alloced_queries_.clear(); |
| + query_timestamp_.clear(); |
| + } |
| + |
| + void SetCurrentGLTime(GLint64 current_time) { |
| + current_time_ = current_time; |
| + } |
| + |
| + void GenQueries(GLsizei n, GLuint* ids) { |
| + for (GLsizei i = 0; i < n; i++) { |
| + ids[i] = next_query_id_++; |
| + alloced_queries_.insert(ids[i]); |
| + } |
| + } |
| + |
| + void DeleteQueries(GLsizei n, const GLuint* ids) { |
| + for (GLsizei i = 0; i < n; i++) { |
| + alloced_queries_.erase(ids[i]); |
| + query_timestamp_.erase(ids[i]); |
| + } |
| + } |
| + |
| + void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) { |
| + switch (pname) { |
| + case GL_QUERY_RESULT_AVAILABLE: { |
| + std::map<GLuint, GLint64>::iterator it = query_timestamp_.find(id); |
| + if (it != query_timestamp_.end() && it->second <= current_time_) |
| + *params = 1; |
| + else |
| + *params = 0; |
| + break; |
| + } |
| + default: |
| + ASSERT_TRUE(false); |
| + } |
| + } |
| + |
| + void QueryCounter(GLuint id, GLenum target) { |
| + switch (target) { |
| + case GL_TIMESTAMP: |
| + ASSERT_TRUE(alloced_queries_.find(id) != alloced_queries_.end()); |
| + query_timestamp_[id] = current_time_; |
| + break; |
| + default: |
| + ASSERT_TRUE(false); |
| + } |
| + } |
| + |
| + void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) { |
| + switch (pname) { |
| + case GL_QUERY_RESULT: |
| + ASSERT_TRUE(query_timestamp_.find(id) != query_timestamp_.end()); |
| + *params = query_timestamp_.find(id)->second; |
| + break; |
| + default: |
| + ASSERT_TRUE(false); |
| + } |
| + } |
| + |
| + protected: |
| + GLint64 current_time_; |
| + GLuint next_query_id_; |
| + std::set<GLuint> alloced_queries_; |
| + std::map<GLuint, GLint64> query_timestamp_; |
| +}; |
| + |
| +class GpuTracerTest : public testing::Test { |
| + public: |
| + GpuTracerTest() { |
| + } |
| + |
| + /////////////////////////////////////////////////////////////////////////// |
| + |
| + protected: |
| + virtual void SetUp() { |
| + gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); |
| + ::gfx::GLInterface::SetGLInterface(gl_.get()); |
| + gl_fake_queries_.Reset(); |
| + } |
| + |
| + virtual void TearDown() { |
| + ::gfx::GLInterface::SetGLInterface(NULL); |
| + gl_.reset(); |
| + gl_fake_queries_.Reset(); |
| + } |
| + |
| + void SetupTimerQueryMocks() { |
| + // Delegate queri APIs used by GLARBTimerTrace to a GlFakeQueries |
|
jbauman
2014/01/04 00:24:12
"query"
vmiura
2014/01/07 21:57:20
Done.
|
| + EXPECT_CALL(*gl_, GenQueries(_, NotNull())) |
| + .Times(AtLeast(1)) |
| + .WillOnce(Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueries)); |
| + |
| + EXPECT_CALL(*gl_, |
| + GetQueryObjectiv(_, GL_QUERY_RESULT_AVAILABLE, NotNull())) |
| + .Times(AtLeast(2)) |
| + .WillRepeatedly(Invoke(&gl_fake_queries_, |
| + &GlFakeQueries::GetQueryObjectiv)); |
| + |
| + EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP)) |
| + .Times(AtLeast(2)) |
| + .WillRepeatedly(Invoke(&gl_fake_queries_, |
| + &GlFakeQueries::QueryCounter)); |
| + |
| + EXPECT_CALL(*gl_, |
| + GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull())) |
| + .Times(AtLeast(2)) |
| + .WillRepeatedly(Invoke(&gl_fake_queries_, |
| + &GlFakeQueries::GetQueryObjectui64v)); |
| + |
| + EXPECT_CALL(*gl_, DeleteQueries(2, NotNull())) |
| + .Times(AtLeast(1)) |
| + .WillRepeatedly(Invoke(&gl_fake_queries_, |
| + &GlFakeQueries::DeleteQueries)); |
| + } |
| + |
| + scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; |
| + GlFakeQueries gl_fake_queries_; |
| +}; |
| + |
| + |
| +TEST_F(GpuTracerTest, GLARBTimerTrace) { |
| + // Test basic timer query functionality |
| + { |
| + MockOutputter* outputter = new MockOutputter(); |
| + scoped_refptr<Outputter> outputter_ref = outputter; |
| + |
| + SetupTimerQueryMocks(); |
| + |
| + // Expected results |
| + const std::string trace_name("trace_test"); |
| + const int64 offset_time = 3231; |
| + const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond; |
| + const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond; |
| + const int64 expect_start_time = |
| + (start_timestamp / base::Time::kNanosecondsPerMicrosecond) |
| + + offset_time; |
| + const int64 expect_end_time = |
| + (end_timestamp / base::Time::kNanosecondsPerMicrosecond) |
| + + offset_time; |
| + |
| + // Expected Outputter::Trace call |
| + EXPECT_CALL(*outputter, Trace(trace_name, expect_start_time, |
| + expect_end_time)); |
| + |
| + // Construct in place (we're going to reuse the space in the next test) |
| + scoped_refptr<GLARBTimerTrace> trace = |
| + new GLARBTimerTrace(outputter_ref, trace_name, offset_time); |
| + |
| + gl_fake_queries_.SetCurrentGLTime(start_timestamp); |
| + trace->Start(); |
| + |
| + // Shouldn't be available before End() call |
| + gl_fake_queries_.SetCurrentGLTime(end_timestamp); |
| + EXPECT_FALSE(trace->IsAvailable()); |
| + |
| + trace->End(); |
| + |
| + // Shouldn't be available until the queries complete |
| + gl_fake_queries_.SetCurrentGLTime(end_timestamp - |
| + base::Time::kNanosecondsPerMicrosecond); |
| + EXPECT_FALSE(trace->IsAvailable()); |
| + |
| + // Now it should be available |
| + gl_fake_queries_.SetCurrentGLTime(end_timestamp); |
| + EXPECT_TRUE(trace->IsAvailable()); |
| + |
| + // Proces should output expected Trace results to MockOutputter |
| + trace->Process(); |
| + } |
| +} |
| + |
| +} // namespace gles2 |
| +} // namespace gpu |