• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 package com.google.crypto.tink.internal;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static java.nio.charset.StandardCharsets.UTF_8;
21 import static org.junit.Assert.assertThrows;
22 
23 import com.google.crypto.tink.InsecureSecretKeyAccess;
24 import com.google.crypto.tink.Key;
25 import com.google.crypto.tink.Parameters;
26 import com.google.crypto.tink.SecretKeyAccess;
27 import com.google.crypto.tink.util.Bytes;
28 import com.google.errorprone.annotations.Immutable;
29 import java.security.GeneralSecurityException;
30 import javax.annotation.Nullable;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.junit.runners.JUnit4;
34 
35 /** Unit tests for {@link SerializationRegistry}. */
36 @RunWith(JUnit4.class)
37 public final class SerializationRegistryTest {
38   // ===============================================================================================
39   // SETUP:
40   // We create 2 different key classes (TestKey1, TestKey2) and two different serialization classes
41   // (TestSerializationA, TestSerializationB), and provide ways to parse and serialize both keys
42   // with both methods.
43   //
44   // For this, we provide the methods serializeKey{1,2}to{A,B} and parseKey{A,B}to{1,2}. The method
45   // serializeKeyBto1 then uses the constant B_1 in the object identifier.
46   //
47   // Note that calling these multiple times will give different objects (which allows us to test
48   // that registering different objects for the same task fails).
49   //
50   // We pick the object identifiers so that they are unique per serialization type, but *not*
51   // unique globally (since different serialization types may use the same object identifiers for
52   // different key types).
53   // ===============================================================================================
54 
55   private static final SecretKeyAccess ACCESS = InsecureSecretKeyAccess.get();
56 
57   private static final Bytes A_1 = Bytes.copyFrom("0".getBytes(UTF_8));
58   private static final Bytes A_2 = Bytes.copyFrom("1".getBytes(UTF_8));
59   private static final Bytes B_1 = Bytes.copyFrom("1".getBytes(UTF_8));
60   private static final Bytes B_2 = Bytes.copyFrom("2".getBytes(UTF_8));
61 
62   @Immutable
63   private static final class TestParameters1 extends Parameters {
64     @Override
hasIdRequirement()65     public boolean hasIdRequirement() {
66       return false;
67     }
68   }
69 
70   @Immutable
71   private static final class TestParameters2 extends Parameters {
72     @Override
hasIdRequirement()73     public boolean hasIdRequirement() {
74       return false;
75     }
76   }
77 
78   @Immutable
79   private static final class TestKey1 extends Key {
80     @Override
getParameters()81     public Parameters getParameters() {
82       throw new UnsupportedOperationException("Not needed in test");
83     }
84 
85     @Override
86     @Nullable
getIdRequirementOrNull()87     public Integer getIdRequirementOrNull() {
88       throw new UnsupportedOperationException("Not needed in test");
89     }
90 
91     @Override
equalsKey(Key other)92     public boolean equalsKey(Key other) {
93       throw new UnsupportedOperationException("Not needed in test");
94     }
95   }
96 
97   @Immutable
98   private static final class TestKey2 extends Key {
99     @Override
getParameters()100     public Parameters getParameters() {
101       throw new UnsupportedOperationException("Not needed in test");
102     }
103 
104     @Override
105     @Nullable
getIdRequirementOrNull()106     public Integer getIdRequirementOrNull() {
107       throw new UnsupportedOperationException("Not needed in test");
108     }
109 
110     @Override
equalsKey(Key other)111     public boolean equalsKey(Key other) {
112       throw new UnsupportedOperationException("Not needed in test");
113     }
114   }
115 
116   @Immutable
117   private static final class TestSerializationA implements Serialization {
TestSerializationA(Bytes objectIdentifier)118     public TestSerializationA(Bytes objectIdentifier) {
119       this.objectIdentifier = objectIdentifier;
120     }
121 
122     private final Bytes objectIdentifier;
123 
124     @Override
getObjectIdentifier()125     public Bytes getObjectIdentifier() {
126       return objectIdentifier;
127     }
128   }
129 
130   @Immutable
131   private static final class TestSerializationB implements Serialization {
TestSerializationB(Bytes objectIdentifier)132     public TestSerializationB(Bytes objectIdentifier) {
133       this.objectIdentifier = objectIdentifier;
134     }
135 
136     private final Bytes objectIdentifier;
137 
138     @Override
getObjectIdentifier()139     public Bytes getObjectIdentifier() {
140       return objectIdentifier;
141     }
142   }
143 
serializeKey1ToA(TestKey1 key, @Nullable SecretKeyAccess access)144   private static TestSerializationA serializeKey1ToA(TestKey1 key, @Nullable SecretKeyAccess access)
145       throws GeneralSecurityException {
146     SecretKeyAccess.requireAccess(access);
147     return new TestSerializationA(A_1);
148   }
149 
serializeKey2ToA(TestKey2 key, @Nullable SecretKeyAccess access)150   private static TestSerializationA serializeKey2ToA(TestKey2 key, @Nullable SecretKeyAccess access)
151       throws GeneralSecurityException {
152     SecretKeyAccess.requireAccess(access);
153     return new TestSerializationA(A_2);
154   }
155 
serializeKey1ToB(TestKey1 key, @Nullable SecretKeyAccess access)156   private static TestSerializationB serializeKey1ToB(TestKey1 key, @Nullable SecretKeyAccess access)
157       throws GeneralSecurityException {
158     SecretKeyAccess.requireAccess(access);
159     return new TestSerializationB(B_1);
160   }
161 
serializeKey2ToB(TestKey2 key, @Nullable SecretKeyAccess access)162   private static TestSerializationB serializeKey2ToB(TestKey2 key, @Nullable SecretKeyAccess access)
163       throws GeneralSecurityException {
164     SecretKeyAccess.requireAccess(access);
165     return new TestSerializationB(B_2);
166   }
167 
parseAToKey1( TestSerializationA serialization, @Nullable SecretKeyAccess access)168   private static Key parseAToKey1(
169       TestSerializationA serialization, @Nullable SecretKeyAccess access)
170       throws GeneralSecurityException {
171     if (!A_1.equals(serialization.getObjectIdentifier())) {
172       throw new GeneralSecurityException("Wrong object identifier");
173     }
174     SecretKeyAccess.requireAccess(access);
175     return new TestKey1();
176   }
177 
parseAToKey2( TestSerializationA serialization, @Nullable SecretKeyAccess access)178   private static Key parseAToKey2(
179       TestSerializationA serialization, @Nullable SecretKeyAccess access)
180       throws GeneralSecurityException {
181     if (!A_2.equals(serialization.getObjectIdentifier())) {
182       throw new GeneralSecurityException("Wrong object identifier");
183     }
184     SecretKeyAccess.requireAccess(access);
185     return new TestKey2();
186   }
187 
parseBToKey1( TestSerializationB serialization, @Nullable SecretKeyAccess access)188   private static Key parseBToKey1(
189       TestSerializationB serialization, @Nullable SecretKeyAccess access)
190       throws GeneralSecurityException {
191     if (!B_1.equals(serialization.getObjectIdentifier())) {
192       throw new GeneralSecurityException("Wrong object identifier");
193     }
194     SecretKeyAccess.requireAccess(access);
195     return new TestKey1();
196   }
197 
parseBToKey2( TestSerializationB serialization, @Nullable SecretKeyAccess access)198   private static Key parseBToKey2(
199       TestSerializationB serialization, @Nullable SecretKeyAccess access)
200       throws GeneralSecurityException {
201     if (!B_2.equals(serialization.getObjectIdentifier())) {
202       throw new GeneralSecurityException("Wrong object identifier");
203     }
204     SecretKeyAccess.requireAccess(access);
205     return new TestKey2();
206   }
207 
208   // ======================================================================= Key serialization tests
209   @Test
test_registerSerializerAndGet()210   public void test_registerSerializerAndGet() throws Exception {
211     SerializationRegistry registry =
212         new SerializationRegistry.Builder()
213             .registerKeySerializer(
214                 KeySerializer.create(
215                     SerializationRegistryTest::serializeKey1ToA,
216                     TestKey1.class,
217                     TestSerializationA.class))
218             .build();
219     assertThat(registry.hasSerializerForKey(new TestKey1(), TestSerializationA.class)).isTrue();
220     assertThat(registry.serializeKey(new TestKey1(), TestSerializationA.class, ACCESS)).isNotNull();
221   }
222 
223   @Test
test_emptyRegistry_throws()224   public void test_emptyRegistry_throws() throws Exception {
225     SerializationRegistry registry = new SerializationRegistry.Builder().build();
226     assertThat(registry.hasSerializerForKey(new TestKey1(), TestSerializationA.class)).isFalse();
227     assertThrows(
228         GeneralSecurityException.class,
229         () -> registry.serializeKey(new TestKey1(), TestSerializationA.class, ACCESS));
230   }
231 
232   @Test
test_noAccessSerializer_throws()233   public void test_noAccessSerializer_throws() throws Exception {
234     SerializationRegistry registry =
235         new SerializationRegistry.Builder()
236             .registerKeySerializer(
237                 KeySerializer.create(
238                     SerializationRegistryTest::serializeKey1ToA,
239                     TestKey1.class,
240                     TestSerializationA.class))
241             .build();
242     assertThrows(
243         GeneralSecurityException.class,
244         () -> registry.serializeKey(new TestKey1(), TestSerializationA.class, /* access= */ null));
245   }
246 
247   @Test
test_registerSameSerializerTwice_works()248   public void test_registerSameSerializerTwice_works() throws Exception {
249     KeySerializer<TestKey1, TestSerializationA> testSerializer =
250         KeySerializer.create(
251             SerializationRegistryTest::serializeKey1ToA, TestKey1.class, TestSerializationA.class);
252     SerializationRegistry unused = new SerializationRegistry.Builder()
253         .registerKeySerializer(testSerializer)
254         .registerKeySerializer(testSerializer)
255         .build();
256   }
257 
258   @Test
test_registerDifferentSerializerWithSameKeyType_throws()259   public void test_registerDifferentSerializerWithSameKeyType_throws() throws Exception {
260     KeySerializer<TestKey1, TestSerializationA> testSerializer1 =
261         KeySerializer.create(
262             SerializationRegistryTest::serializeKey1ToA, TestKey1.class, TestSerializationA.class);
263     KeySerializer<TestKey1, TestSerializationA> testSerializer2 =
264         KeySerializer.create(
265             SerializationRegistryTest::serializeKey1ToA, TestKey1.class, TestSerializationA.class);
266     SerializationRegistry.Builder builder = new SerializationRegistry.Builder();
267     builder.registerKeySerializer(testSerializer1);
268     assertThrows(
269         GeneralSecurityException.class,
270         () -> builder.registerKeySerializer(testSerializer2));
271   }
272 
273   @Test
test_registerDifferentSerializerWithDifferentKeyType_works()274   public void test_registerDifferentSerializerWithDifferentKeyType_works() throws Exception {
275     KeySerializer<TestKey1, TestSerializationA> testSerializer1 =
276         KeySerializer.create(
277             SerializationRegistryTest::serializeKey1ToA, TestKey1.class, TestSerializationA.class);
278     KeySerializer<TestKey2, TestSerializationA> testSerializer2 =
279         KeySerializer.create(
280             SerializationRegistryTest::serializeKey2ToA, TestKey2.class, TestSerializationA.class);
281     SerializationRegistry unused = new SerializationRegistry.Builder()
282         .registerKeySerializer(testSerializer1)
283         .registerKeySerializer(testSerializer2)
284         .build();
285   }
286 
287   @Test
test_registerDifferentSerializerWithDifferentSerializationType_works()288   public void test_registerDifferentSerializerWithDifferentSerializationType_works()
289       throws Exception {
290     KeySerializer<TestKey1, TestSerializationA> testSerializer1 =
291         KeySerializer.create(
292             SerializationRegistryTest::serializeKey1ToA, TestKey1.class, TestSerializationA.class);
293     KeySerializer<TestKey2, TestSerializationA> testSerializer2 =
294         KeySerializer.create(
295             SerializationRegistryTest::serializeKey2ToA, TestKey2.class, TestSerializationA.class);
296     SerializationRegistry unused = new SerializationRegistry.Builder()
297         .registerKeySerializer(testSerializer1)
298         .registerKeySerializer(testSerializer2)
299         .build();
300   }
301 
302   @Test
test_registerAll_checkDispatch()303   public void test_registerAll_checkDispatch() throws Exception {
304     SerializationRegistry registry =
305         new SerializationRegistry.Builder()
306             .registerKeySerializer(
307                 KeySerializer.create(
308                     SerializationRegistryTest::serializeKey1ToA,
309                     TestKey1.class,
310                     TestSerializationA.class))
311             .registerKeySerializer(
312                 KeySerializer.create(
313                     SerializationRegistryTest::serializeKey1ToB,
314                     TestKey1.class,
315                     TestSerializationB.class))
316             .registerKeySerializer(
317                 KeySerializer.create(
318                     SerializationRegistryTest::serializeKey2ToA,
319                     TestKey2.class,
320                     TestSerializationA.class))
321             .registerKeySerializer(
322                 KeySerializer.create(
323                     SerializationRegistryTest::serializeKey2ToB,
324                     TestKey2.class,
325                     TestSerializationB.class))
326             .build();
327     assertThat(
328             registry
329                 .serializeKey(new TestKey1(), TestSerializationA.class, ACCESS)
330                 .getObjectIdentifier())
331         .isEqualTo(A_1);
332     assertThat(
333             registry
334                 .serializeKey(new TestKey2(), TestSerializationA.class, ACCESS)
335                 .getObjectIdentifier())
336         .isEqualTo(A_2);
337     assertThat(
338             registry
339                 .serializeKey(new TestKey1(), TestSerializationB.class, ACCESS)
340                 .getObjectIdentifier())
341         .isEqualTo(B_1);
342     assertThat(
343             registry
344                 .serializeKey(new TestKey2(), TestSerializationB.class, ACCESS)
345                 .getObjectIdentifier())
346         .isEqualTo(B_2);
347   }
348 
349   @Test
test_serializer_copyWorks()350   public void test_serializer_copyWorks() throws Exception {
351     SerializationRegistry registry =
352         new SerializationRegistry.Builder()
353             .registerKeySerializer(
354                 KeySerializer.create(
355                     SerializationRegistryTest::serializeKey1ToA,
356                     TestKey1.class,
357                     TestSerializationA.class))
358             .build();
359     SerializationRegistry registry2 = new SerializationRegistry.Builder(registry).build();
360     assertThat(registry2.serializeKey(new TestKey1(), TestSerializationA.class, ACCESS))
361         .isNotNull();
362   }
363 
364   @Test
test_copyDoesNotChangeOldVersion_serializer()365   public void test_copyDoesNotChangeOldVersion_serializer() throws Exception {
366     SerializationRegistry registry1 = new SerializationRegistry.Builder().build();
367     SerializationRegistry.Builder builder = new SerializationRegistry.Builder(registry1);
368     SerializationRegistry registry2 = builder.build();
369     builder.registerKeySerializer(
370         KeySerializer.create(
371             SerializationRegistryTest::serializeKey1ToA, TestKey1.class, TestSerializationA.class));
372     assertThrows(
373         GeneralSecurityException.class,
374         () -> registry1.serializeKey(new TestKey1(), TestSerializationA.class, ACCESS));
375     assertThrows(
376         GeneralSecurityException.class,
377         () -> registry2.serializeKey(new TestKey1(), TestSerializationA.class, ACCESS));
378   }
379 
380   // ============================================================================= Key parsing tests
381   @Test
test_registerParserAndGet()382   public void test_registerParserAndGet() throws Exception {
383     SerializationRegistry registry =
384         new SerializationRegistry.Builder()
385             .registerKeyParser(
386                 KeyParser.create(
387                     SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class))
388             .build();
389     assertThat(registry.hasParserForKey(new TestSerializationA(A_1))).isTrue();
390     assertThat(registry.parseKey(new TestSerializationA(A_1), ACCESS)).isNotNull();
391   }
392 
393   @Test
test_registerParser_noAccess_throws()394   public void test_registerParser_noAccess_throws() throws Exception {
395     SerializationRegistry registry =
396         new SerializationRegistry.Builder()
397             .registerKeyParser(
398                 KeyParser.create(
399                     SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class))
400             .build();
401     assertThrows(
402         GeneralSecurityException.class,
403         () -> registry.parseKey(new TestSerializationA(A_1), /* access = */ null));
404   }
405 
406   @Test
test_parse_emptyRegistry_throws()407   public void test_parse_emptyRegistry_throws() throws Exception {
408     SerializationRegistry registry = new SerializationRegistry.Builder().build();
409     assertThat(registry.hasParserForKey(new TestSerializationA(A_1))).isFalse();
410     assertThrows(
411         GeneralSecurityException.class,
412         () -> registry.parseKey(new TestSerializationA(A_1), ACCESS));
413   }
414 
415   @Test
test_registerSameParserTwice_works()416   public void test_registerSameParserTwice_works() throws Exception {
417     KeyParser<TestSerializationA> testParser =
418         KeyParser.create(SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class);
419     SerializationRegistry unused = new SerializationRegistry.Builder()
420         .registerKeyParser(testParser)
421         .registerKeyParser(testParser)
422         .build();
423   }
424 
425   @Test
test_registerDifferentParsersWithSameKeyType_throws()426   public void test_registerDifferentParsersWithSameKeyType_throws() throws Exception {
427     KeyParser<TestSerializationA> testParser1 =
428         KeyParser.create(SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class);
429     KeyParser<TestSerializationA> testParser2 =
430         KeyParser.create(SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class);
431     SerializationRegistry.Builder builder = new SerializationRegistry.Builder();
432     builder.registerKeyParser(testParser1);
433     assertThrows(
434         GeneralSecurityException.class, () -> builder.registerKeyParser(testParser2));
435   }
436 
437   @Test
test_registerDifferentParsersWithDifferentSerializationType_works()438   public void test_registerDifferentParsersWithDifferentSerializationType_works() throws Exception {
439     KeyParser<TestSerializationA> testParser1 =
440         KeyParser.create(SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class);
441     KeyParser<TestSerializationB> testParser2 =
442         KeyParser.create(SerializationRegistryTest::parseBToKey1, B_1, TestSerializationB.class);
443     SerializationRegistry unused = new SerializationRegistry.Builder()
444         .registerKeyParser(testParser1)
445         .registerKeyParser(testParser2)
446         .build();
447   }
448 
449   @Test
test_registerDifferentParsersWithDifferentKeyType_works()450   public void test_registerDifferentParsersWithDifferentKeyType_works() throws Exception {
451     KeyParser<TestSerializationA> testParser1 =
452         KeyParser.create(SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class);
453     KeyParser<TestSerializationA> testParser2 =
454         KeyParser.create(SerializationRegistryTest::parseAToKey2, A_2, TestSerializationA.class);
455     SerializationRegistry unused = new SerializationRegistry.Builder()
456         .registerKeyParser(testParser1)
457         .registerKeyParser(testParser2)
458         .build();
459   }
460 
461   @Test
test_registerAllParsers_checkDispatch()462   public void test_registerAllParsers_checkDispatch() throws Exception {
463     SerializationRegistry registry =
464         new SerializationRegistry.Builder()
465             .registerKeyParser(
466                 KeyParser.create(
467                     SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class))
468             .registerKeyParser(
469                 KeyParser.create(
470                     SerializationRegistryTest::parseBToKey1, B_1, TestSerializationB.class))
471             .registerKeyParser(
472                 KeyParser.create(
473                     SerializationRegistryTest::parseAToKey2, A_2, TestSerializationA.class))
474             .registerKeyParser(
475                 KeyParser.create(
476                     SerializationRegistryTest::parseBToKey2, B_2, TestSerializationB.class))
477             .build();
478     assertThat(registry.parseKey(new TestSerializationA(A_1), ACCESS)).isInstanceOf(TestKey1.class);
479     assertThat(registry.parseKey(new TestSerializationA(A_2), ACCESS)).isInstanceOf(TestKey2.class);
480     assertThat(registry.parseKey(new TestSerializationB(B_1), ACCESS)).isInstanceOf(TestKey1.class);
481     assertThat(registry.parseKey(new TestSerializationB(B_2), ACCESS)).isInstanceOf(TestKey2.class);
482   }
483 
484   @Test
test_copyWorksForParsers()485   public void test_copyWorksForParsers() throws Exception {
486     SerializationRegistry registry =
487         new SerializationRegistry.Builder()
488             .registerKeyParser(
489                 KeyParser.create(
490                     SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class))
491             .build();
492     SerializationRegistry registry2 = new SerializationRegistry.Builder(registry).build();
493     assertThat(registry2.parseKey(new TestSerializationA(A_1), ACCESS)).isNotNull();
494   }
495 
496   @Test
test_copyDoesNotChangeOldVersion_parser()497   public void test_copyDoesNotChangeOldVersion_parser() throws Exception {
498     SerializationRegistry registry1 = new SerializationRegistry.Builder().build();
499     SerializationRegistry.Builder builder = new SerializationRegistry.Builder(registry1);
500     SerializationRegistry registry2 = builder.build();
501 
502     SerializationRegistry unused = builder
503         .registerKeyParser(
504             KeyParser.create(
505                 SerializationRegistryTest::parseAToKey1, A_1, TestSerializationA.class))
506         .build();
507     assertThrows(
508         GeneralSecurityException.class,
509         () -> registry1.parseKey(new TestSerializationA(A_1), ACCESS));
510     assertThrows(
511         GeneralSecurityException.class,
512         () -> registry2.parseKey(new TestSerializationA(A_1), ACCESS));
513   }
514 
515   // ================================================================================================
516   // PARAMETERS TESTS
517   // ================================================================================================
serializeParameters1ToA(TestParameters1 parameters)518   private static TestSerializationA serializeParameters1ToA(TestParameters1 parameters)
519       throws GeneralSecurityException {
520     return new TestSerializationA(A_1);
521   }
522 
serializeParameters2ToA(TestParameters2 parameters)523   private static TestSerializationA serializeParameters2ToA(TestParameters2 parameters)
524       throws GeneralSecurityException {
525     return new TestSerializationA(A_2);
526   }
527 
serializeParameters1ToB(TestParameters1 parameters)528   private static TestSerializationB serializeParameters1ToB(TestParameters1 parameters)
529       throws GeneralSecurityException {
530     return new TestSerializationB(B_1);
531   }
532 
serializeParameters2ToB(TestParameters2 parameters)533   private static TestSerializationB serializeParameters2ToB(TestParameters2 parameters)
534       throws GeneralSecurityException {
535     return new TestSerializationB(B_2);
536   }
537 
parseAToParameters1(TestSerializationA serialization)538   private static Parameters parseAToParameters1(TestSerializationA serialization)
539       throws GeneralSecurityException {
540     if (!A_1.equals(serialization.getObjectIdentifier())) {
541       throw new GeneralSecurityException("Wrong object identifier");
542     }
543     return new TestParameters1();
544   }
545 
parseAToParameters2(TestSerializationA serialization)546   private static Parameters parseAToParameters2(TestSerializationA serialization)
547       throws GeneralSecurityException {
548     if (!A_2.equals(serialization.getObjectIdentifier())) {
549       throw new GeneralSecurityException("Wrong object identifier");
550     }
551     return new TestParameters2();
552   }
553 
parseBToParameters1(TestSerializationB serialization)554   private static Parameters parseBToParameters1(TestSerializationB serialization)
555       throws GeneralSecurityException {
556     if (!B_1.equals(serialization.getObjectIdentifier())) {
557       throw new GeneralSecurityException("Wrong object identifier");
558     }
559     return new TestParameters1();
560   }
561 
parseBToParameters2(TestSerializationB serialization)562   private static Parameters parseBToParameters2(TestSerializationB serialization)
563       throws GeneralSecurityException {
564     if (!B_2.equals(serialization.getObjectIdentifier())) {
565       throw new GeneralSecurityException("Wrong object identifier");
566     }
567     return new TestParameters2();
568   }
569 
570   // ParametersSerialization tests
571   @Test
test_registerParametersSerializerAndGet()572   public void test_registerParametersSerializerAndGet() throws Exception {
573     SerializationRegistry registry =
574         new SerializationRegistry.Builder()
575             .registerParametersSerializer(
576                 ParametersSerializer.create(
577                     SerializationRegistryTest::serializeParameters1ToA,
578                     TestParameters1.class,
579                     TestSerializationA.class))
580             .build();
581     assertThat(registry.hasSerializerForParameters(new TestParameters1(), TestSerializationA.class))
582         .isTrue();
583     assertThat(registry.serializeParameters(new TestParameters1(), TestSerializationA.class))
584         .isNotNull();
585   }
586 
587   @Test
test_emptyRegistrySerializeParameters_throws()588   public void test_emptyRegistrySerializeParameters_throws() throws Exception {
589     SerializationRegistry registry = new SerializationRegistry.Builder().build();
590     assertThat(registry.hasSerializerForParameters(new TestParameters1(), TestSerializationA.class))
591         .isFalse();
592     assertThrows(
593         GeneralSecurityException.class,
594         () -> registry.serializeParameters(new TestParameters1(), TestSerializationA.class));
595   }
596 
597   @Test
test_registerSameParametersSerializerTwice_works()598   public void test_registerSameParametersSerializerTwice_works() throws Exception {
599     ParametersSerializer<TestParameters1, TestSerializationA> testSerializer =
600         ParametersSerializer.create(
601             SerializationRegistryTest::serializeParameters1ToA,
602             TestParameters1.class,
603             TestSerializationA.class);
604     SerializationRegistry unused = new SerializationRegistry.Builder()
605         .registerParametersSerializer(testSerializer)
606         .registerParametersSerializer(testSerializer)
607         .build();
608   }
609 
610   @Test
test_registerDifferentSerializerWithSameParametersType_throws()611   public void test_registerDifferentSerializerWithSameParametersType_throws() throws Exception {
612     ParametersSerializer<TestParameters1, TestSerializationA> testSerializer1 =
613         ParametersSerializer.create(
614             SerializationRegistryTest::serializeParameters1ToA,
615             TestParameters1.class,
616             TestSerializationA.class);
617     ParametersSerializer<TestParameters1, TestSerializationA> testSerializer2 =
618         ParametersSerializer.create(
619             SerializationRegistryTest::serializeParameters1ToA,
620             TestParameters1.class,
621             TestSerializationA.class);
622     SerializationRegistry.Builder builder = new SerializationRegistry.Builder();
623     builder.registerParametersSerializer(testSerializer1);
624     assertThrows(
625         GeneralSecurityException.class,
626         () -> builder.registerParametersSerializer(testSerializer2));
627   }
628 
629   @Test
test_registerDifferentSerializerWithDifferentParametersType_works()630   public void test_registerDifferentSerializerWithDifferentParametersType_works() throws Exception {
631     ParametersSerializer<TestParameters1, TestSerializationA> testSerializer1 =
632         ParametersSerializer.create(
633             SerializationRegistryTest::serializeParameters1ToA,
634             TestParameters1.class,
635             TestSerializationA.class);
636     ParametersSerializer<TestParameters2, TestSerializationA> testSerializer2 =
637         ParametersSerializer.create(
638             SerializationRegistryTest::serializeParameters2ToA,
639             TestParameters2.class,
640             TestSerializationA.class);
641     SerializationRegistry unused = new SerializationRegistry.Builder()
642         .registerParametersSerializer(testSerializer1)
643         .registerParametersSerializer(testSerializer2)
644         .build();
645   }
646 
647   @Test
test_registerDifferentSerializerWithDifferentFormatSerializationType_works()648   public void test_registerDifferentSerializerWithDifferentFormatSerializationType_works()
649       throws Exception {
650     ParametersSerializer<TestParameters1, TestSerializationA> testSerializer1 =
651         ParametersSerializer.create(
652             SerializationRegistryTest::serializeParameters1ToA,
653             TestParameters1.class,
654             TestSerializationA.class);
655     ParametersSerializer<TestParameters2, TestSerializationA> testSerializer2 =
656         ParametersSerializer.create(
657             SerializationRegistryTest::serializeParameters2ToA,
658             TestParameters2.class,
659             TestSerializationA.class);
660     SerializationRegistry unused = new SerializationRegistry.Builder()
661         .registerParametersSerializer(testSerializer1)
662         .registerParametersSerializer(testSerializer2)
663         .build();
664   }
665 
666   @Test
test_registerAllParametersSerializers_checkDispatch()667   public void test_registerAllParametersSerializers_checkDispatch() throws Exception {
668     SerializationRegistry registry =
669         new SerializationRegistry.Builder()
670             .registerParametersSerializer(
671                 ParametersSerializer.create(
672                     SerializationRegistryTest::serializeParameters1ToA,
673                     TestParameters1.class,
674                     TestSerializationA.class))
675             .registerParametersSerializer(
676                 ParametersSerializer.create(
677                     SerializationRegistryTest::serializeParameters1ToB,
678                     TestParameters1.class,
679                     TestSerializationB.class))
680             .registerParametersSerializer(
681                 ParametersSerializer.create(
682                     SerializationRegistryTest::serializeParameters2ToA,
683                     TestParameters2.class,
684                     TestSerializationA.class))
685             .registerParametersSerializer(
686                 ParametersSerializer.create(
687                     SerializationRegistryTest::serializeParameters2ToB,
688                     TestParameters2.class,
689                     TestSerializationB.class))
690             .build();
691     assertThat(
692             registry
693                 .serializeParameters(new TestParameters1(), TestSerializationA.class)
694                 .getObjectIdentifier())
695         .isEqualTo(A_1);
696     assertThat(
697             registry
698                 .serializeParameters(new TestParameters2(), TestSerializationA.class)
699                 .getObjectIdentifier())
700         .isEqualTo(A_2);
701     assertThat(
702             registry
703                 .serializeParameters(new TestParameters1(), TestSerializationB.class)
704                 .getObjectIdentifier())
705         .isEqualTo(B_1);
706     assertThat(
707             registry
708                 .serializeParameters(new TestParameters2(), TestSerializationB.class)
709                 .getObjectIdentifier())
710         .isEqualTo(B_2);
711   }
712 
713   @Test
test_formatSerializer_copyWorks()714   public void test_formatSerializer_copyWorks() throws Exception {
715     SerializationRegistry registry =
716         new SerializationRegistry.Builder()
717             .registerParametersSerializer(
718                 ParametersSerializer.create(
719                     SerializationRegistryTest::serializeParameters1ToA,
720                     TestParameters1.class,
721                     TestSerializationA.class))
722             .build();
723     SerializationRegistry registry2 = new SerializationRegistry.Builder(registry).build();
724     assertThat(registry2.serializeParameters(new TestParameters1(), TestSerializationA.class))
725         .isNotNull();
726   }
727 
728   @Test
test_copyDoesNotChangeOldVersion_formatSerializer()729   public void test_copyDoesNotChangeOldVersion_formatSerializer() throws Exception {
730     SerializationRegistry registry1 = new SerializationRegistry.Builder().build();
731     SerializationRegistry.Builder builder = new SerializationRegistry.Builder(registry1);
732     SerializationRegistry registry2 = builder.build();
733     builder.registerParametersSerializer(
734         ParametersSerializer.create(
735             SerializationRegistryTest::serializeParameters1ToA,
736             TestParameters1.class,
737             TestSerializationA.class));
738     assertThrows(
739         GeneralSecurityException.class,
740         () -> registry1.serializeParameters(new TestParameters1(), TestSerializationA.class));
741     assertThrows(
742         GeneralSecurityException.class,
743         () -> registry2.serializeParameters(new TestParameters1(), TestSerializationA.class));
744   }
745 
746   // ====================================================================== Parameters parsing tests
747   @Test
test_registerParametersParserAndGet()748   public void test_registerParametersParserAndGet() throws Exception {
749     SerializationRegistry registry =
750         new SerializationRegistry.Builder()
751             .registerParametersParser(
752                 ParametersParser.create(
753                     SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class))
754             .build();
755     assertThat(registry.hasParserForParameters(new TestSerializationA(A_1))).isTrue();
756     assertThat(registry.parseParameters(new TestSerializationA(A_1))).isNotNull();
757   }
758 
759   @Test
test_formatParse_emptyRegistry_throws()760   public void test_formatParse_emptyRegistry_throws() throws Exception {
761     SerializationRegistry registry = new SerializationRegistry.Builder().build();
762     assertThat(registry.hasParserForParameters(new TestSerializationA(A_1))).isFalse();
763     assertThrows(
764         GeneralSecurityException.class,
765         () -> registry.parseParameters(new TestSerializationA(A_1)));
766   }
767 
768   @Test
test_registerSameParametersParserTwice_works()769   public void test_registerSameParametersParserTwice_works() throws Exception {
770     ParametersParser<TestSerializationA> testParser =
771         ParametersParser.create(
772             SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class);
773     SerializationRegistry unused = new SerializationRegistry.Builder()
774         .registerParametersParser(testParser)
775         .registerParametersParser(testParser)
776         .build();
777   }
778 
779   @Test
test_registerDifferentParsersWithSameParametersType_throws()780   public void test_registerDifferentParsersWithSameParametersType_throws() throws Exception {
781     ParametersParser<TestSerializationA> testParser1 =
782         ParametersParser.create(
783             SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class);
784     ParametersParser<TestSerializationA> testParser2 =
785         ParametersParser.create(
786             SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class);
787     SerializationRegistry.Builder builder = new SerializationRegistry.Builder();
788     builder.registerParametersParser(testParser1);
789     assertThrows(
790         GeneralSecurityException.class,
791         () -> builder.registerParametersParser(testParser2));
792   }
793 
794   @Test
test_registerDifferentParametersParsersWithDifferentSerializationType_works()795   public void test_registerDifferentParametersParsersWithDifferentSerializationType_works()
796       throws Exception {
797     ParametersParser<TestSerializationA> testParser1 =
798         ParametersParser.create(
799             SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class);
800     ParametersParser<TestSerializationB> testParser2 =
801         ParametersParser.create(
802             SerializationRegistryTest::parseBToParameters1, B_1, TestSerializationB.class);
803     SerializationRegistry unused = new SerializationRegistry.Builder()
804         .registerParametersParser(testParser1)
805         .registerParametersParser(testParser2)
806         .build();
807   }
808 
809   @Test
test_registerDifferentParametersParsersWithDifferentKeyType_works()810   public void test_registerDifferentParametersParsersWithDifferentKeyType_works() throws Exception {
811     ParametersParser<TestSerializationA> testParser1 =
812         ParametersParser.create(
813             SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class);
814     ParametersParser<TestSerializationA> testParser2 =
815         ParametersParser.create(
816             SerializationRegistryTest::parseAToParameters2, A_2, TestSerializationA.class);
817     SerializationRegistry unused = new SerializationRegistry.Builder()
818         .registerParametersParser(testParser1)
819         .registerParametersParser(testParser2)
820         .build();
821   }
822 
823   @Test
test_registerAllParametersParsers_checkDispatch()824   public void test_registerAllParametersParsers_checkDispatch() throws Exception {
825     SerializationRegistry registry =
826         new SerializationRegistry.Builder()
827             .registerParametersParser(
828                 ParametersParser.create(
829                     SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class))
830             .registerParametersParser(
831                 ParametersParser.create(
832                     SerializationRegistryTest::parseBToParameters1, B_1, TestSerializationB.class))
833             .registerParametersParser(
834                 ParametersParser.create(
835                     SerializationRegistryTest::parseAToParameters2, A_2, TestSerializationA.class))
836             .registerParametersParser(
837                 ParametersParser.create(
838                     SerializationRegistryTest::parseBToParameters2, B_2, TestSerializationB.class))
839             .build();
840     assertThat(registry.parseParameters(new TestSerializationA(A_1)))
841         .isInstanceOf(TestParameters1.class);
842     assertThat(registry.parseParameters(new TestSerializationA(A_2)))
843         .isInstanceOf(TestParameters2.class);
844     assertThat(registry.parseParameters(new TestSerializationB(B_1)))
845         .isInstanceOf(TestParameters1.class);
846     assertThat(registry.parseParameters(new TestSerializationB(B_2)))
847         .isInstanceOf(TestParameters2.class);
848   }
849 
850   @Test
test_copyWorksForParametersParsers()851   public void test_copyWorksForParametersParsers() throws Exception {
852     SerializationRegistry registry =
853         new SerializationRegistry.Builder()
854             .registerParametersParser(
855                 ParametersParser.create(
856                     SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class))
857             .build();
858     SerializationRegistry registry2 = new SerializationRegistry.Builder(registry).build();
859     assertThat(registry2.parseParameters(new TestSerializationA(A_1))).isNotNull();
860   }
861 
862   @Test
test_copyDoesNotChangeOldVersion_formatParser()863   public void test_copyDoesNotChangeOldVersion_formatParser() throws Exception {
864     SerializationRegistry registry1 = new SerializationRegistry.Builder().build();
865     SerializationRegistry.Builder builder = new SerializationRegistry.Builder(registry1);
866     SerializationRegistry registry2 = builder.build();
867 
868     SerializationRegistry unused = builder
869         .registerParametersParser(
870             ParametersParser.create(
871                 SerializationRegistryTest::parseAToParameters1, A_1, TestSerializationA.class))
872         .build();
873     assertThrows(
874         GeneralSecurityException.class,
875         () -> registry1.parseParameters(new TestSerializationA(A_1)));
876     assertThrows(
877         GeneralSecurityException.class,
878         () -> registry2.parseParameters(new TestSerializationA(A_1)));
879   }
880 }
881