OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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. |
| 4 |
| 5 #include "gpu/command_buffer/service/common_decoder.h" |
| 6 #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
| 7 #include "testing/gtest/include/gtest/gtest.h" |
| 8 |
| 9 namespace command_buffer { |
| 10 |
| 11 TEST(CommonDecoderBucket, Basic) { |
| 12 CommonDecoder::Bucket bucket; |
| 13 EXPECT_EQ(0, bucket.size()); |
| 14 EXPECT_TRUE(NULL == bucket.GetData(0, 0)); |
| 15 } |
| 16 |
| 17 TEST(CommonDecoderBucket, Size) { |
| 18 CommonDecoder::Bucket bucket; |
| 19 bucket.SetSize(24); |
| 20 EXPECT_EQ(24, bucket.size()); |
| 21 bucket.SetSize(12); |
| 22 EXPECT_EQ(12, bucket.size()); |
| 23 } |
| 24 |
| 25 TEST(CommonDecoderBucket, GetData) { |
| 26 CommonDecoder::Bucket bucket; |
| 27 |
| 28 bucket.SetSize(24); |
| 29 EXPECT_TRUE(NULL != bucket.GetData(0, 0)); |
| 30 EXPECT_TRUE(NULL != bucket.GetData(24, 0)); |
| 31 EXPECT_TRUE(NULL == bucket.GetData(25, 0)); |
| 32 EXPECT_TRUE(NULL != bucket.GetData(0, 24)); |
| 33 EXPECT_TRUE(NULL == bucket.GetData(0, 25)); |
| 34 bucket.SetSize(23); |
| 35 EXPECT_TRUE(NULL == bucket.GetData(0, 24)); |
| 36 } |
| 37 |
| 38 TEST(CommonDecoderBucket, SetData) { |
| 39 CommonDecoder::Bucket bucket; |
| 40 static const char data[] = "testing"; |
| 41 |
| 42 bucket.SetSize(10); |
| 43 EXPECT_TRUE(bucket.SetData(data, 0, sizeof(data))); |
| 44 EXPECT_EQ(0, memcmp(data, bucket.GetData(0, sizeof(data)), sizeof(data))); |
| 45 EXPECT_TRUE(bucket.SetData(data, 2, sizeof(data))); |
| 46 EXPECT_EQ(0, memcmp(data, bucket.GetData(2, sizeof(data)), sizeof(data))); |
| 47 EXPECT_FALSE(bucket.SetData(data, 0, sizeof(data) * 2)); |
| 48 EXPECT_FALSE(bucket.SetData(data, 5, sizeof(data))); |
| 49 } |
| 50 |
| 51 class TestCommonDecoder : public CommonDecoder { |
| 52 public: |
| 53 // Overridden from AsyncAPIInterface |
| 54 const char* GetCommandName(unsigned int command_id) const { |
| 55 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id)); |
| 56 } |
| 57 |
| 58 // Overridden from AsyncAPIInterface |
| 59 parse_error::ParseError DoCommand( |
| 60 unsigned int command, |
| 61 unsigned int arg_count, |
| 62 const void* cmd_data) { |
| 63 return DoCommonCommand(command, arg_count, cmd_data); |
| 64 } |
| 65 |
| 66 CommonDecoder::Bucket* GetBucket(uint32 id) const { |
| 67 return CommonDecoder::GetBucket(id); |
| 68 } |
| 69 }; |
| 70 |
| 71 class MockCommandBufferEngine : public CommandBufferEngine { |
| 72 public: |
| 73 static const int32 kValidShmId = 1; |
| 74 |
| 75 MockCommandBufferEngine() |
| 76 : CommandBufferEngine(), |
| 77 token_() { |
| 78 } |
| 79 |
| 80 // Overridden from CommandBufferEngine. |
| 81 virtual void* GetSharedMemoryAddress(int32 shm_id) { |
| 82 return (shm_id == kValidShmId) ? buffer_ : NULL; |
| 83 } |
| 84 |
| 85 // Overridden from CommandBufferEngine. |
| 86 virtual size_t GetSharedMemorySize(int32 shm_id) { |
| 87 return (shm_id == kValidShmId) ? kBufferSize : 0; |
| 88 } |
| 89 |
| 90 template <typename T> |
| 91 T GetSharedMemoryAs(uint32 offset) { |
| 92 DCHECK(offset < kBufferSize); |
| 93 return reinterpret_cast<T>(&buffer_[offset]); |
| 94 } |
| 95 |
| 96 uint32 GetSharedMemoryOffset(const void* memory) { |
| 97 ptrdiff_t offset = reinterpret_cast<const int8*>(memory) - &buffer_[0]; |
| 98 DCHECK(offset >= 0); |
| 99 DCHECK(offset < kBufferSize); |
| 100 return static_cast<uint32>(offset); |
| 101 } |
| 102 |
| 103 // Overridden from CommandBufferEngine. |
| 104 virtual void set_token(int32 token) { |
| 105 token_ = token; |
| 106 } |
| 107 |
| 108 int32 token() const { |
| 109 return token_; |
| 110 } |
| 111 |
| 112 private: |
| 113 static const size_t kBufferSize = 1024; |
| 114 |
| 115 int8 buffer_[kBufferSize]; |
| 116 int32 token_; |
| 117 }; |
| 118 |
| 119 class CommonDecoderTest : public testing::Test { |
| 120 protected: |
| 121 virtual void SetUp() { |
| 122 decoder_.set_engine(&engine_); |
| 123 } |
| 124 |
| 125 virtual void TearDown() { |
| 126 } |
| 127 |
| 128 template <typename T> |
| 129 parse_error::ParseError ExecuteCmd(const T& cmd) { |
| 130 COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed); |
| 131 return decoder_.DoCommand(cmd.kCmdId, |
| 132 ComputeNumEntries(sizeof(cmd)) - 1, |
| 133 &cmd); |
| 134 } |
| 135 |
| 136 template <typename T> |
| 137 parse_error::ParseError ExecuteImmediateCmd(const T& cmd, size_t data_size) { |
| 138 COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN); |
| 139 return decoder_.DoCommand(cmd.kCmdId, |
| 140 ComputeNumEntries(sizeof(cmd) + data_size) - 1, |
| 141 &cmd); |
| 142 } |
| 143 |
| 144 MockCommandBufferEngine engine_; |
| 145 TestCommonDecoder decoder_; |
| 146 }; |
| 147 |
| 148 TEST_F(CommonDecoderTest, HandleNoop) { |
| 149 cmd::Noop cmd; |
| 150 const uint32 kSkipCount = 5; |
| 151 cmd.Init(kSkipCount); |
| 152 EXPECT_EQ(parse_error::kParseNoError, |
| 153 ExecuteImmediateCmd( |
| 154 cmd, kSkipCount * kCommandBufferEntrySize)); |
| 155 } |
| 156 |
| 157 TEST_F(CommonDecoderTest, SetToken) { |
| 158 cmd::SetToken cmd; |
| 159 const int32 kTokenId = 123; |
| 160 EXPECT_EQ(0, engine_.token()); |
| 161 cmd.Init(kTokenId); |
| 162 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 163 EXPECT_EQ(kTokenId, engine_.token()); |
| 164 } |
| 165 |
| 166 TEST_F(CommonDecoderTest, Jump) { |
| 167 // cmd::Jump cmd; |
| 168 // TODO(gman): implement. |
| 169 } |
| 170 |
| 171 TEST_F(CommonDecoderTest, JumpRelative) { |
| 172 // cmd::JumpRelative cmd; |
| 173 // TODO(gman): implement. |
| 174 } |
| 175 |
| 176 TEST_F(CommonDecoderTest, Call) { |
| 177 // cmd::Call cmd; |
| 178 // TODO(gman): implement. |
| 179 } |
| 180 |
| 181 TEST_F(CommonDecoderTest, CallRelative) { |
| 182 // cmd::CallRelative cmd; |
| 183 // TODO(gman): implement. |
| 184 } |
| 185 |
| 186 TEST_F(CommonDecoderTest, Return) { |
| 187 // cmd::Return cmd; |
| 188 // TODO(gman): implement. |
| 189 } |
| 190 |
| 191 TEST_F(CommonDecoderTest, SetBucketSize) { |
| 192 cmd::SetBucketSize cmd; |
| 193 const uint32 kBucketId = 123; |
| 194 const uint32 kBucketLength1 = 1234; |
| 195 const uint32 kBucketLength2 = 78; |
| 196 // Check the bucket does not exist. |
| 197 EXPECT_TRUE(NULL == decoder_.GetBucket(kBucketId)); |
| 198 // Check we can create one. |
| 199 cmd.Init(kBucketId, kBucketLength1); |
| 200 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 201 CommonDecoder::Bucket* bucket; |
| 202 bucket = decoder_.GetBucket(kBucketId); |
| 203 EXPECT_TRUE(NULL != bucket); |
| 204 EXPECT_EQ(kBucketLength1, bucket->size()); |
| 205 // Check we can change it. |
| 206 cmd.Init(kBucketId, kBucketLength2); |
| 207 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 208 bucket = decoder_.GetBucket(kBucketId); |
| 209 EXPECT_TRUE(NULL != bucket); |
| 210 EXPECT_EQ(kBucketLength2, bucket->size()); |
| 211 // Check we can delete it. |
| 212 cmd.Init(kBucketId, 0); |
| 213 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 214 bucket = decoder_.GetBucket(kBucketId); |
| 215 EXPECT_EQ(0, bucket->size()); |
| 216 } |
| 217 |
| 218 TEST_F(CommonDecoderTest, SetBucketData) { |
| 219 cmd::SetBucketSize size_cmd; |
| 220 cmd::SetBucketData cmd; |
| 221 |
| 222 static const char kData[] = "1234567890123456789"; |
| 223 |
| 224 const uint32 kBucketId = 123; |
| 225 const uint32 kInvalidBucketId = 124; |
| 226 |
| 227 size_cmd.Init(kBucketId, sizeof(kData)); |
| 228 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(size_cmd)); |
| 229 CommonDecoder::Bucket* bucket = decoder_.GetBucket(kBucketId); |
| 230 // Check the data is not there. |
| 231 EXPECT_NE(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData))); |
| 232 |
| 233 // Check we can set it. |
| 234 const uint32 kSomeOffsetInSharedMemory = 50; |
| 235 void* memory = engine_.GetSharedMemoryAs<void*>(kSomeOffsetInSharedMemory); |
| 236 memcpy(memory, kData, sizeof(kData)); |
| 237 cmd.Init(kBucketId, 0, sizeof(kData), |
| 238 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 239 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 240 EXPECT_EQ(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData))); |
| 241 |
| 242 // Check we can set it partially. |
| 243 static const char kData2[] = "ABCEDFG"; |
| 244 const uint32 kSomeOffsetInBucket = 5; |
| 245 memcpy(memory, kData2, sizeof(kData2)); |
| 246 cmd.Init(kBucketId, kSomeOffsetInBucket, sizeof(kData2), |
| 247 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 248 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 249 EXPECT_EQ(0, memcmp(bucket->GetData(kSomeOffsetInBucket, sizeof(kData2)), |
| 250 kData2, sizeof(kData2))); |
| 251 const char* bucket_data = bucket->GetDataAs<const char*>(0, sizeof(kData)); |
| 252 // Check that nothing was affected outside of updated area. |
| 253 EXPECT_EQ(kData[kSomeOffsetInBucket - 1], |
| 254 bucket_data[kSomeOffsetInBucket - 1]); |
| 255 EXPECT_EQ(kData[kSomeOffsetInBucket + sizeof(kData2)], |
| 256 bucket_data[kSomeOffsetInBucket + sizeof(kData2)]); |
| 257 |
| 258 // Check that it fails if the bucket_id is invalid |
| 259 cmd.Init(kInvalidBucketId, kSomeOffsetInBucket, sizeof(kData2), |
| 260 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 261 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 262 |
| 263 // Check that it fails if the offset is out of range. |
| 264 cmd.Init(kBucketId, bucket->size(), 1, |
| 265 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 266 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 267 |
| 268 // Check that it fails if the size is out of range. |
| 269 cmd.Init(kBucketId, 0, bucket->size() + 1, |
| 270 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 271 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 272 } |
| 273 |
| 274 TEST_F(CommonDecoderTest, SetBucketDataImmediate) { |
| 275 cmd::SetBucketSize size_cmd; |
| 276 int8 buffer[1024]; |
| 277 cmd::SetBucketDataImmediate& cmd = |
| 278 *reinterpret_cast<cmd::SetBucketDataImmediate*>(&buffer); |
| 279 |
| 280 static const char kData[] = "1234567890123456789"; |
| 281 |
| 282 const uint32 kBucketId = 123; |
| 283 const uint32 kInvalidBucketId = 124; |
| 284 |
| 285 size_cmd.Init(kBucketId, sizeof(kData)); |
| 286 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(size_cmd)); |
| 287 CommonDecoder::Bucket* bucket = decoder_.GetBucket(kBucketId); |
| 288 // Check the data is not there. |
| 289 EXPECT_NE(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData))); |
| 290 |
| 291 // Check we can set it. |
| 292 void* memory = &buffer[0] + sizeof(cmd); |
| 293 memcpy(memory, kData, sizeof(kData)); |
| 294 cmd.Init(kBucketId, 0, sizeof(kData)); |
| 295 EXPECT_EQ(parse_error::kParseNoError, |
| 296 ExecuteImmediateCmd(cmd, sizeof(kData))); |
| 297 EXPECT_EQ(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData))); |
| 298 |
| 299 // Check we can set it partially. |
| 300 static const char kData2[] = "ABCEDFG"; |
| 301 const uint32 kSomeOffsetInBucket = 5; |
| 302 memcpy(memory, kData2, sizeof(kData2)); |
| 303 cmd.Init(kBucketId, kSomeOffsetInBucket, sizeof(kData2)); |
| 304 EXPECT_EQ(parse_error::kParseNoError, |
| 305 ExecuteImmediateCmd(cmd, sizeof(kData2))); |
| 306 EXPECT_EQ(0, memcmp(bucket->GetData(kSomeOffsetInBucket, sizeof(kData2)), |
| 307 kData2, sizeof(kData2))); |
| 308 const char* bucket_data = bucket->GetDataAs<const char*>(0, sizeof(kData)); |
| 309 // Check that nothing was affected outside of updated area. |
| 310 EXPECT_EQ(kData[kSomeOffsetInBucket - 1], |
| 311 bucket_data[kSomeOffsetInBucket - 1]); |
| 312 EXPECT_EQ(kData[kSomeOffsetInBucket + sizeof(kData2)], |
| 313 bucket_data[kSomeOffsetInBucket + sizeof(kData2)]); |
| 314 |
| 315 // Check that it fails if the bucket_id is invalid |
| 316 cmd.Init(kInvalidBucketId, kSomeOffsetInBucket, sizeof(kData2)); |
| 317 EXPECT_NE(parse_error::kParseNoError, |
| 318 ExecuteImmediateCmd(cmd, sizeof(kData2))); |
| 319 |
| 320 // Check that it fails if the offset is out of range. |
| 321 cmd.Init(kBucketId, bucket->size(), 1); |
| 322 EXPECT_NE(parse_error::kParseNoError, |
| 323 ExecuteImmediateCmd(cmd, sizeof(kData2))); |
| 324 |
| 325 // Check that it fails if the size is out of range. |
| 326 cmd.Init(kBucketId, 0, bucket->size() + 1); |
| 327 EXPECT_NE(parse_error::kParseNoError, |
| 328 ExecuteImmediateCmd(cmd, sizeof(kData2))); |
| 329 } |
| 330 |
| 331 TEST_F(CommonDecoderTest, GetBucketSize) { |
| 332 cmd::SetBucketSize size_cmd; |
| 333 cmd::GetBucketSize cmd; |
| 334 |
| 335 const uint32 kBucketSize = 456; |
| 336 const uint32 kBucketId = 123; |
| 337 const uint32 kInvalidBucketId = 124; |
| 338 |
| 339 size_cmd.Init(kBucketId, kBucketSize); |
| 340 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(size_cmd)); |
| 341 |
| 342 // Check that the size is correct. |
| 343 const uint32 kSomeOffsetInSharedMemory = 50; |
| 344 uint32* memory = |
| 345 engine_.GetSharedMemoryAs<uint32*>(kSomeOffsetInSharedMemory); |
| 346 *memory = 0xFFFFFFFF; |
| 347 cmd.Init(kBucketId, |
| 348 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 349 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 350 EXPECT_EQ(kBucketSize, *memory); |
| 351 |
| 352 // Check that it fails if the bucket_id is invalid |
| 353 cmd.Init(kInvalidBucketId, |
| 354 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 355 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 356 } |
| 357 |
| 358 TEST_F(CommonDecoderTest, GetBucketData) { |
| 359 cmd::SetBucketSize size_cmd; |
| 360 cmd::SetBucketData set_cmd; |
| 361 cmd::GetBucketData cmd; |
| 362 |
| 363 static const char kData[] = "1234567890123456789"; |
| 364 static const char zero[sizeof(kData)] = { 0, }; |
| 365 |
| 366 const uint32 kBucketId = 123; |
| 367 const uint32 kInvalidBucketId = 124; |
| 368 |
| 369 size_cmd.Init(kBucketId, sizeof(kData)); |
| 370 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(size_cmd)); |
| 371 CommonDecoder::Bucket* bucket = decoder_.GetBucket(kBucketId); |
| 372 const uint32 kSomeOffsetInSharedMemory = 50; |
| 373 uint8* memory = engine_.GetSharedMemoryAs<uint8*>(kSomeOffsetInSharedMemory); |
| 374 memcpy(memory, kData, sizeof(kData)); |
| 375 set_cmd.Init(kBucketId, 0, sizeof(kData), |
| 376 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 377 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(set_cmd)); |
| 378 |
| 379 // Check we can get the whole thing. |
| 380 memset(memory, 0, sizeof(kData)); |
| 381 cmd.Init(kBucketId, 0, sizeof(kData), |
| 382 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 383 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 384 EXPECT_EQ(0, memcmp(memory, kData, sizeof(kData))); |
| 385 |
| 386 // Check we can get a piece. |
| 387 const uint32 kSomeOffsetInBucket = 5; |
| 388 const uint32 kLengthOfPiece = 6; |
| 389 const uint8 kSentinel = 0xff; |
| 390 memset(memory, 0, sizeof(kData)); |
| 391 memory[-1] = kSentinel; |
| 392 cmd.Init(kBucketId, kSomeOffsetInBucket, kLengthOfPiece, |
| 393 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 394 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 395 EXPECT_EQ(0, memcmp(memory, kData + kSomeOffsetInBucket, kLengthOfPiece)); |
| 396 EXPECT_EQ(0, memcmp(memory + kLengthOfPiece, zero, |
| 397 sizeof(kData) - kLengthOfPiece)); |
| 398 EXPECT_EQ(kSentinel, memory[-1]); |
| 399 |
| 400 // Check that it fails if the bucket_id is invalid |
| 401 cmd.Init(kInvalidBucketId, kSomeOffsetInBucket, sizeof(kData), |
| 402 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 403 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 404 |
| 405 // Check that it fails if the offset is invalid |
| 406 cmd.Init(kBucketId, sizeof(kData) + 1, 1, |
| 407 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 408 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 409 |
| 410 // Check that it fails if the size is invalid |
| 411 cmd.Init(kBucketId, 0, sizeof(kData) + 1, |
| 412 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
| 413 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 414 } |
| 415 |
| 416 |
| 417 } // namespace command_buffer |
| 418 |
OLD | NEW |