diff --git a/TestVectors/runtimes/java/src/main/java/software/amazon/cryptography/dbencryptionsdk/dynamodb/testvectors/TestVectorModels.java b/TestVectors/runtimes/java/src/main/java/software/amazon/cryptography/dbencryptionsdk/dynamodb/testvectors/TestVectorModels.java new file mode 100644 index 0000000000..2c608dabd2 --- /dev/null +++ b/TestVectors/runtimes/java/src/main/java/software/amazon/cryptography/dbencryptionsdk/dynamodb/testvectors/TestVectorModels.java @@ -0,0 +1,253 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.cryptography.dbencryptionsdk.dynamodb.testvectors; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.model.DynamoDbTableEncryptionConfig; + +/** + * Replacement for Dafny-generated test vector model types. + * All collections are defensively copied to unmodifiable forms. + */ +public final class TestVectorModels { + + public static final String TABLE_NAME = "GazelleVectorTable"; + public static final String HASH_NAME = "RecNum"; + + private TestVectorModels() {} + + public static final class Record { + public final int number; + public final Map item; + + public Record(int number, Map item) { + this.number = number; + this.item = unmodifiableMap(Objects.requireNonNull(item, "item")); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Record)) return false; + Record r = (Record) o; + return number == r.number && item.equals(r.item); + } + + @Override + public int hashCode() { + return 31 * number + item.hashCode(); + } + } + + public static final class LargeRecord { + public final String name; + public final Map item; + + public LargeRecord(String name, Map item) { + this.name = Objects.requireNonNull(name, "name"); + this.item = unmodifiableMap(Objects.requireNonNull(item, "item")); + } + } + + public static final class TableConfig { + + public final String name; + public final DynamoDbTableEncryptionConfig config; // null when vanilla == true + public final boolean vanilla; + + public TableConfig( + String name, + DynamoDbTableEncryptionConfig config, + boolean vanilla + ) { + this.name = Objects.requireNonNull(name, "name"); + this.config = config; + this.vanilla = vanilla; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof TableConfig)) return false; + TableConfig t = (TableConfig) o; + return ( + vanilla == t.vanilla && + name.equals(t.name) && + Objects.equals(config, t.config) + ); + } + + @Override + public int hashCode() { + int h = name.hashCode(); + h = 31 * h + (config != null ? config.hashCode() : 0); + h = 31 * h + Boolean.hashCode(vanilla); + return h; + } + } + + public static final class SimpleQuery { + + public final String index; // nullable + public final String keyExpr; // nullable + public final String filterExpr; // nullable + public final List failConfigs; + + public SimpleQuery( + String index, + String keyExpr, + String filterExpr, + List failConfigs + ) { + this.index = index; + this.keyExpr = keyExpr; + this.filterExpr = filterExpr; + this.failConfigs = + unmodifiableList(Objects.requireNonNull(failConfigs, "failConfigs")); + } + } + + public static final class ComplexQuery { + public final SimpleQuery query; + public final List pass; + public final List fail; + + public ComplexQuery( + SimpleQuery query, + List pass, + List fail + ) { + this.query = Objects.requireNonNull(query, "query"); + this.pass = unmodifiableList(Objects.requireNonNull(pass, "pass")); + this.fail = unmodifiableList(Objects.requireNonNull(fail, "fail")); + } + } + + public static final class ComplexTest { + public final String config; + public final List queries; + public final List failures; + + public ComplexTest( + String config, + List queries, + List failures + ) { + this.config = Objects.requireNonNull(config, "config"); + this.queries = + unmodifiableList(Objects.requireNonNull(queries, "queries")); + this.failures = + unmodifiableList(Objects.requireNonNull(failures, "failures")); + } + } + + public static final class RoundTripTest { + public final Map configs; + public final List records; + + public RoundTripTest( + Map configs, + List records + ) { + this.configs = + unmodifiableMap(Objects.requireNonNull(configs, "configs")); + this.records = + unmodifiableList(Objects.requireNonNull(records, "records")); + } + } + + public static final class WriteTest { + public final TableConfig config; + public final List records; + public final String fileName; + + public WriteTest( + TableConfig config, + List records, + String fileName + ) { + this.config = Objects.requireNonNull(config, "config"); + this.records = + unmodifiableList(Objects.requireNonNull(records, "records")); + this.fileName = Objects.requireNonNull(fileName, "fileName"); + } + } + + public static final class DecryptTest { + public final TableConfig config; + public final List encryptedRecords; + public final List plaintextRecords; + + public DecryptTest( + TableConfig config, + List encryptedRecords, + List plaintextRecords + ) { + this.config = Objects.requireNonNull(config, "config"); + this.encryptedRecords = + unmodifiableList( + Objects.requireNonNull(encryptedRecords, "encryptedRecords") + ); + this.plaintextRecords = + unmodifiableList( + Objects.requireNonNull(plaintextRecords, "plaintextRecords") + ); + } + } + + public static final class IoTest { + public final String name; + public final TableConfig writeConfig; + public final TableConfig readConfig; + public final List records; + public final Map names; + public final Map values; + public final List queries; + + public IoTest( + String name, + TableConfig writeConfig, + TableConfig readConfig, + List records, + Map names, + Map values, + List queries + ) { + this.name = Objects.requireNonNull(name, "name"); + this.writeConfig = Objects.requireNonNull(writeConfig, "writeConfig"); + this.readConfig = Objects.requireNonNull(readConfig, "readConfig"); + this.records = + unmodifiableList(Objects.requireNonNull(records, "records")); + this.names = unmodifiableMap(Objects.requireNonNull(names, "names")); + this.values = unmodifiableMap(Objects.requireNonNull(values, "values")); + this.queries = + unmodifiableList(Objects.requireNonNull(queries, "queries")); + } + } + + public static final class ConfigPair { + public final String first; + public final String second; + + public ConfigPair(String first, String second) { + this.first = Objects.requireNonNull(first, "first"); + this.second = Objects.requireNonNull(second, "second"); + } + } + + // Java 8 compatible defensive copy helpers + + private static List unmodifiableList(List src) { + return Collections.unmodifiableList(new ArrayList<>(src)); + } + + private static Map unmodifiableMap(Map src) { + return Collections.unmodifiableMap(new HashMap<>(src)); + } +}