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..3506c54dcddb2563f7cbbdc2e2eda56365576ff1 |
--- /dev/null |
+++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc |
@@ -0,0 +1,211 @@ |
+// 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 query APIs used by GLARBTimerTrace to a GlFakeQueries |
+ 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)); |
+ |
+ 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 |