1 /* 2 ** Copyright 2011, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 #include <sys/socket.h> 18 #include <sys/ioctl.h> 19 20 #include "header.h" 21 #include "gtest/gtest.h" 22 #include "hooks.h" 23 24 namespace android 25 { 26 extern int serverSock, clientSock; 27 }; 28 29 void * glNoop(); 30 31 class SocketContextTest : public ::testing::Test 32 { 33 protected: 34 DbgContext* dbg; 35 gl_hooks_t hooks; 36 int sock; 37 char * buffer; 38 unsigned int bufferSize; 39 40 SocketContextTest() : sock(-1) { 41 } 42 43 virtual ~SocketContextTest() { 44 } 45 46 virtual void SetUp() { 47 dbg = new DbgContext(1, &hooks, 32); 48 ASSERT_TRUE(dbg != NULL); 49 for (unsigned int i = 0; i < sizeof(hooks) / sizeof(void *); i++) 50 ((void **)&hooks)[i] = (void *)glNoop; 51 52 int socks[2] = {-1, -1}; 53 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, socks)); 54 clientSock = socks[0]; 55 sock = socks[1]; 56 57 bufferSize = 128; 58 buffer = new char [128]; 59 ASSERT_NE((char *)NULL, buffer); 60 } 61 62 virtual void TearDown() { 63 close(sock); 64 close(clientSock); 65 clientSock = -1; 66 delete buffer; 67 } 68 69 void Write(glesv2debugger::Message & msg) const { 70 msg.set_context_id((int)dbg); 71 msg.set_type(msg.Response); 72 ASSERT_TRUE(msg.has_context_id()); 73 ASSERT_TRUE(msg.has_function()); 74 ASSERT_TRUE(msg.has_type()); 75 ASSERT_TRUE(msg.has_expect_response()); 76 static std::string str; 77 msg.SerializeToString(&str); 78 const uint32_t len = str.length(); 79 ASSERT_EQ(sizeof(len), send(sock, &len, sizeof(len), 0)); 80 ASSERT_EQ(str.length(), send(sock, str.data(), str.length(), 0)); 81 } 82 83 void Read(glesv2debugger::Message & msg) { 84 int available = 0; 85 ASSERT_EQ(0, ioctl(sock, FIONREAD, &available)); 86 ASSERT_GT(available, 0); 87 uint32_t len = 0; 88 ASSERT_EQ(sizeof(len), recv(sock, &len, sizeof(len), 0)); 89 if (len > bufferSize) { 90 bufferSize = len; 91 buffer = new char[bufferSize]; 92 ASSERT_TRUE(buffer != NULL); 93 } 94 ASSERT_EQ(len, recv(sock, buffer, len, 0)); 95 msg.Clear(); 96 msg.ParseFromArray(buffer, len); 97 ASSERT_TRUE(msg.has_context_id()); 98 ASSERT_TRUE(msg.has_function()); 99 ASSERT_TRUE(msg.has_type()); 100 ASSERT_TRUE(msg.has_expect_response()); 101 } 102 103 void CheckNoAvailable() { 104 int available = 0; 105 ASSERT_EQ(0, ioctl(sock, FIONREAD, &available)); 106 ASSERT_EQ(available, 0); 107 } 108 }; 109 110 TEST_F(SocketContextTest, MessageLoopSkip) 111 { 112 static const int arg0 = 45; 113 static const float arg7 = -87.2331f; 114 static const int arg8 = -3; 115 static const int * ret = (int *)870; 116 117 struct Caller : public FunctionCall { 118 const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) { 119 msg.set_arg0(arg0); 120 msg.set_arg7((int &)arg7); 121 msg.set_arg8(arg8); 122 return ret; 123 } 124 } caller; 125 glesv2debugger::Message msg, read, cmd; 126 dbg->expectResponse.Bit(msg.glFinish, true); 127 128 cmd.set_function(cmd.SKIP); 129 cmd.set_expect_response(false); 130 Write(cmd); 131 132 EXPECT_NE(ret, MessageLoop(caller, msg, msg.glFinish)); 133 134 Read(read); 135 EXPECT_EQ(read.glFinish, read.function()); 136 EXPECT_EQ(read.BeforeCall, read.type()); 137 EXPECT_NE(arg0, read.arg0()); 138 EXPECT_NE((int &)arg7, read.arg7()); 139 EXPECT_NE(arg8, read.arg8()); 140 141 CheckNoAvailable(); 142 } 143 144 TEST_F(SocketContextTest, MessageLoopContinue) 145 { 146 static const int arg0 = GL_FRAGMENT_SHADER; 147 static const int ret = -342; 148 struct Caller : public FunctionCall { 149 const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) { 150 msg.set_ret(ret); 151 return (int *)ret; 152 } 153 } caller; 154 glesv2debugger::Message msg, read, cmd; 155 dbg->expectResponse.Bit(msg.glCreateShader, true); 156 157 cmd.set_function(cmd.CONTINUE); 158 cmd.set_expect_response(false); // MessageLoop should automatically skip after continue 159 Write(cmd); 160 161 msg.set_arg0(arg0); 162 EXPECT_EQ((int *)ret, MessageLoop(caller, msg, msg.glCreateShader)); 163 164 Read(read); 165 EXPECT_EQ(read.glCreateShader, read.function()); 166 EXPECT_EQ(read.BeforeCall, read.type()); 167 EXPECT_EQ(arg0, read.arg0()); 168 169 Read(read); 170 EXPECT_EQ(read.glCreateShader, read.function()); 171 EXPECT_EQ(read.AfterCall, read.type()); 172 EXPECT_EQ(ret, read.ret()); 173 174 CheckNoAvailable(); 175 } 176 177 TEST_F(SocketContextTest, MessageLoopGenerateCall) 178 { 179 static const int ret = -342; 180 static unsigned int createShader, createProgram; 181 createShader = 0; 182 createProgram = 0; 183 struct Caller : public FunctionCall { 184 const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) { 185 const int r = (int)_c->glCreateProgram(); 186 msg.set_ret(r); 187 return (int *)r; 188 } 189 static GLuint CreateShader(const GLenum type) { 190 createShader++; 191 return type; 192 } 193 static GLuint CreateProgram() { 194 createProgram++; 195 return ret; 196 } 197 } caller; 198 glesv2debugger::Message msg, read, cmd; 199 hooks.gl.glCreateShader = caller.CreateShader; 200 hooks.gl.glCreateProgram = caller.CreateProgram; 201 dbg->expectResponse.Bit(msg.glCreateProgram, true); 202 203 cmd.set_function(cmd.glCreateShader); 204 cmd.set_arg0(GL_FRAGMENT_SHADER); 205 cmd.set_expect_response(true); 206 Write(cmd); 207 208 cmd.Clear(); 209 cmd.set_function(cmd.CONTINUE); 210 cmd.set_expect_response(true); 211 Write(cmd); 212 213 cmd.set_function(cmd.glCreateShader); 214 cmd.set_arg0(GL_VERTEX_SHADER); 215 cmd.set_expect_response(false); // MessageLoop should automatically skip afterwards 216 Write(cmd); 217 218 EXPECT_EQ((int *)ret, MessageLoop(caller, msg, msg.glCreateProgram)); 219 220 Read(read); 221 EXPECT_EQ(read.glCreateProgram, read.function()); 222 EXPECT_EQ(read.BeforeCall, read.type()); 223 224 Read(read); 225 EXPECT_EQ(read.glCreateShader, read.function()); 226 EXPECT_EQ(read.AfterGeneratedCall, read.type()); 227 EXPECT_EQ(GL_FRAGMENT_SHADER, read.ret()); 228 229 Read(read); 230 EXPECT_EQ(read.glCreateProgram, read.function()); 231 EXPECT_EQ(read.AfterCall, read.type()); 232 EXPECT_EQ(ret, read.ret()); 233 234 Read(read); 235 EXPECT_EQ(read.glCreateShader, read.function()); 236 EXPECT_EQ(read.AfterGeneratedCall, read.type()); 237 EXPECT_EQ(GL_VERTEX_SHADER, read.ret()); 238 239 EXPECT_EQ(2, createShader); 240 EXPECT_EQ(1, createProgram); 241 242 CheckNoAvailable(); 243 } 244 245 TEST_F(SocketContextTest, MessageLoopSetProp) 246 { 247 static const int ret = -342; 248 static unsigned int createShader, createProgram; 249 createShader = 0; 250 createProgram = 0; 251 struct Caller : public FunctionCall { 252 const int * operator()(gl_hooks_t::gl_t const * const _c, glesv2debugger::Message & msg) { 253 const int r = (int)_c->glCreateProgram(); 254 msg.set_ret(r); 255 return (int *)r; 256 } 257 static GLuint CreateShader(const GLenum type) { 258 createShader++; 259 return type; 260 } 261 static GLuint CreateProgram() { 262 createProgram++; 263 return ret; 264 } 265 } caller; 266 glesv2debugger::Message msg, read, cmd; 267 hooks.gl.glCreateShader = caller.CreateShader; 268 hooks.gl.glCreateProgram = caller.CreateProgram; 269 dbg->expectResponse.Bit(msg.glCreateProgram, false); 270 271 cmd.set_function(cmd.SETPROP); 272 cmd.set_prop(cmd.ExpectResponse); 273 cmd.set_arg0(cmd.glCreateProgram); 274 cmd.set_arg1(true); 275 cmd.set_expect_response(true); 276 Write(cmd); 277 278 cmd.Clear(); 279 cmd.set_function(cmd.glCreateShader); 280 cmd.set_arg0(GL_FRAGMENT_SHADER); 281 cmd.set_expect_response(true); 282 Write(cmd); 283 284 cmd.set_function(cmd.SETPROP); 285 cmd.set_prop(cmd.CaptureDraw); 286 cmd.set_arg0(819); 287 cmd.set_expect_response(true); 288 Write(cmd); 289 290 cmd.Clear(); 291 cmd.set_function(cmd.CONTINUE); 292 cmd.set_expect_response(true); 293 Write(cmd); 294 295 cmd.set_function(cmd.glCreateShader); 296 cmd.set_arg0(GL_VERTEX_SHADER); 297 cmd.set_expect_response(false); // MessageLoop should automatically skip afterwards 298 Write(cmd); 299 300 EXPECT_EQ((int *)ret, MessageLoop(caller, msg, msg.glCreateProgram)); 301 302 EXPECT_TRUE(dbg->expectResponse.Bit(msg.glCreateProgram)); 303 EXPECT_EQ(819, dbg->captureDraw); 304 305 Read(read); 306 EXPECT_EQ(read.glCreateProgram, read.function()); 307 EXPECT_EQ(read.BeforeCall, read.type()); 308 309 Read(read); 310 EXPECT_EQ(read.glCreateShader, read.function()); 311 EXPECT_EQ(read.AfterGeneratedCall, read.type()); 312 EXPECT_EQ(GL_FRAGMENT_SHADER, read.ret()); 313 314 Read(read); 315 EXPECT_EQ(read.glCreateProgram, read.function()); 316 EXPECT_EQ(read.AfterCall, read.type()); 317 EXPECT_EQ(ret, read.ret()); 318 319 Read(read); 320 EXPECT_EQ(read.glCreateShader, read.function()); 321 EXPECT_EQ(read.AfterGeneratedCall, read.type()); 322 EXPECT_EQ(GL_VERTEX_SHADER, read.ret()); 323 324 EXPECT_EQ(2, createShader); 325 EXPECT_EQ(1, createProgram); 326 327 CheckNoAvailable(); 328 } 329 330 TEST_F(SocketContextTest, TexImage2D) 331 { 332 static const GLenum _target = GL_TEXTURE_2D; 333 static const GLint _level = 1, _internalformat = GL_RGBA; 334 static const GLsizei _width = 2, _height = 2; 335 static const GLint _border = 333; 336 static const GLenum _format = GL_RGB, _type = GL_UNSIGNED_SHORT_5_6_5; 337 static const short _pixels [_width * _height] = {11, 22, 33, 44}; 338 static unsigned int texImage2D; 339 texImage2D = 0; 340 341 struct Caller { 342 static void TexImage2D(GLenum target, GLint level, GLint internalformat, 343 GLsizei width, GLsizei height, GLint border, 344 GLenum format, GLenum type, const GLvoid* pixels) { 345 EXPECT_EQ(_target, target); 346 EXPECT_EQ(_level, level); 347 EXPECT_EQ(_internalformat, internalformat); 348 EXPECT_EQ(_width, width); 349 EXPECT_EQ(_height, height); 350 EXPECT_EQ(_border, border); 351 EXPECT_EQ(_format, format); 352 EXPECT_EQ(_type, type); 353 EXPECT_EQ(0, memcmp(_pixels, pixels, sizeof(_pixels))); 354 texImage2D++; 355 } 356 } caller; 357 glesv2debugger::Message msg, read, cmd; 358 hooks.gl.glTexImage2D = caller.TexImage2D; 359 dbg->expectResponse.Bit(msg.glTexImage2D, false); 360 361 Debug_glTexImage2D(_target, _level, _internalformat, _width, _height, _border, 362 _format, _type, _pixels); 363 EXPECT_EQ(1, texImage2D); 364 365 Read(read); 366 EXPECT_EQ(read.glTexImage2D, read.function()); 367 EXPECT_EQ(read.BeforeCall, read.type()); 368 EXPECT_EQ(_target, read.arg0()); 369 EXPECT_EQ(_level, read.arg1()); 370 EXPECT_EQ(_internalformat, read.arg2()); 371 EXPECT_EQ(_width, read.arg3()); 372 EXPECT_EQ(_height, read.arg4()); 373 EXPECT_EQ(_border, read.arg5()); 374 EXPECT_EQ(_format, read.arg6()); 375 EXPECT_EQ(_type, read.arg7()); 376 377 EXPECT_TRUE(read.has_data()); 378 uint32_t dataLen = 0; 379 const unsigned char * data = dbg->Decompress(read.data().data(), 380 read.data().length(), &dataLen); 381 EXPECT_EQ(sizeof(_pixels), dataLen); 382 if (sizeof(_pixels) == dataLen) 383 EXPECT_EQ(0, memcmp(_pixels, data, sizeof(_pixels))); 384 385 Read(read); 386 EXPECT_EQ(read.glTexImage2D, read.function()); 387 EXPECT_EQ(read.AfterCall, read.type()); 388 389 CheckNoAvailable(); 390 } 391 392 TEST_F(SocketContextTest, CopyTexImage2D) 393 { 394 static const GLenum _target = GL_TEXTURE_2D; 395 static const GLint _level = 1, _internalformat = GL_RGBA; 396 static const GLint _x = 9, _y = 99; 397 static const GLsizei _width = 2, _height = 3; 398 static const GLint _border = 333; 399 static const int _pixels [_width * _height] = {11, 22, 33, 44, 55, 66}; 400 static unsigned int copyTexImage2D, readPixels; 401 copyTexImage2D = 0, readPixels = 0; 402 403 struct Caller { 404 static void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, 405 GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { 406 EXPECT_EQ(_target, target); 407 EXPECT_EQ(_level, level); 408 EXPECT_EQ(_internalformat, internalformat); 409 EXPECT_EQ(_x, x); 410 EXPECT_EQ(_y, y); 411 EXPECT_EQ(_width, width); 412 EXPECT_EQ(_height, height); 413 EXPECT_EQ(_border, border); 414 copyTexImage2D++; 415 } 416 static void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, 417 GLenum format, GLenum type, GLvoid* pixels) { 418 EXPECT_EQ(_x, x); 419 EXPECT_EQ(_y, y); 420 EXPECT_EQ(_width, width); 421 EXPECT_EQ(_height, height); 422 EXPECT_EQ(GL_RGBA, format); 423 EXPECT_EQ(GL_UNSIGNED_BYTE, type); 424 ASSERT_TRUE(pixels != NULL); 425 memcpy(pixels, _pixels, sizeof(_pixels)); 426 readPixels++; 427 } 428 } caller; 429 glesv2debugger::Message msg, read, cmd; 430 hooks.gl.glCopyTexImage2D = caller.CopyTexImage2D; 431 hooks.gl.glReadPixels = caller.ReadPixels; 432 dbg->expectResponse.Bit(msg.glCopyTexImage2D, false); 433 434 Debug_glCopyTexImage2D(_target, _level, _internalformat, _x, _y, _width, _height, 435 _border); 436 ASSERT_EQ(1, copyTexImage2D); 437 ASSERT_EQ(1, readPixels); 438 439 Read(read); 440 EXPECT_EQ(read.glCopyTexImage2D, read.function()); 441 EXPECT_EQ(read.BeforeCall, read.type()); 442 EXPECT_EQ(_target, read.arg0()); 443 EXPECT_EQ(_level, read.arg1()); 444 EXPECT_EQ(_internalformat, read.arg2()); 445 EXPECT_EQ(_x, read.arg3()); 446 EXPECT_EQ(_y, read.arg4()); 447 EXPECT_EQ(_width, read.arg5()); 448 EXPECT_EQ(_height, read.arg6()); 449 EXPECT_EQ(_border, read.arg7()); 450 451 EXPECT_TRUE(read.has_data()); 452 EXPECT_EQ(read.ReferencedImage, read.data_type()); 453 EXPECT_EQ(GL_RGBA, read.pixel_format()); 454 EXPECT_EQ(GL_UNSIGNED_BYTE, read.pixel_type()); 455 uint32_t dataLen = 0; 456 unsigned char * const data = dbg->Decompress(read.data().data(), 457 read.data().length(), &dataLen); 458 ASSERT_EQ(sizeof(_pixels), dataLen); 459 for (unsigned i = 0; i < sizeof(_pixels) / sizeof(*_pixels); i++) 460 EXPECT_EQ(_pixels[i], ((const int *)data)[i]) << "xor with 0 ref is identity"; 461 free(data); 462 463 Read(read); 464 EXPECT_EQ(read.glCopyTexImage2D, read.function()); 465 EXPECT_EQ(read.AfterCall, read.type()); 466 467 CheckNoAvailable(); 468 } 469