Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / gpu / command_buffer / service / cmd_parser_test.cc
blob232ebe7dd09c1b5edaf28de3a355d74c0d8bf3b2
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Tests for the command parser.
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "gpu/command_buffer/service/cmd_parser.h"
10 #include "gpu/command_buffer/service/mocks.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 namespace gpu {
15 using testing::Return;
16 using testing::Mock;
17 using testing::Truly;
18 using testing::Sequence;
19 using testing::_;
21 // Test fixture for CommandParser test - Creates a mock AsyncAPIInterface, and
22 // a fixed size memory buffer. Also provides a simple API to create a
23 // CommandParser.
24 class CommandParserTest : public testing::Test {
25 protected:
26 virtual void SetUp() {
27 api_mock_.reset(new AsyncAPIMock);
28 buffer_entry_count_ = 20;
29 buffer_.reset(new CommandBufferEntry[buffer_entry_count_]);
31 virtual void TearDown() {}
33 // Adds a DoCommand expectation in the mock.
34 void AddDoCommandExpect(error::Error _return,
35 unsigned int command,
36 unsigned int arg_count,
37 CommandBufferEntry *args) {
38 EXPECT_CALL(*api_mock(), DoCommand(command, arg_count,
39 Truly(AsyncAPIMock::IsArgs(arg_count, args))))
40 .InSequence(sequence_)
41 .WillOnce(Return(_return));
44 // Creates a parser, with a buffer of the specified size (in entries).
45 CommandParser *MakeParser(unsigned int entry_count) {
46 size_t shm_size = buffer_entry_count_ *
47 sizeof(CommandBufferEntry); // NOLINT
48 size_t command_buffer_size = entry_count *
49 sizeof(CommandBufferEntry); // NOLINT
50 DCHECK_LE(command_buffer_size, shm_size);
51 CommandParser* parser = new CommandParser(api_mock());
53 parser->SetBuffer(buffer(), shm_size, 0, command_buffer_size);
54 return parser;
57 unsigned int buffer_entry_count() { return 20; }
58 AsyncAPIMock *api_mock() { return api_mock_.get(); }
59 CommandBufferEntry *buffer() { return buffer_.get(); }
60 private:
61 unsigned int buffer_entry_count_;
62 scoped_ptr<AsyncAPIMock> api_mock_;
63 scoped_ptr<CommandBufferEntry[]> buffer_;
64 Sequence sequence_;
67 // Tests initialization conditions.
68 TEST_F(CommandParserTest, TestInit) {
69 scoped_ptr<CommandParser> parser(MakeParser(10));
70 EXPECT_EQ(0, parser->get());
71 EXPECT_EQ(0, parser->put());
72 EXPECT_TRUE(parser->IsEmpty());
75 // Tests simple commands.
76 TEST_F(CommandParserTest, TestSimple) {
77 scoped_ptr<CommandParser> parser(MakeParser(10));
78 CommandBufferOffset put = parser->put();
79 CommandHeader header;
81 // add a single command, no args
82 header.size = 1;
83 header.command = 123;
84 buffer()[put++].value_header = header;
86 parser->set_put(put);
87 EXPECT_EQ(put, parser->put());
89 AddDoCommandExpect(error::kNoError, 123, 0, NULL);
90 EXPECT_EQ(error::kNoError, parser->ProcessCommand());
91 EXPECT_EQ(put, parser->get());
92 Mock::VerifyAndClearExpectations(api_mock());
94 // add a single command, 2 args
95 header.size = 3;
96 header.command = 456;
97 buffer()[put++].value_header = header;
98 buffer()[put++].value_int32 = 2134;
99 buffer()[put++].value_float = 1.f;
101 parser->set_put(put);
102 EXPECT_EQ(put, parser->put());
104 CommandBufferEntry param_array[2];
105 param_array[0].value_int32 = 2134;
106 param_array[1].value_float = 1.f;
107 AddDoCommandExpect(error::kNoError, 456, 2, param_array);
108 EXPECT_EQ(error::kNoError, parser->ProcessCommand());
109 EXPECT_EQ(put, parser->get());
110 Mock::VerifyAndClearExpectations(api_mock());
113 // Tests having multiple commands in the buffer.
114 TEST_F(CommandParserTest, TestMultipleCommands) {
115 scoped_ptr<CommandParser> parser(MakeParser(10));
116 CommandBufferOffset put = parser->put();
117 CommandHeader header;
119 // add 2 commands, test with single ProcessCommand()
120 header.size = 2;
121 header.command = 789;
122 buffer()[put++].value_header = header;
123 buffer()[put++].value_int32 = 5151;
125 CommandBufferOffset put_cmd2 = put;
126 header.size = 2;
127 header.command = 876;
128 buffer()[put++].value_header = header;
129 buffer()[put++].value_int32 = 3434;
131 parser->set_put(put);
132 EXPECT_EQ(put, parser->put());
134 CommandBufferEntry param_array[2];
135 param_array[0].value_int32 = 5151;
136 AddDoCommandExpect(error::kNoError, 789, 1, param_array);
137 param_array[1].value_int32 = 3434;
138 AddDoCommandExpect(error::kNoError, 876, 1,
139 param_array+1);
141 EXPECT_EQ(error::kNoError, parser->ProcessCommand());
142 EXPECT_EQ(put_cmd2, parser->get());
143 EXPECT_EQ(error::kNoError, parser->ProcessCommand());
144 EXPECT_EQ(put, parser->get());
145 Mock::VerifyAndClearExpectations(api_mock());
147 // add 2 commands again, test with ProcessAllCommands()
148 header.size = 2;
149 header.command = 123;
150 buffer()[put++].value_header = header;
151 buffer()[put++].value_int32 = 5656;
153 header.size = 2;
154 header.command = 321;
155 buffer()[put++].value_header = header;
156 buffer()[put++].value_int32 = 7878;
158 parser->set_put(put);
159 EXPECT_EQ(put, parser->put());
161 param_array[0].value_int32 = 5656;
162 AddDoCommandExpect(error::kNoError, 123, 1, param_array);
163 param_array[1].value_int32 = 7878;
164 AddDoCommandExpect(error::kNoError, 321, 1,
165 param_array+1);
167 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
168 EXPECT_EQ(put, parser->get());
169 Mock::VerifyAndClearExpectations(api_mock());
172 // Tests that the parser will wrap correctly at the end of the buffer.
173 TEST_F(CommandParserTest, TestWrap) {
174 scoped_ptr<CommandParser> parser(MakeParser(5));
175 CommandBufferOffset put = parser->put();
176 CommandHeader header;
178 // add 3 commands with no args (1 word each)
179 for (unsigned int i = 0; i < 3; ++i) {
180 header.size = 1;
181 header.command = i;
182 buffer()[put++].value_header = header;
183 AddDoCommandExpect(error::kNoError, i, 0, NULL);
185 parser->set_put(put);
186 EXPECT_EQ(put, parser->put());
187 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
188 EXPECT_EQ(put, parser->get());
189 Mock::VerifyAndClearExpectations(api_mock());
191 // add 1 command with 1 arg (2 words). That should put us at the end of the
192 // buffer.
193 header.size = 2;
194 header.command = 3;
195 buffer()[put++].value_header = header;
196 buffer()[put++].value_int32 = 5;
197 CommandBufferEntry param;
198 param.value_int32 = 5;
199 AddDoCommandExpect(error::kNoError, 3, 1, &param);
201 DCHECK_EQ(5, put);
202 put = 0;
203 parser->set_put(put);
204 EXPECT_EQ(put, parser->put());
205 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
206 EXPECT_EQ(put, parser->get());
207 Mock::VerifyAndClearExpectations(api_mock());
209 // add 1 command with 1 arg (2 words).
210 header.size = 2;
211 header.command = 4;
212 buffer()[put++].value_header = header;
213 buffer()[put++].value_int32 = 6;
214 param.value_int32 = 6;
215 AddDoCommandExpect(error::kNoError, 4, 1, &param);
216 parser->set_put(put);
217 EXPECT_EQ(put, parser->put());
218 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
219 EXPECT_EQ(put, parser->get());
220 Mock::VerifyAndClearExpectations(api_mock());
223 // Tests error conditions.
224 TEST_F(CommandParserTest, TestError) {
225 const unsigned int kNumEntries = 5;
226 scoped_ptr<CommandParser> parser(MakeParser(kNumEntries));
227 CommandBufferOffset put = parser->put();
228 CommandHeader header;
230 EXPECT_FALSE(parser->set_get(-1));
231 EXPECT_FALSE(parser->set_get(kNumEntries));
233 // Generate a command with size 0.
234 header.size = 0;
235 header.command = 3;
236 buffer()[put++].value_header = header;
238 parser->set_put(put);
239 EXPECT_EQ(put, parser->put());
240 EXPECT_EQ(error::kInvalidSize,
241 parser->ProcessAllCommands());
242 // check that no DoCommand call was made.
243 Mock::VerifyAndClearExpectations(api_mock());
245 parser.reset(MakeParser(5));
246 put = parser->put();
248 // Generate a command with size 6, extends beyond the end of the buffer.
249 header.size = 6;
250 header.command = 3;
251 buffer()[put++].value_header = header;
253 parser->set_put(put);
254 EXPECT_EQ(put, parser->put());
255 EXPECT_EQ(error::kOutOfBounds,
256 parser->ProcessAllCommands());
257 // check that no DoCommand call was made.
258 Mock::VerifyAndClearExpectations(api_mock());
260 parser.reset(MakeParser(5));
261 put = parser->put();
263 // Generates 2 commands.
264 header.size = 1;
265 header.command = 3;
266 buffer()[put++].value_header = header;
267 CommandBufferOffset put_post_fail = put;
268 header.size = 1;
269 header.command = 4;
270 buffer()[put++].value_header = header;
272 parser->set_put(put);
273 EXPECT_EQ(put, parser->put());
274 // have the first command fail to parse.
275 AddDoCommandExpect(error::kUnknownCommand, 3, 0, NULL);
276 EXPECT_EQ(error::kUnknownCommand,
277 parser->ProcessAllCommands());
278 // check that only one command was executed, and that get reflects that
279 // correctly.
280 EXPECT_EQ(put_post_fail, parser->get());
281 Mock::VerifyAndClearExpectations(api_mock());
282 // make the second one succeed, and check that the parser recovered fine.
283 AddDoCommandExpect(error::kNoError, 4, 0, NULL);
284 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
285 EXPECT_EQ(put, parser->get());
286 Mock::VerifyAndClearExpectations(api_mock());
289 TEST_F(CommandParserTest, SetBuffer) {
290 scoped_ptr<CommandParser> parser(MakeParser(3));
291 CommandBufferOffset put = parser->put();
292 CommandHeader header;
294 // add a single command, no args
295 header.size = 2;
296 header.command = 123;
297 buffer()[put++].value_header = header;
298 buffer()[put++].value_int32 = 456;
300 CommandBufferEntry param_array[1];
301 param_array[0].value_int32 = 456;
303 parser->set_put(put);
304 AddDoCommandExpect(error::kNoError, 123, 1, param_array);
305 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
306 // We should have advanced 2 entries
307 EXPECT_EQ(2, parser->get());
308 Mock::VerifyAndClearExpectations(api_mock());
310 scoped_ptr<CommandBufferEntry[]> buffer2(new CommandBufferEntry[2]);
311 parser->SetBuffer(
312 buffer2.get(), sizeof(CommandBufferEntry) * 2, 0,
313 sizeof(CommandBufferEntry) * 2);
314 // The put and get should have reset to 0.
315 EXPECT_EQ(0, parser->get());
316 EXPECT_EQ(0, parser->put());
319 } // namespace gpu