hidl2aidl: add support for array and vector translation am: 8cc4e9a907

Original change: https://android-review.googlesource.com/c/platform/system/tools/hidl/+/1511709

Change-Id: I1aabd885dd8fb3718cdc9b4b66dd6fccf4a0e73a
diff --git a/hidl2aidl/AidlTranslate.cpp b/hidl2aidl/AidlTranslate.cpp
index 345fb19..1840bae 100644
--- a/hidl2aidl/AidlTranslate.cpp
+++ b/hidl2aidl/AidlTranslate.cpp
@@ -25,11 +25,15 @@
 #include <vector>
 
 #include "AidlHelper.h"
+#include "ArrayType.h"
 #include "CompoundType.h"
+#include "ConstantExpression.h"
 #include "Coordinator.h"
+#include "EnumType.h"
 #include "NamedType.h"
 #include "ScalarType.h"
 #include "Scope.h"
+#include "VectorType.h"
 
 namespace android {
 
@@ -59,12 +63,12 @@
     }
 }
 
-static const std::string aidlTypePackage(const NamedType* type, AidlBackend backend) {
+static const std::string aidlTypePackage(const NamedType& type, AidlBackend backend) {
     const std::string prefix = (backend == AidlBackend::NDK) ? "aidl::" : std::string();
     const std::string separator = (backend == AidlBackend::JAVA) ? "." : "::";
     return prefix +
-           base::Join(base::Split(AidlHelper::getAidlPackage(type->fqName()), "."), separator) +
-           separator + AidlHelper::getAidlType(*type, type->fqName());
+           base::Join(base::Split(AidlHelper::getAidlPackage(type.fqName()), "."), separator) +
+           separator + AidlHelper::getAidlType(type, type.fqName());
 }
 
 static void namedTypeTranslation(Formatter& out, const std::set<const NamedType*>& namedTypes,
@@ -100,10 +104,10 @@
                     << "(h2aTranslate(in." << field.fullName << "()));\n";
             } else {
                 out << "{\n";
-                out << aidlTypePackage(type, backend) << " " << field.field->name() << ";\n";
+                out << aidlTypePackage(*type, backend) << " " << field.field->name() << ";\n";
                 out << "if (!translate(in." << field.fullName + "(), &" << field.field->name()
                     << ")) return false;\n";
-                out << "out->set<" << aidlTypePackage(parent, backend) << "::" << field.fullName
+                out << "out->set<" << aidlTypePackage(*parent, backend) << "::" << field.fullName
                     << ">(" << field.field->name() << ");\n";
                 out << "}\n";
             }
@@ -111,34 +115,32 @@
     }
 }
 
-static void h2aScalarChecks(Formatter& out, const FieldWithVersion& field,
-                            const CompoundType* parent, AidlBackend backend) {
+static void h2aScalarChecks(Formatter& out, const Type& type, const std::string& inputAccess,
+                            AidlBackend backend) {
     static const std::map<ScalarType::Kind, size_t> kSignedMaxSize{
             {ScalarType::KIND_UINT8, std::numeric_limits<int8_t>::max()},
             {ScalarType::KIND_INT16, std::numeric_limits<int32_t>::max()},
             {ScalarType::KIND_UINT32, std::numeric_limits<int32_t>::max()},
             {ScalarType::KIND_UINT64, std::numeric_limits<int64_t>::max()}};
-
-    const ScalarType* scalarType = field.field->type().resolveToScalarType();
-    if (scalarType != nullptr) {
+    const ScalarType* scalarType = type.resolveToScalarType();
+    if (scalarType != nullptr && !type.isEnum()) {
         const auto& it = kSignedMaxSize.find(scalarType->getKind());
         if (it != kSignedMaxSize.end()) {
             out << "// FIXME This requires conversion between signed and unsigned. Change this if "
                    "it doesn't suit your needs.\n";
-            std::string functionCall = (parent->style() == CompoundType::STYLE_STRUCT) ? "" : "()";
             if (scalarType->getKind() == ScalarType::KIND_INT16) {
                 // AIDL uses an unsigned 16-bit integer(char16_t), so this is signed to unsigned.
-                out << "if (in." << field.fullName << functionCall << " < 0) {\n";
+                out << "if (" << inputAccess << " < 0) {\n";
             } else {
                 std::string affix = (scalarType->getKind() == ScalarType::KIND_UINT64) ? "L" : "";
-                out << "if (in." << field.fullName << functionCall << " > " << it->second << affix
-                    << " || in." << field.fullName << functionCall << " < 0) {\n";
+                out << "if (" << inputAccess << " > " << it->second << affix << " || "
+                    << inputAccess << " < 0) {\n";
             }
             if (backend == AidlBackend::JAVA) {
                 out.indent([&] {
                     out << "throw new RuntimeException(\"Unsafe conversion between signed and "
                            "unsigned scalars for field: "
-                        << field.fullName << "\");\n";
+                        << inputAccess << "\");\n";
                 });
             } else {
                 out.indent([&] { out << "return false;\n"; });
@@ -157,10 +159,15 @@
 }
 
 static std::string wrapStaticCast(const std::string& payload, const Type& type,
-                                  const FQName& fqName) {
+                                  const FQName& fqName, AidlBackend backend) {
     static const std::map<std::string, std::string> kAidlBackendScalarTypes{
             {"boolean", "bool"}, {"byte", "int8_t"}, {"char", "char16_t"}, {"int", "int32_t"},
             {"long", "int64_t"}, {"float", "float"}, {"double", "double"}};
+    if (type.isEnum()) {
+        return "static_cast<" +
+               aidlTypePackage(static_cast<const android::NamedType&>(type), backend) + ">(" +
+               payload + ")";
+    }
     const auto& it = kAidlBackendScalarTypes.find(AidlHelper::getAidlType(type, fqName));
     if (it != kAidlBackendScalarTypes.end()) {
         return "static_cast<" + it->second + ">(" + payload + ")";
@@ -174,30 +181,100 @@
     if (type.isString()) {
         return wrapToString16(payload, backend);
     } else {
-        return wrapStaticCast(payload, type, fqName);
+        return wrapStaticCast(payload, type, fqName, backend);
+    }
+}
+
+static void containerTranslation(Formatter& out, const FieldWithVersion& field,
+                                 const CompoundType* parent, AidlBackend backend) {
+    const Type* elementType;
+    std::string javaSizeAccess;
+    std::string javaElementAccess;
+    std::string cppSize;
+    if (field.field->type().isArray()) {
+        elementType = static_cast<const ArrayType*>(field.field->get())->getElementType();
+        javaSizeAccess = ".length";
+        javaElementAccess = "[i]";
+        cppSize = "sizeof(in." + field.fullName + ")/sizeof(in." + field.fullName + "[0])";
+    } else if (field.field->type().isVector()) {
+        elementType = static_cast<const VectorType*>(field.field->get())->getElementType();
+        javaSizeAccess = ".size()";
+        javaElementAccess = ".get(i)";
+        cppSize = "in." + field.fullName + ".size()";
+    } else {
+        LOG(FATAL) << "Unexpected container type for field: " << field.field->name();
+        return;
+    }
+    if (elementType->isArray() || elementType->isVector()) {
+        out << "#error Nested arrays and vectors are currently not supported. Needs implementation "
+               "for field: "
+            << field.field->name() << "\n";
+        return;
+    }
+    if (elementType->isNamedType() && !elementType->isEnum()) {
+        out << "#error Arrays of NamedTypes are not currently not supported. Needs implementation "
+               "for field: "
+            << field.field->name() << "\n";
+        return;
+    }
+    if (backend == AidlBackend::JAVA) {
+        const std::string inputAccess = "in." + field.fullName;
+        out << "if (" << inputAccess << " != null) {\n";
+        out.indent([&] {
+            out << "out." << field.field->name() << " = new " << elementType->getJavaType(true)
+                << "[" << inputAccess << javaSizeAccess << "];\n";
+            out << "for (int i = 0; i < " << inputAccess << javaSizeAccess << "; i++) {\n";
+            out.indent([&] {
+                h2aScalarChecks(out, *elementType, inputAccess + javaElementAccess, backend);
+                out << "out." << field.field->name() << "[i] = " << inputAccess << javaElementAccess
+                    << ";\n";
+            });
+            out << "}\n";
+        });
+        out << "}\n";
+    } else {
+        const std::string inputAccessElement = "in." + field.fullName + "[i]";
+        out << "{\n";
+        out.indent([&] {
+            out << "size_t size = " << cppSize << ";\n";
+            out << "for (size_t i = 0; i < size; i++) {\n";
+            out.indent([&] {
+                h2aScalarChecks(out, *elementType, inputAccessElement, backend);
+                out << "out->" << field.field->name() << ".push_back("
+                    << wrapCppSource(inputAccessElement, *elementType, parent->fqName(), backend)
+                    << ");\n";
+            });
+            out << "}\n";
+        });
+        out << "}\n";
     }
 }
 
 static void simpleTranslation(Formatter& out, const FieldWithVersion& field,
                               const CompoundType* parent, AidlBackend backend) {
-    h2aScalarChecks(out, field, parent, backend);
+    std::string inputAccess = "in." + field.fullName;
     if (backend == AidlBackend::JAVA) {
         if (parent->style() == CompoundType::STYLE_STRUCT) {
-            out << "out." << field.field->name() << " = in." << field.fullName << ";\n";
+            h2aScalarChecks(out, field.field->type(), inputAccess, backend);
+            out << "out." << field.field->name() << " = " << inputAccess << ";\n";
         } else {
-            out << "out.set" << StringHelper::Capitalize(field.fullName) << "(in."
-                << field.field->name() << "());\n";
+            inputAccess += "()";
+            h2aScalarChecks(out, field.field->type(), inputAccess, backend);
+            out << "out.set" << StringHelper::Capitalize(field.fullName) << "(" << inputAccess
+                << ");\n";
         }
     } else {
         if (parent->style() == CompoundType::STYLE_STRUCT) {
+            h2aScalarChecks(out, field.field->type(), inputAccess, backend);
             out << "out->" << field.field->name() << " = "
-                << wrapCppSource("in." + field.fullName, *field.field->get(), parent->fqName(),
+                << wrapCppSource("in." + field.fullName, field.field->type(), parent->fqName(),
                                  backend)
                 << ";\n";
         } else {
+            inputAccess += "()";
+            h2aScalarChecks(out, field.field->type(), inputAccess, backend);
             out << "*out = "
-                << wrapCppSource("in." + field.fullName + "()", *field.field->get(),
-                                 parent->fqName(), backend)
+                << wrapCppSource(inputAccess, field.field->type(), parent->fqName(), backend)
                 << ";\n";
         }
     }
@@ -209,6 +286,8 @@
     // TODO(b/158489355) Need to support and validate more types like arrays/vectors.
     if (field.field->type().isNamedType()) {
         namedTypeTranslation(out, namedTypes, field, parent, backend);
+    } else if (field.field->type().isArray() || field.field->type().isVector()) {
+        containerTranslation(out, field, parent, backend);
     } else if (field.field->type().isEnum() || field.field->type().isScalar() ||
                field.field->type().isString()) {
         simpleTranslation(out, field, parent, backend);
@@ -221,11 +300,11 @@
 
 static const std::string declareAidlFunctionSignature(const NamedType* type, AidlBackend backend) {
     if (backend == AidlBackend::JAVA) {
-        return "static public " + aidlTypePackage(type, backend) + " h2aTranslate(" +
+        return "static public " + aidlTypePackage(*type, backend) + " h2aTranslate(" +
                type->fullJavaName() + " in)";
     } else {
         return "__attribute__((warn_unused_result)) bool translate(const " + type->fullName() +
-               "& in, " + aidlTypePackage(type, backend) + "* out)";
+               "& in, " + aidlTypePackage(*type, backend) + "* out)";
     }
 }
 
@@ -332,8 +411,8 @@
         if (compound->style() == CompoundType::STYLE_SAFE_UNION) {
             out.indent([&] {
                 if (backend == AidlBackend::JAVA) {
-                    out << aidlTypePackage(type, backend) << " out = new "
-                        << aidlTypePackage(type, backend) << "();\n";
+                    out << aidlTypePackage(*type, backend) << " out = new "
+                        << aidlTypePackage(*type, backend) << "();\n";
                 }
                 out << "switch (in.getDiscriminator()) {\n";
                 out.indent([&] {
@@ -366,8 +445,8 @@
         } else {
             out.indent([&] {
                 if (backend == AidlBackend::JAVA) {
-                    out << aidlTypePackage(type, backend) << " out = new "
-                        << aidlTypePackage(type, backend) << "();\n";
+                    out << aidlTypePackage(*type, backend) << " out = new "
+                        << aidlTypePackage(*type, backend) << "();\n";
                 }
                 const ProcessedCompoundType& processedType = it->second;
                 for (const auto& field : processedType.fields) {
diff --git a/hidl2aidl/test/1.2/types.hal b/hidl2aidl/test/1.2/types.hal
index 0371a8e..12990b9 100644
--- a/hidl2aidl/test/1.2/types.hal
+++ b/hidl2aidl/test/1.2/types.hal
@@ -18,6 +18,7 @@
 
 import @1.1::OnlyIn11;
 import @1.1::NameCollision;
+import @1.1::Value;
 import android.hidl.safe_union@1.0::Monostate;
 
 struct NameCollision {
@@ -45,3 +46,18 @@
     float e;
     double f;
 };
+
+struct ArrayFoo {
+    int8_t[12] a;
+    uint32_t[12] b;
+    @1.1::Value[12] c;
+    string[2] d;
+};
+
+struct VectorFoo {
+    vec<int8_t> a;
+    vec<uint32_t> b;
+    vec<@1.1::Value> c;
+    vec<string> d;
+};
+
diff --git a/hidl2aidl/test/Android.bp b/hidl2aidl/test/Android.bp
index 28e2558..696b7d3 100644
--- a/hidl2aidl/test/Android.bp
+++ b/hidl2aidl/test/Android.bp
@@ -40,6 +40,8 @@
     name: "hidl2aidl_test_gen_aidl",
     defaults: ["hidl2aidl_test_gen_defaults"],
     out: [
+        "hidl2aidl/test/ArrayFoo.aidl",
+        "hidl2aidl/test/VectorFoo.aidl",
         "hidl2aidl/test/IBar.aidl",
         "hidl2aidl/test/IBarInner.aidl",
         "hidl2aidl/test/IFoo.aidl",
diff --git a/hidl2aidl/test/TranslateJavaTest.java b/hidl2aidl/test/TranslateJavaTest.java
index 6e9cbcd..5ff8550 100644
--- a/hidl2aidl/test/TranslateJavaTest.java
+++ b/hidl2aidl/test/TranslateJavaTest.java
@@ -115,7 +115,7 @@
             fail("Expected an exception to be thrown for out of bounds unsigned to signed translation");
         } catch (RuntimeException e) {
             String message = e.getMessage();
-            assertThat("Unsafe conversion between signed and unsigned scalars for field: a",
+            assertThat("Unsafe conversion between signed and unsigned scalars for field: in.a",
                     is(message));
         }
     }
@@ -191,4 +191,102 @@
         dest = Translate.h2aTranslate(source);
         assertThat(source.f(), is(dest.getF()));
     }
+
+    @Test
+    public void ArrayFoo() {
+        hidl2aidl.test.ArrayFoo dest;
+        hidl2aidl.test.V1_2.ArrayFoo source = new hidl2aidl.test.V1_2.ArrayFoo();
+        source.a[0] = 42;
+        source.a[0] = 42;
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.a[0], is(dest.a[0]));
+    }
+
+    @Test
+    public void ArrayFooEmpty() {
+        hidl2aidl.test.ArrayFoo dest;
+        hidl2aidl.test.V1_2.ArrayFoo source = new hidl2aidl.test.V1_2.ArrayFoo();
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.a.length, is(dest.a.length));
+    }
+
+    @Test
+    public void ArrayFooEnum() {
+        hidl2aidl.test.ArrayFoo dest;
+        hidl2aidl.test.V1_2.ArrayFoo source = new hidl2aidl.test.V1_2.ArrayFoo();
+        source.c[0] = hidl2aidl.test.Value.A;
+        source.c[1] = hidl2aidl.test.Value.B;
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.c[0], is(dest.c[0]));
+        assertThat(source.c[1], is(dest.c[1]));
+    }
+
+    @Test
+    public void ArrayFooString() {
+        hidl2aidl.test.ArrayFoo dest;
+        hidl2aidl.test.V1_2.ArrayFoo source = new hidl2aidl.test.V1_2.ArrayFoo();
+        source.d[0] = "hello";
+        source.d[1] = "world";
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.d[0], is(dest.d[0]));
+        assertThat(source.d[1], is(dest.d[1]));
+    }
+
+    @Test
+    public void VectorFoo() {
+        hidl2aidl.test.VectorFoo dest;
+        hidl2aidl.test.V1_2.VectorFoo source = new hidl2aidl.test.V1_2.VectorFoo();
+        source.a.add((byte) 42);
+        source.a.add((byte) 8);
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.a.get(0), is(dest.a[0]));
+        assertThat(source.a.get(1), is(dest.a[1]));
+    }
+
+    @Test
+    public void VectorFooEmpty() {
+        hidl2aidl.test.VectorFoo dest;
+        hidl2aidl.test.V1_2.VectorFoo source = new hidl2aidl.test.V1_2.VectorFoo();
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.a.size(), is(dest.a.length));
+    }
+
+    @Test
+    public void VectorFooUnsigned() {
+        hidl2aidl.test.VectorFoo dest;
+        hidl2aidl.test.V1_2.VectorFoo source = new hidl2aidl.test.V1_2.VectorFoo();
+        source.b.add(12);
+        source.b.add(0xf0000000);
+        try {
+            dest = Translate.h2aTranslate(source);
+            fail("Expected an exception to be thrown for out of bounds unsigned to signed translation");
+        } catch (RuntimeException e) {
+            String message = e.getMessage();
+            assertThat(
+                    "Unsafe conversion between signed and unsigned scalars for field: in.b.get(i)",
+                    is(message));
+        }
+    }
+
+    @Test
+    public void VectorFooEnum() {
+        hidl2aidl.test.VectorFoo dest;
+        hidl2aidl.test.V1_2.VectorFoo source = new hidl2aidl.test.V1_2.VectorFoo();
+        source.c.add(hidl2aidl.test.Value.A);
+        source.c.add(hidl2aidl.test.Value.B);
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.c.get(0), is(dest.c[0]));
+        assertThat(source.c.get(1), is(dest.c[1]));
+    }
+
+    @Test
+    public void VectorFooString() {
+        hidl2aidl.test.VectorFoo dest;
+        hidl2aidl.test.V1_2.VectorFoo source = new hidl2aidl.test.V1_2.VectorFoo();
+        source.d.add("hello");
+        source.d.add("world");
+        dest = Translate.h2aTranslate(source);
+        assertThat(source.d.get(0), is(dest.d[0]));
+        assertThat(source.d.get(1), is(dest.d[1]));
+    }
 }
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/ArrayFoo.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/ArrayFoo.aidl
new file mode 100644
index 0000000..0354af6
--- /dev/null
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/ArrayFoo.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package hidl2aidl.test;
+@VintfStability
+parcelable ArrayFoo {
+  byte[] a;
+  int[] b;
+  hidl2aidl.test.Value[] c;
+  String[] d;
+}
diff --git a/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/VectorFoo.aidl b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/VectorFoo.aidl
new file mode 100644
index 0000000..d2e8b76
--- /dev/null
+++ b/hidl2aidl/test/aidl_api/hidl2aidl_test_gen/current/hidl2aidl/test/VectorFoo.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package hidl2aidl.test;
+@VintfStability
+parcelable VectorFoo {
+  byte[] a;
+  int[] b;
+  hidl2aidl.test.Value[] c;
+  String[] d;
+}
diff --git a/hidl2aidl/test/translate_cpp_test.cpp b/hidl2aidl/test/translate_cpp_test.cpp
index 0b2bf1c..0d94c29 100644
--- a/hidl2aidl/test/translate_cpp_test.cpp
+++ b/hidl2aidl/test/translate_cpp_test.cpp
@@ -23,134 +23,110 @@
 namespace android {
 
 TEST_F(Hidl2aidlTranslateTest, OnlyIn10) {
-    bool ret;
     hidl2aidl::test::OnlyIn10 dest;
     hidl2aidl::test::V1_0::OnlyIn10 source;
     source.str = "Hello";
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.str, String8(dest.str).c_str());
 }
 
 TEST_F(Hidl2aidlTranslateTest, OnlyIn11) {
-    bool ret;
     hidl2aidl::test::OnlyIn11 dest;
     hidl2aidl::test::V1_1::OnlyIn11 source;
     source.str = 12;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.str, dest.str);
 }
 
 TEST_F(Hidl2aidlTranslateTest, OverrideMe) {
-    bool ret;
     hidl2aidl::test::OverrideMe dest;
     hidl2aidl::test::V1_1::OverrideMe source;
     source.a = "World";
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a, String8(dest.a).c_str());
 }
 
 TEST_F(Hidl2aidlTranslateTest, Outer) {
-    bool ret;
     hidl2aidl::test::Outer dest;
     hidl2aidl::test::V1_1::Outer source;
     source.a = 12;
     source.v1_0.inner.a = 16;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a, dest.a);
     EXPECT_EQ(source.v1_0.inner.a, dest.inner.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, OuterInner) {
-    bool ret;
     hidl2aidl::test::OuterInner dest;
     hidl2aidl::test::V1_0::Outer::Inner source;
     source.a = 12;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a, dest.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, NameCollision) {
-    bool ret;
     hidl2aidl::test::NameCollision dest;
     hidl2aidl::test::V1_2::NameCollision source;
     source.reference.reference.a = 12;
     source.reference.b = "Fancy";
     source.c = "Car";
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.reference.reference.a, dest.a);
     EXPECT_EQ(source.reference.b, String8(dest.b).c_str());
     EXPECT_EQ(source.c, String8(dest.c).c_str());
 }
 
 TEST_F(Hidl2aidlTranslateTest, IFooBigStruct) {
-    bool ret;
     hidl2aidl::test::IFooBigStruct dest;
     hidl2aidl::test::V1_1::IFoo::BigStruct source;
     source.type = 12;
     source.value = 16;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.type, dest.type);
     EXPECT_EQ(source.value, dest.value);
 }
 
 TEST_F(Hidl2aidlTranslateTest, IBarInner) {
-    bool ret;
     hidl2aidl::test::IBarInner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     source.a = 0x70000000;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
-    EXPECT_EQ((int32_t)source.a, dest.a);
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<int32_t>(source.a), dest.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, UnsignedToSignedTooLarge) {
-    bool ret;
     hidl2aidl::test::IBarInner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     // source.a is uint32_t, dest.a is int32_t
     source.a = 0xf0000000;
-    ret = h2a::translate(source, &dest);
-    EXPECT_FALSE(ret);
-    EXPECT_NE((int32_t)source.a, dest.a);
+    ASSERT_FALSE(h2a::translate(source, &dest));
+    EXPECT_NE(static_cast<int32_t>(source.a), dest.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarByte) {
-    bool ret;
     hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.a(8);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a(), dest.get<hidl2aidl::test::SafeUnionBar::a>());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarInt64) {
-    bool ret;
     hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.b(25000);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
-    EXPECT_EQ(source.b(), (uint64_t)dest.get<hidl2aidl::test::SafeUnionBar::b>());
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<int64_t>(source.b()), dest.get<hidl2aidl::test::SafeUnionBar::b>());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarInnerStructBar) {
-    bool ret;
     hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     hidl2aidl::test::V1_2::SafeUnionBar::InnerStructBar inner;
     inner.x = 8;
     inner.z = 12;
     source.innerStructBar(inner);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.innerStructBar().x,
               dest.get<hidl2aidl::test::SafeUnionBar::innerStructBar>().x);
     EXPECT_EQ(source.innerStructBar().z,
@@ -158,45 +134,120 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarOnlyIn11) {
-    bool ret;
     hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     hidl2aidl::test::V1_1::OnlyIn11 onlyIn11;
     onlyIn11.str = 12;
     source.c(onlyIn11);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.c().str, dest.get<hidl2aidl::test::SafeUnionBar::c>().str);
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarString) {
-    bool ret;
     hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.d("Hello world!");
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.d(), String8(dest.get<hidl2aidl::test::SafeUnionBar::d>()).c_str());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarFloat) {
-    bool ret;
     hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.e(3.5f);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.e(), dest.get<hidl2aidl::test::SafeUnionBar::e>());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarDouble) {
-    bool ret;
     hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.f(3e10);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.f(), dest.get<hidl2aidl::test::SafeUnionBar::f>());
 }
 
+TEST_F(Hidl2aidlTranslateTest, ArrayFoo) {
+    hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    source.a[0] = 42;
+    source.a[1] = 8;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    ASSERT_EQ(12u, dest.a.size());
+    EXPECT_EQ(source.a[0], dest.a[0]);
+    EXPECT_EQ(source.a[1], dest.a[1]);
+    EXPECT_EQ(source.a[2], dest.a[2]);
+    EXPECT_EQ(source.a[11], dest.a[11]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, ArrayFooEmpty) {
+    hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(12u, dest.a.size());
+    EXPECT_EQ(0, dest.a[0]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, ArrayFooEnum) {
+    hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    source.c[0] = hidl2aidl::test::V1_1::Value::A;
+    source.c[1] = hidl2aidl::test::V1_1::Value::B;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<hidl2aidl::test::Value>(source.c[0]), dest.c[0]);
+    EXPECT_EQ(static_cast<hidl2aidl::test::Value>(source.c[1]), dest.c[1]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, ArrayFooString) {
+    hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    source.d[0] = "hello";
+    source.d[1] = "world";
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(source.d[0], String8(dest.d[0]).c_str());
+    EXPECT_EQ(source.d[1], String8(dest.d[1]).c_str());
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFoo) {
+    hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    source.a = {42, 8};
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(source.a[0], dest.a[0]);
+    EXPECT_EQ(source.a[1], dest.a[1]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooEmpty) {
+    hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(0u, dest.a.size());
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooUnsigned) {
+    hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    // source.a is uint32_t, dest.a is int32_t
+    source.b = {12, 0xf0000000};
+    ASSERT_FALSE(h2a::translate(source, &dest));
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooEnum) {
+    hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    source.c = {hidl2aidl::test::V1_1::Value::A, hidl2aidl::test::V1_1::Value::B};
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<hidl2aidl::test::Value>(source.c[0]), dest.c[0]);
+    EXPECT_EQ(static_cast<hidl2aidl::test::Value>(source.c[1]), dest.c[1]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooString) {
+    hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    source.d = {"hello", "world"};
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(source.d[0], String8(dest.d[0]).c_str());
+    EXPECT_EQ(source.d[1], String8(dest.d[1]).c_str());
+}
+
 }  // namespace android
diff --git a/hidl2aidl/test/translate_ndk_test.cpp b/hidl2aidl/test/translate_ndk_test.cpp
index 11b8ae7..125c236 100644
--- a/hidl2aidl/test/translate_ndk_test.cpp
+++ b/hidl2aidl/test/translate_ndk_test.cpp
@@ -23,134 +23,110 @@
 namespace android {
 
 TEST_F(Hidl2aidlTranslateTest, Onlyin10) {
-    bool ret;
     aidl::hidl2aidl::test::OnlyIn10 dest;
     hidl2aidl::test::V1_0::OnlyIn10 source;
     source.str = "Hello";
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.str, dest.str);
 }
 
 TEST_F(Hidl2aidlTranslateTest, OnlyIn11) {
-    bool ret;
     aidl::hidl2aidl::test::OnlyIn11 dest;
     hidl2aidl::test::V1_1::OnlyIn11 source;
     source.str = 12;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.str, dest.str);
 }
 
 TEST_F(Hidl2aidlTranslateTest, OverrideMe) {
-    bool ret;
     aidl::hidl2aidl::test::OverrideMe dest;
     hidl2aidl::test::V1_1::OverrideMe source;
     source.a = "World";
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a, dest.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, Outer) {
-    bool ret;
     aidl::hidl2aidl::test::Outer dest;
     hidl2aidl::test::V1_1::Outer source;
     source.a = 12;
     source.v1_0.inner.a = 16;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a, dest.a);
     EXPECT_EQ(source.v1_0.inner.a, dest.inner.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, OuterInner) {
-    bool ret;
     aidl::hidl2aidl::test::OuterInner dest;
     hidl2aidl::test::V1_0::Outer::Inner source;
     source.a = 12;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a, dest.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, NameCollision) {
-    bool ret;
     aidl::hidl2aidl::test::NameCollision dest;
     hidl2aidl::test::V1_2::NameCollision source;
     source.reference.reference.a = 12;
     source.reference.b = "Fancy";
     source.c = "Car";
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.reference.reference.a, dest.a);
     EXPECT_EQ(source.reference.b, dest.b);
     EXPECT_EQ(source.c, dest.c);
 }
 
 TEST_F(Hidl2aidlTranslateTest, IFooBigStruct) {
-    bool ret;
     aidl::hidl2aidl::test::IFooBigStruct dest;
     hidl2aidl::test::V1_1::IFoo::BigStruct source;
     source.type = 12;
     source.value = 16;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.type, dest.type);
     EXPECT_EQ(source.value, dest.value);
 }
 
 TEST_F(Hidl2aidlTranslateTest, IBarInner) {
-    bool ret;
     aidl::hidl2aidl::test::IBarInner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     source.a = 0x70000000;
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
-    EXPECT_EQ((int32_t)source.a, dest.a);
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<int32_t>(source.a), dest.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, UnsignedToSignedTooLarge) {
-    bool ret;
     aidl::hidl2aidl::test::IBarInner dest;
     hidl2aidl::test::V1_0::IBar::Inner source;
     // source.a is uint32_t, dest.a is int32_t
     source.a = 0xf0000000;
-    ret = h2a::translate(source, &dest);
-    EXPECT_FALSE(ret);
-    EXPECT_NE((int32_t)source.a, dest.a);
+    ASSERT_FALSE(h2a::translate(source, &dest));
+    EXPECT_NE(static_cast<int32_t>(source.a), dest.a);
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarByte) {
-    bool ret;
     aidl::hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.a(8);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.a(), dest.get<aidl::hidl2aidl::test::SafeUnionBar::a>());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarInt64) {
-    bool ret;
     aidl::hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.b(25000);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
-    EXPECT_EQ(source.b(), (uint64_t)dest.get<aidl::hidl2aidl::test::SafeUnionBar::b>());
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<int64_t>(source.b()), dest.get<aidl::hidl2aidl::test::SafeUnionBar::b>());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarInnerStructBar) {
-    bool ret;
     aidl::hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     hidl2aidl::test::V1_2::SafeUnionBar::InnerStructBar inner;
     inner.x = 8;
     inner.z = 12;
     source.innerStructBar(inner);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.innerStructBar().x,
               dest.get<aidl::hidl2aidl::test::SafeUnionBar::innerStructBar>().x);
     EXPECT_EQ(source.innerStructBar().z,
@@ -158,45 +134,120 @@
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarOnlyIn11) {
-    bool ret;
     aidl::hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     hidl2aidl::test::V1_1::OnlyIn11 onlyIn11;
     onlyIn11.str = 12;
     source.c(onlyIn11);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.c().str, dest.get<aidl::hidl2aidl::test::SafeUnionBar::c>().str);
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarString) {
-    bool ret;
     aidl::hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.d("Hello world!");
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.d(), dest.get<aidl::hidl2aidl::test::SafeUnionBar::d>());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarFloat) {
-    bool ret;
     aidl::hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.e(3.5f);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.e(), dest.get<aidl::hidl2aidl::test::SafeUnionBar::e>());
 }
 
 TEST_F(Hidl2aidlTranslateTest, SafeUnionBarDouble) {
-    bool ret;
     aidl::hidl2aidl::test::SafeUnionBar dest;
     hidl2aidl::test::V1_2::SafeUnionBar source;
     source.f(3e10);
-    ret = h2a::translate(source, &dest);
-    EXPECT_TRUE(ret);
+    ASSERT_TRUE(h2a::translate(source, &dest));
     EXPECT_EQ(source.f(), dest.get<aidl::hidl2aidl::test::SafeUnionBar::f>());
 }
 
+TEST_F(Hidl2aidlTranslateTest, ArrayFoo) {
+    aidl::hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    source.a[0] = 42;
+    source.a[1] = 8;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    ASSERT_EQ(12u, dest.a.size());
+    EXPECT_EQ(source.a[0], dest.a[0]);
+    EXPECT_EQ(source.a[1], dest.a[1]);
+    EXPECT_EQ(source.a[2], dest.a[2]);
+    EXPECT_EQ(source.a[11], dest.a[11]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, ArrayFooEmpty) {
+    aidl::hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(12u, dest.a.size());
+    EXPECT_EQ(0, dest.a[0]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, ArrayFooEnum) {
+    aidl::hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    source.c[0] = hidl2aidl::test::V1_1::Value::A;
+    source.c[1] = hidl2aidl::test::V1_1::Value::B;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<aidl::hidl2aidl::test::Value>(source.c[0]), dest.c[0]);
+    EXPECT_EQ(static_cast<aidl::hidl2aidl::test::Value>(source.c[1]), dest.c[1]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, ArrayFooString) {
+    aidl::hidl2aidl::test::ArrayFoo dest;
+    hidl2aidl::test::V1_2::ArrayFoo source;
+    source.d[0] = "hello";
+    source.d[1] = "world";
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(source.d[0], dest.d[0]);
+    EXPECT_EQ(source.d[1], dest.d[1]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFoo) {
+    aidl::hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    source.a = {42, 8};
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(source.a[0], dest.a[0]);
+    EXPECT_EQ(source.a[1], dest.a[1]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooEmpty) {
+    aidl::hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(0u, dest.a.size());
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooUnsigned) {
+    aidl::hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    // source.a is uint32_t, dest.a is int32_t
+    source.b = {12, 0xf0000000};
+    ASSERT_FALSE(h2a::translate(source, &dest));
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooEnum) {
+    aidl::hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    source.c = {hidl2aidl::test::V1_1::Value::A, hidl2aidl::test::V1_1::Value::B};
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(static_cast<aidl::hidl2aidl::test::Value>(source.c[0]), dest.c[0]);
+    EXPECT_EQ(static_cast<aidl::hidl2aidl::test::Value>(source.c[1]), dest.c[1]);
+}
+
+TEST_F(Hidl2aidlTranslateTest, VectorFooString) {
+    aidl::hidl2aidl::test::VectorFoo dest;
+    hidl2aidl::test::V1_2::VectorFoo source;
+    source.d = {"hello", "world"};
+    ASSERT_TRUE(h2a::translate(source, &dest));
+    EXPECT_EQ(source.d[0], dest.d[0]);
+    EXPECT_EQ(source.d[1], dest.d[1]);
+}
+
 }  // namespace android