1// Copyright 2013 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 "base/pickle.h"
6#include "components/nacl/browser/nacl_validation_cache.h"
7#include "testing/gtest/include/gtest/gtest.h"
8
9namespace nacl {
10
11const char key1[65] =
12    "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
13const char key2[65] =
14    "a 64-byte string of various junk................................";
15const char sig1[33] = "0123456789ABCDEF0123456789ABCDEF";
16const char sig2[33] = "a 32-byte string of various junk";
17
18class NaClValidationCacheTest : public ::testing::Test {
19 protected:
20  NaClValidationCache cache1;
21  NaClValidationCache cache2;
22
23  virtual void SetUp() {
24    // The compiler chokes if std::string(key1) is passed directly as an arg.
25    std::string key(key1);
26    cache1.SetValidationCacheKey(key);
27    cache2.SetValidationCacheKey(key);
28  }
29
30  bool IsIdentical(const NaClValidationCache& a,
31                   const NaClValidationCache& b) const {
32    if (a.GetValidationCacheKey() != b.GetValidationCacheKey())
33      return false;
34    if (a.size() != b.size())
35      return false;
36    return a.GetContents() == b.GetContents();
37  }
38};
39
40TEST_F(NaClValidationCacheTest, Sanity) {
41  ASSERT_EQ(0, (int) cache1.size());
42  ASSERT_FALSE(cache1.QueryKnownToValidate(sig1, true));
43  ASSERT_FALSE(cache1.QueryKnownToValidate(sig2, true));
44}
45
46TEST_F(NaClValidationCacheTest, Sig1) {
47  cache1.SetKnownToValidate(sig1);
48  ASSERT_EQ(1, (int) cache1.size());
49  ASSERT_TRUE(cache1.QueryKnownToValidate(sig1, true));
50  ASSERT_FALSE(cache1.QueryKnownToValidate(sig2, true));
51}
52
53TEST_F(NaClValidationCacheTest, Sig2) {
54  cache1.SetKnownToValidate(sig2);
55  ASSERT_EQ(1, (int) cache1.size());
56  ASSERT_FALSE(cache1.QueryKnownToValidate(sig1, true));
57  ASSERT_TRUE(cache1.QueryKnownToValidate(sig2, true));
58}
59
60TEST_F(NaClValidationCacheTest, SigBoth) {
61  cache1.SetKnownToValidate(sig1);
62  cache1.SetKnownToValidate(sig2);
63  ASSERT_EQ(2, (int) cache1.size());
64  ASSERT_TRUE(cache1.QueryKnownToValidate(sig1, true));
65  ASSERT_TRUE(cache1.QueryKnownToValidate(sig2, true));
66}
67
68TEST_F(NaClValidationCacheTest, DoubleSet) {
69  cache1.SetKnownToValidate(sig1);
70  cache1.SetKnownToValidate(sig1);
71  ASSERT_EQ(1, (int) cache1.size());
72  ASSERT_TRUE(cache1.QueryKnownToValidate(sig1, true));
73}
74
75TEST_F(NaClValidationCacheTest, EmptyIdentical) {
76  ASSERT_TRUE(IsIdentical(cache1, cache2));
77}
78
79TEST_F(NaClValidationCacheTest, DifferentKeysNotIdentical) {
80  std::string key(key2);
81  cache2.SetValidationCacheKey(key);
82  ASSERT_FALSE(IsIdentical(cache1, cache2));
83}
84
85
86TEST_F(NaClValidationCacheTest, DifferentSizesNotIdentical) {
87  cache1.SetKnownToValidate(sig1);
88
89  ASSERT_FALSE(IsIdentical(cache1, cache2));
90}
91
92TEST_F(NaClValidationCacheTest, SameSigsIdentical) {
93  cache1.SetKnownToValidate(sig1);
94
95  cache2.SetKnownToValidate(sig1);
96
97  ASSERT_TRUE(IsIdentical(cache1, cache2));
98}
99
100TEST_F(NaClValidationCacheTest, DifferentSigsNotIdentical) {
101  cache1.SetKnownToValidate(sig1);
102
103  cache2.SetKnownToValidate(sig2);
104
105  ASSERT_FALSE(IsIdentical(cache1, cache2));
106}
107
108TEST_F(NaClValidationCacheTest, InOrderIdentical) {
109  cache1.SetKnownToValidate(sig1);
110  cache1.SetKnownToValidate(sig2);
111
112  cache2.SetKnownToValidate(sig1);
113  cache2.SetKnownToValidate(sig2);
114
115  ASSERT_TRUE(IsIdentical(cache1, cache2));
116}
117
118TEST_F(NaClValidationCacheTest, QueryReorders) {
119  cache1.SetKnownToValidate(sig1);
120  cache1.SetKnownToValidate(sig2);
121
122  cache2.SetKnownToValidate(sig2);
123  cache2.SetKnownToValidate(sig1);
124
125  ASSERT_FALSE(IsIdentical(cache1, cache2));
126  cache2.QueryKnownToValidate(sig2, true);
127  ASSERT_TRUE(IsIdentical(cache1, cache2));
128}
129
130TEST_F(NaClValidationCacheTest, ForceNoReorder) {
131  cache1.SetKnownToValidate(sig1);
132  cache1.SetKnownToValidate(sig2);
133
134  cache2.SetKnownToValidate(sig2);
135  cache2.SetKnownToValidate(sig1);
136
137  cache2.QueryKnownToValidate(sig2, false);
138  ASSERT_FALSE(IsIdentical(cache1, cache2));
139}
140
141TEST_F(NaClValidationCacheTest, SerializeDeserialize) {
142  std::string key(key2);
143  cache1.SetValidationCacheKey(key);
144  cache1.SetKnownToValidate(sig1);
145  cache1.SetKnownToValidate(sig2);
146
147  Pickle pickle;
148  cache1.Serialize(&pickle);
149  ASSERT_TRUE(cache2.Deserialize(&pickle));
150  ASSERT_EQ(2, (int) cache2.size());
151  ASSERT_TRUE(IsIdentical(cache1, cache2));
152}
153
154TEST_F(NaClValidationCacheTest, SerializeDeserializeTruncated) {
155  std::string key(key2);
156  cache1.SetValidationCacheKey(key);
157  cache1.SetKnownToValidate(sig1);
158  cache1.SetKnownToValidate(sig2);
159
160  Pickle pickle;
161  cache1.Serialize(&pickle);
162  Pickle truncated(static_cast<const char*>(pickle.data()), pickle.size()-20);
163  ASSERT_FALSE(cache2.Deserialize(&truncated));
164  ASSERT_EQ(0, (int) cache2.size());
165}
166
167TEST_F(NaClValidationCacheTest, DeserializeBadKey) {
168  std::string key(sig1); // Too short, will cause the deserialization to error.
169  cache1.SetValidationCacheKey(key);
170  cache1.SetKnownToValidate(sig1);
171  cache1.SetKnownToValidate(sig2);
172
173  Pickle pickle;
174  cache1.Serialize(&pickle);
175  ASSERT_FALSE(cache2.Deserialize(&pickle));
176  ASSERT_EQ(0, (int) cache2.size());
177}
178
179TEST_F(NaClValidationCacheTest, DeserializeNothing) {
180  cache1.SetKnownToValidate(sig1);
181  Pickle pickle("", 0);
182  ASSERT_FALSE(cache1.Deserialize(&pickle));
183  ASSERT_EQ(0, (int) cache1.size());
184}
185
186TEST_F(NaClValidationCacheTest, DeserializeJunk) {
187  cache1.SetKnownToValidate(sig1);
188  Pickle pickle(key1, strlen(key1));
189  ASSERT_FALSE(cache1.Deserialize(&pickle));
190  ASSERT_EQ(0, (int) cache1.size());
191}
192
193}
194