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"
15 using testing::Return
;
18 using testing::Sequence
;
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
24 class CommandParserTest
: public testing::Test
{
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
,
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
);
57 unsigned int buffer_entry_count() { return 20; }
58 AsyncAPIMock
*api_mock() { return api_mock_
.get(); }
59 CommandBufferEntry
*buffer() { return buffer_
.get(); }
61 unsigned int buffer_entry_count_
;
62 scoped_ptr
<AsyncAPIMock
> api_mock_
;
63 scoped_ptr
<CommandBufferEntry
[]> buffer_
;
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();
81 // add a single command, no args
84 buffer()[put
++].value_header
= header
;
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
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()
121 header
.command
= 789;
122 buffer()[put
++].value_header
= header
;
123 buffer()[put
++].value_int32
= 5151;
125 CommandBufferOffset put_cmd2
= put
;
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,
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()
149 header
.command
= 123;
150 buffer()[put
++].value_header
= header
;
151 buffer()[put
++].value_int32
= 5656;
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,
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
) {
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
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, ¶m
);
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).
212 buffer()[put
++].value_header
= header
;
213 buffer()[put
++].value_int32
= 6;
214 param
.value_int32
= 6;
215 AddDoCommandExpect(error::kNoError
, 4, 1, ¶m
);
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.
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));
248 // Generate a command with size 6, extends beyond the end of the buffer.
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));
263 // Generates 2 commands.
266 buffer()[put
++].value_header
= header
;
267 CommandBufferOffset put_post_fail
= put
;
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
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
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]);
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());