Add integration test for @utf8InCpp List<String>

Test @nullable support as well since we've never seen two
annotations at once before.

Bug: 26729450
Change-Id: If76d617980e1fda3e5efecc8410786295fe1da9f
Test: unit, integration tests pass
diff --git a/tests/aidl_test_client.cpp b/tests/aidl_test_client.cpp
index af4312b..84c8183 100644
--- a/tests/aidl_test_client.cpp
+++ b/tests/aidl_test_client.cpp
@@ -102,5 +102,7 @@
 
   if (!client_tests::ConfirmUtf8InCppStringArrayReverse(service)) return 1;
 
+  if (!client_tests::ConfirmUtf8InCppStringListReverse(service)) return 1;
+
   return 0;
 }
diff --git a/tests/aidl_test_client_utf8_strings.cpp b/tests/aidl_test_client_utf8_strings.cpp
index 4e5b2e1..216aef7 100644
--- a/tests/aidl_test_client_utf8_strings.cpp
+++ b/tests/aidl_test_client_utf8_strings.cpp
@@ -110,6 +110,57 @@
   return true;
 }
 
+bool ConfirmUtf8InCppStringListReverse(const sp<ITestService>& s) {
+  LOG(INFO) << "Confirming reversing a list of utf8 strings works";
+  unique_ptr<vector<unique_ptr<string>>> input, reversed, repeated;
+  Status status = s->ReverseUtf8CppStringList(input, &reversed, &repeated);
+  if (!status.isOk() || reversed || repeated) {
+    LOG(ERROR) << "Reversing null list of utf8 strings failed.";
+    return false;
+  }
+
+  input.reset(new vector<unique_ptr<string>>);
+  input->emplace_back(new string("Deliver us from evil."));
+  input->emplace_back(nullptr);
+  input->emplace_back(new string("\xF0\x90\x90\xB7\xE2\x82\xAC"));
+
+  status = s->ReverseUtf8CppStringList(input, &repeated, &reversed);
+  if (!status.isOk() || !reversed || !repeated) {
+    LOG(ERROR) << "Reversing list of utf8 strings failed.";
+    return false;
+  }
+  if (reversed->size() != input->size() || repeated->size() != input->size()) {
+    LOG(ERROR) << "Bad output sizes.";
+    return false;
+  }
+
+  for (size_t i = 0; i < input->size(); ++i) {
+    const string* input_str = (*input)[i].get();
+    const string* repeated_str = (*repeated)[i].get();
+    const string* reversed_str = (*reversed)[(reversed->size() - 1) - i].get();
+    if (!input_str) {
+      if(repeated_str || reversed_str) {
+        LOG(ERROR) << "Expected null values, but got non-null.";
+        return false;
+      }
+      // 3 nullptrs to strings.  No need to compare values.
+      continue;
+    }
+    if (!repeated_str || !reversed_str) {
+      LOG(ERROR) << "Expected non-null values, but got null.";
+      return false;
+    }
+    if (*input_str != *repeated_str || *input_str != *reversed_str) {
+      LOG(ERROR) << "Expected '" << *input_str << "' but got "
+                 << "repeated='" << *repeated_str << "' and "
+                 << "reversed='" << *reversed_str;
+      return false;
+    }
+  }
+  return true;
+}
+
+
 }  // namespace client
 }  // namespace tests
 }  // namespace aidl
diff --git a/tests/aidl_test_client_utf8_strings.h b/tests/aidl_test_client_utf8_strings.h
index a1e160e..a362fd5 100644
--- a/tests/aidl_test_client_utf8_strings.h
+++ b/tests/aidl_test_client_utf8_strings.h
@@ -31,6 +31,8 @@
     const android::sp<android::aidl::tests::ITestService>& s);
 bool ConfirmUtf8InCppStringArrayReverse(
     const android::sp<android::aidl::tests::ITestService>& s);
+bool ConfirmUtf8InCppStringListReverse(
+    const android::sp<android::aidl::tests::ITestService>& s);
 
 }  // namespace client
 }  // namespace tests
diff --git a/tests/aidl_test_service.cpp b/tests/aidl_test_service.cpp
index 1046f99..a3e83e9 100644
--- a/tests/aidl_test_service.cpp
+++ b/tests/aidl_test_service.cpp
@@ -368,6 +368,30 @@
     return ReverseArray(input, repeated, _aidl_return);
   }
 
+  Status ReverseUtf8CppStringList(
+      const unique_ptr<vector<unique_ptr<::string>>>& input,
+      unique_ptr<vector<unique_ptr<string>>>* repeated,
+      unique_ptr<vector<unique_ptr<string>>>* _aidl_return) {
+    if (!input) {
+      ALOGI("Received null list of utf8 strings");
+      return Status::ok();
+    }
+    _aidl_return->reset(new vector<unique_ptr<string>>);
+    repeated->reset(new vector<unique_ptr<string>>);
+
+    for (const auto& item : *input) {
+      (*repeated)->emplace_back(nullptr);
+      (*_aidl_return)->emplace_back(nullptr);
+      if (item) {
+        (*repeated)->back().reset(new string(*item));
+        (*_aidl_return)->back().reset(new string(*item));
+      }
+    }
+    std::reverse((*_aidl_return)->begin(), (*_aidl_return)->end());
+
+    return Status::ok();
+  }
+
  private:
   map<String16, sp<INamedCallback>> service_map_;
 };
diff --git a/tests/android/aidl/tests/ITestService.aidl b/tests/android/aidl/tests/ITestService.aidl
index 8d92e05..7d37691 100644
--- a/tests/android/aidl/tests/ITestService.aidl
+++ b/tests/android/aidl/tests/ITestService.aidl
@@ -91,9 +91,7 @@
   @utf8InCpp String[]  ReverseUtf8CppString (in @utf8InCpp String[] input,
                                              out @utf8InCpp String[] repeated);
 
-  /* This type is not implemented yet.
-  @utf8InCpp List<String> ReverseUtf8CppStringList(
-      in @utf8InCpp List<String> input,
-      out List<String> repeated);
-  */
+  @nullable @utf8InCpp List<String> ReverseUtf8CppStringList(
+      in @nullable @utf8InCpp List<String> input,
+      out @nullable @utf8InCpp List<String> repeated);
 }