Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / memory_program_cache_unittest.cc
1 // Copyright (c) 2012 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/memory_program_cache.h"
6
7 #include "base/bind.h"
8 #include "gpu/command_buffer/common/gles2_cmd_format.h"
9 #include "gpu/command_buffer/service/gl_utils.h"
10 #include "gpu/command_buffer/service/gpu_service_test.h"
11 #include "gpu/command_buffer/service/shader_manager.h"
12 #include "gpu/command_buffer/service/shader_translator.h"
13 #include "gpu/command_buffer/service/test_helper.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/gl/gl_bindings.h"
16 #include "ui/gl/gl_mock.h"
17
18 using ::testing::_;
19 using ::testing::ElementsAreArray;
20 using ::testing::Invoke;
21 using ::testing::SetArgPointee;
22 using ::testing::SetArrayArgument;
23
24 namespace {
25 typedef gpu::gles2::ShaderTranslator::VariableMap VariableMap;
26 }  // anonymous namespace
27
28 namespace gpu {
29 namespace gles2 {
30
31 class ProgramBinaryEmulator {
32  public:
33   ProgramBinaryEmulator(GLsizei length,
34                         GLenum format,
35                         const char* binary)
36       : length_(length),
37         format_(format),
38         binary_(binary) { }
39
40   void GetProgramBinary(GLuint program,
41                         GLsizei buffer_size,
42                         GLsizei* length,
43                         GLenum* format,
44                         GLvoid* binary) {
45     if (length) {
46       *length = length_;
47     }
48     *format = format_;
49     memcpy(binary, binary_, length_);
50   }
51
52   void ProgramBinary(GLuint program,
53                      GLenum format,
54                      const GLvoid* binary,
55                      GLsizei length) {
56     // format and length are verified by matcher
57     EXPECT_EQ(0, memcmp(binary_, binary, length));
58   }
59
60   GLsizei length() const { return length_; }
61   GLenum format() const { return format_; }
62   const char* binary() const { return binary_; }
63
64  private:
65   GLsizei length_;
66   GLenum format_;
67   const char* binary_;
68 };
69
70 class MemoryProgramCacheTest : public GpuServiceTest {
71  public:
72   static const size_t kCacheSizeBytes = 1024;
73   static const GLuint kVertexShaderClientId = 90;
74   static const GLuint kVertexShaderServiceId = 100;
75   static const GLuint kFragmentShaderClientId = 91;
76   static const GLuint kFragmentShaderServiceId = 100;
77
78   MemoryProgramCacheTest()
79       : cache_(new MemoryProgramCache(kCacheSizeBytes)),
80         vertex_shader_(NULL),
81         fragment_shader_(NULL),
82         shader_cache_count_(0) { }
83   virtual ~MemoryProgramCacheTest() {
84     shader_manager_.Destroy(false);
85   }
86
87   void ShaderCacheCb(const std::string& key, const std::string& shader) {
88     shader_cache_count_++;
89     shader_cache_shader_ = shader;
90   }
91
92   int32 shader_cache_count() { return shader_cache_count_; }
93   const std::string& shader_cache_shader() { return shader_cache_shader_; }
94
95  protected:
96   virtual void SetUp() {
97     GpuServiceTest::SetUp();
98
99     vertex_shader_ = shader_manager_.CreateShader(kVertexShaderClientId,
100                                                   kVertexShaderServiceId,
101                                                   GL_VERTEX_SHADER);
102     fragment_shader_ = shader_manager_.CreateShader(
103         kFragmentShaderClientId,
104         kFragmentShaderServiceId,
105         GL_FRAGMENT_SHADER);
106     ASSERT_TRUE(vertex_shader_ != NULL);
107     ASSERT_TRUE(fragment_shader_ != NULL);
108     typedef ShaderTranslatorInterface::VariableInfo VariableInfo;
109     typedef ShaderTranslator::VariableMap VariableMap;
110     VariableMap vertex_attrib_map;
111     VariableMap vertex_uniform_map;
112     VariableMap vertex_varying_map;
113     VariableMap fragment_attrib_map;
114     VariableMap fragment_uniform_map;
115     VariableMap fragment_varying_map;
116
117     vertex_attrib_map["a"] = VariableInfo(1, 34, SH_PRECISION_LOWP, 0, "a");
118     vertex_uniform_map["a"] = VariableInfo(0, 10, SH_PRECISION_MEDIUMP, 1, "a");
119     vertex_uniform_map["b"] = VariableInfo(2, 3114, SH_PRECISION_HIGHP, 1, "b");
120     vertex_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, 1, "c");
121     fragment_attrib_map["jjjbb"] =
122         VariableInfo(463, 1114, SH_PRECISION_MEDIUMP, 0, "jjjbb");
123     fragment_uniform_map["k"] =
124         VariableInfo(10, 34413, SH_PRECISION_MEDIUMP, 1, "k");
125     fragment_varying_map["c"] = VariableInfo(3, 2, SH_PRECISION_HIGHP, 1, "c");
126
127     vertex_shader_->set_source("bbbalsldkdkdkd");
128     fragment_shader_->set_source("bbbal   sldkdkdkas 134 ad");
129
130     TestHelper::SetShaderStates(
131         gl_.get(), vertex_shader_, true, NULL, NULL,
132         &vertex_attrib_map, &vertex_uniform_map, &vertex_varying_map,
133         NULL);
134     TestHelper::SetShaderStates(
135         gl_.get(), fragment_shader_, true, NULL, NULL,
136         &fragment_attrib_map, &fragment_uniform_map, &fragment_varying_map,
137         NULL);
138   }
139
140   void SetExpectationsForSaveLinkedProgram(
141       const GLint program_id,
142       ProgramBinaryEmulator* emulator) const {
143     EXPECT_CALL(*gl_.get(),
144                 GetProgramiv(program_id, GL_PROGRAM_BINARY_LENGTH_OES, _))
145         .WillOnce(SetArgPointee<2>(emulator->length()));
146     EXPECT_CALL(*gl_.get(),
147                 GetProgramBinary(program_id, emulator->length(), _, _, _))
148         .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::GetProgramBinary));
149   }
150
151   void SetExpectationsForLoadLinkedProgram(
152       const GLint program_id,
153       ProgramBinaryEmulator* emulator) const {
154     EXPECT_CALL(*gl_.get(),
155                 ProgramBinary(program_id,
156                               emulator->format(),
157                               _,
158                               emulator->length()))
159         .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::ProgramBinary));
160     EXPECT_CALL(*gl_.get(),
161                 GetProgramiv(program_id, GL_LINK_STATUS, _))
162                 .WillOnce(SetArgPointee<2>(GL_TRUE));
163   }
164
165   void SetExpectationsForLoadLinkedProgramFailure(
166       const GLint program_id,
167       ProgramBinaryEmulator* emulator) const {
168     EXPECT_CALL(*gl_.get(),
169                 ProgramBinary(program_id,
170                               emulator->format(),
171                               _,
172                               emulator->length()))
173         .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::ProgramBinary));
174     EXPECT_CALL(*gl_.get(),
175                 GetProgramiv(program_id, GL_LINK_STATUS, _))
176                 .WillOnce(SetArgPointee<2>(GL_FALSE));
177   }
178
179   scoped_ptr<MemoryProgramCache> cache_;
180   ShaderManager shader_manager_;
181   Shader* vertex_shader_;
182   Shader* fragment_shader_;
183   int32 shader_cache_count_;
184   std::string shader_cache_shader_;
185 };
186
187 TEST_F(MemoryProgramCacheTest, CacheSave) {
188   const GLenum kFormat = 1;
189   const int kProgramId = 10;
190   const int kBinaryLength = 20;
191   char test_binary[kBinaryLength];
192   for (int i = 0; i < kBinaryLength; ++i) {
193     test_binary[i] = i;
194   }
195   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
196
197   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
198   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
199                             fragment_shader_, NULL, NULL,
200                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
201                                        base::Unretained(this)));
202
203   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
204       vertex_shader_->signature_source(),
205       NULL,
206       fragment_shader_->signature_source(),
207       NULL,
208       NULL));
209   EXPECT_EQ(1, shader_cache_count());
210 }
211
212 TEST_F(MemoryProgramCacheTest, LoadProgram) {
213   const GLenum kFormat = 1;
214   const int kProgramId = 10;
215   const int kBinaryLength = 20;
216   char test_binary[kBinaryLength];
217   for (int i = 0; i < kBinaryLength; ++i) {
218     test_binary[i] = i;
219   }
220   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
221
222   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
223   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
224                             fragment_shader_, NULL, NULL,
225                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
226                                        base::Unretained(this)));
227
228   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
229       vertex_shader_->signature_source(),
230       NULL,
231       fragment_shader_->signature_source(),
232       NULL,
233       NULL));
234   EXPECT_EQ(1, shader_cache_count());
235
236   cache_->Clear();
237
238   cache_->LoadProgram(shader_cache_shader());
239   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
240       vertex_shader_->signature_source(),
241       NULL,
242       fragment_shader_->signature_source(),
243       NULL,
244       NULL));
245 }
246
247 TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) {
248   const GLenum kFormat = 1;
249   const int kProgramId = 10;
250   const int kBinaryLength = 20;
251   char test_binary[kBinaryLength];
252   for (int i = 0; i < kBinaryLength; ++i) {
253     test_binary[i] = i;
254   }
255   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
256
257   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
258   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
259                             fragment_shader_, NULL, NULL,
260                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
261                                        base::Unretained(this)));
262   EXPECT_EQ(1, shader_cache_count());
263
264   VariableMap vertex_attrib_map = vertex_shader_->attrib_map();
265   VariableMap vertex_uniform_map = vertex_shader_->uniform_map();
266   VariableMap vertex_varying_map = vertex_shader_->varying_map();
267   VariableMap fragment_attrib_map = fragment_shader_->attrib_map();
268   VariableMap fragment_uniform_map = fragment_shader_->uniform_map();
269   VariableMap fragment_varying_map = fragment_shader_->varying_map();
270
271   vertex_shader_->set_attrib_map(VariableMap());
272   vertex_shader_->set_uniform_map(VariableMap());
273   vertex_shader_->set_varying_map(VariableMap());
274   fragment_shader_->set_attrib_map(VariableMap());
275   fragment_shader_->set_uniform_map(VariableMap());
276   fragment_shader_->set_varying_map(VariableMap());
277
278   SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
279
280   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
281       kProgramId,
282       vertex_shader_,
283       NULL,
284       fragment_shader_,
285       NULL,
286       NULL,
287       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
288                  base::Unretained(this))));
289
290   // apparently the hash_map implementation on android doesn't have the
291   // equality operator
292 #if !defined(OS_ANDROID)
293   EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map());
294   EXPECT_EQ(vertex_uniform_map, vertex_shader_->uniform_map());
295   EXPECT_EQ(vertex_varying_map, vertex_shader_->varying_map());
296   EXPECT_EQ(fragment_attrib_map, fragment_shader_->attrib_map());
297   EXPECT_EQ(fragment_uniform_map, fragment_shader_->uniform_map());
298   EXPECT_EQ(fragment_varying_map, fragment_shader_->varying_map());
299 #endif
300 }
301
302 TEST_F(MemoryProgramCacheTest, LoadProgramMatchesSave) {
303   const GLenum kFormat = 1;
304   const int kProgramId = 10;
305   const int kBinaryLength = 20;
306   char test_binary[kBinaryLength];
307   for (int i = 0; i < kBinaryLength; ++i) {
308     test_binary[i] = i;
309   }
310   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
311
312   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
313   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
314                             fragment_shader_, NULL, NULL,
315                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
316                                        base::Unretained(this)));
317   EXPECT_EQ(1, shader_cache_count());
318
319   VariableMap vertex_attrib_map = vertex_shader_->attrib_map();
320   VariableMap vertex_uniform_map = vertex_shader_->uniform_map();
321   VariableMap vertex_varying_map = vertex_shader_->varying_map();
322   VariableMap fragment_attrib_map = fragment_shader_->attrib_map();
323   VariableMap fragment_uniform_map = fragment_shader_->uniform_map();
324   VariableMap fragment_varying_map = fragment_shader_->varying_map();
325
326   vertex_shader_->set_attrib_map(VariableMap());
327   vertex_shader_->set_uniform_map(VariableMap());
328   vertex_shader_->set_varying_map(VariableMap());
329   fragment_shader_->set_attrib_map(VariableMap());
330   fragment_shader_->set_uniform_map(VariableMap());
331   fragment_shader_->set_varying_map(VariableMap());
332
333   SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
334
335   cache_->Clear();
336   cache_->LoadProgram(shader_cache_shader());
337
338   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
339       kProgramId,
340       vertex_shader_,
341       NULL,
342       fragment_shader_,
343       NULL,
344       NULL,
345       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
346                  base::Unretained(this))));
347
348   // apparently the hash_map implementation on android doesn't have the
349   // equality operator
350 #if !defined(OS_ANDROID)
351   EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map());
352   EXPECT_EQ(vertex_uniform_map, vertex_shader_->uniform_map());
353   EXPECT_EQ(vertex_varying_map, vertex_shader_->varying_map());
354   EXPECT_EQ(fragment_attrib_map, fragment_shader_->attrib_map());
355   EXPECT_EQ(fragment_uniform_map, fragment_shader_->uniform_map());
356   EXPECT_EQ(fragment_varying_map, fragment_shader_->varying_map());
357 #endif
358 }
359
360 TEST_F(MemoryProgramCacheTest, LoadFailOnLinkFalse) {
361   const GLenum kFormat = 1;
362   const int kProgramId = 10;
363   const int kBinaryLength = 20;
364   char test_binary[kBinaryLength];
365   for (int i = 0; i < kBinaryLength; ++i) {
366     test_binary[i] = i;
367   }
368   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
369
370   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
371   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
372                             fragment_shader_, NULL, NULL,
373                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
374                                        base::Unretained(this)));
375
376   SetExpectationsForLoadLinkedProgramFailure(kProgramId, &emulator);
377   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
378       kProgramId,
379       vertex_shader_,
380       NULL,
381       fragment_shader_,
382       NULL,
383       NULL,
384       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
385                  base::Unretained(this))));
386 }
387
388 TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentSource) {
389   const GLenum kFormat = 1;
390   const int kProgramId = 10;
391   const int kBinaryLength = 20;
392   char test_binary[kBinaryLength];
393   for (int i = 0; i < kBinaryLength; ++i) {
394     test_binary[i] = i;
395   }
396   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
397
398   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
399   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
400                             fragment_shader_, NULL, NULL,
401                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
402                                        base::Unretained(this)));
403
404   const std::string vertex_orig_source = vertex_shader_->signature_source();
405   vertex_shader_->set_source("different!");
406   TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
407   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
408       kProgramId,
409       vertex_shader_,
410       NULL,
411       fragment_shader_,
412       NULL,
413       NULL,
414       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
415                  base::Unretained(this))));
416
417   vertex_shader_->set_source(vertex_orig_source);
418   TestHelper::SetShaderStates(gl_.get(), vertex_shader_, true);
419   fragment_shader_->set_source("different!");
420   TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
421   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
422       kProgramId,
423       vertex_shader_,
424       NULL,
425       fragment_shader_,
426       NULL,
427       NULL,
428       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
429                  base::Unretained(this))));
430 }
431
432 TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentMap) {
433   const GLenum kFormat = 1;
434   const int kProgramId = 10;
435   const int kBinaryLength = 20;
436   char test_binary[kBinaryLength];
437   for (int i = 0; i < kBinaryLength; ++i) {
438     test_binary[i] = i;
439   }
440   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
441
442   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
443   ProgramCache::LocationMap binding_map;
444   binding_map["test"] = 512;
445   cache_->SaveLinkedProgram(kProgramId,
446                             vertex_shader_,
447                             NULL,
448                             fragment_shader_,
449                             NULL,
450                             &binding_map,
451                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
452                                        base::Unretained(this)));
453
454   binding_map["different!"] = 59;
455   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
456       kProgramId,
457       vertex_shader_,
458       NULL,
459       fragment_shader_,
460       NULL,
461       &binding_map,
462       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
463                  base::Unretained(this))));
464   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
465       kProgramId,
466       vertex_shader_,
467       NULL,
468       fragment_shader_,
469       NULL,
470       NULL,
471       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
472                  base::Unretained(this))));
473 }
474
475 TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) {
476   const GLenum kFormat = 1;
477   const int kProgramId = 10;
478   const int kBinaryLength = 20;
479   char test_binary[kBinaryLength];
480   for (int i = 0; i < kBinaryLength; ++i) {
481     test_binary[i] = i;
482   }
483   ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary);
484
485
486   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
487   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
488                             fragment_shader_, NULL, NULL,
489                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
490                                        base::Unretained(this)));
491
492   const int kEvictingProgramId = 11;
493   const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1;
494
495   // save old source and modify for new program
496   const std::string& old_source = fragment_shader_->signature_source();
497   fragment_shader_->set_source("al sdfkjdk");
498   TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
499
500   scoped_ptr<char[]> bigTestBinary =
501       scoped_ptr<char[]>(new char[kEvictingBinaryLength]);
502   for (size_t i = 0; i < kEvictingBinaryLength; ++i) {
503     bigTestBinary[i] = i % 250;
504   }
505   ProgramBinaryEmulator emulator2(kEvictingBinaryLength,
506                                   kFormat,
507                                   bigTestBinary.get());
508
509   SetExpectationsForSaveLinkedProgram(kEvictingProgramId, &emulator2);
510   cache_->SaveLinkedProgram(kEvictingProgramId,
511                             vertex_shader_,
512                             NULL,
513                             fragment_shader_,
514                             NULL,
515                             NULL,
516                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
517                                        base::Unretained(this)));
518
519   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
520       vertex_shader_->signature_source(),
521       NULL,
522       fragment_shader_->signature_source(),
523       NULL,
524       NULL));
525   EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
526       old_source,
527       NULL,
528       fragment_shader_->signature_source(),
529       NULL,
530       NULL));
531 }
532
533 TEST_F(MemoryProgramCacheTest, SaveCorrectProgram) {
534   const GLenum kFormat = 1;
535   const int kProgramId = 10;
536   const int kBinaryLength = 20;
537   char test_binary[kBinaryLength];
538   for (int i = 0; i < kBinaryLength; ++i) {
539     test_binary[i] = i;
540   }
541   ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary);
542
543   vertex_shader_->set_source("different!");
544   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
545   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
546                             fragment_shader_, NULL, NULL,
547                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
548                                        base::Unretained(this)));
549
550   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
551       vertex_shader_->signature_source(),
552       NULL,
553       fragment_shader_->signature_source(),
554       NULL,
555       NULL));
556 }
557
558 TEST_F(MemoryProgramCacheTest, LoadCorrectProgram) {
559   const GLenum kFormat = 1;
560   const int kProgramId = 10;
561   const int kBinaryLength = 20;
562   char test_binary[kBinaryLength];
563   for (int i = 0; i < kBinaryLength; ++i) {
564     test_binary[i] = i;
565   }
566   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
567
568   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
569   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
570                             fragment_shader_, NULL, NULL,
571                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
572                                        base::Unretained(this)));
573
574   EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
575       vertex_shader_->signature_source(),
576       NULL,
577       fragment_shader_->signature_source(),
578       NULL,
579       NULL));
580
581   SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
582
583   fragment_shader_->set_source("different!");
584   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
585       kProgramId,
586       vertex_shader_,
587       NULL,
588       fragment_shader_,
589       NULL,
590       NULL,
591       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
592                  base::Unretained(this))));
593 }
594
595 TEST_F(MemoryProgramCacheTest, OverwriteOnNewSave) {
596   const GLenum kFormat = 1;
597   const int kProgramId = 10;
598   const int kBinaryLength = 20;
599   char test_binary[kBinaryLength];
600   for (int i = 0; i < kBinaryLength; ++i) {
601     test_binary[i] = i;
602   }
603   ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
604
605   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
606   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
607                             fragment_shader_, NULL, NULL,
608                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
609                                        base::Unretained(this)));
610
611
612   char test_binary2[kBinaryLength];
613   for (int i = 0; i < kBinaryLength; ++i) {
614     test_binary2[i] = (i*2) % 250;
615   }
616   ProgramBinaryEmulator emulator2(kBinaryLength, kFormat, test_binary2);
617   SetExpectationsForSaveLinkedProgram(kProgramId, &emulator2);
618   cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
619                             fragment_shader_, NULL, NULL,
620                             base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
621                                        base::Unretained(this)));
622
623   SetExpectationsForLoadLinkedProgram(kProgramId, &emulator2);
624   EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
625       kProgramId,
626       vertex_shader_,
627       NULL,
628       fragment_shader_,
629       NULL,
630       NULL,
631       base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
632                  base::Unretained(this))));
633 }
634
635 }  // namespace gles2
636 }  // namespace gpu