1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker *
4*993b0882SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker *
8*993b0882SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker *
10*993b0882SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker */
16*993b0882SAndroid Build Coastguard Worker
17*993b0882SAndroid Build Coastguard Worker #include <jni.h>
18*993b0882SAndroid Build Coastguard Worker
19*993b0882SAndroid Build Coastguard Worker #include <memory>
20*993b0882SAndroid Build Coastguard Worker #include <vector>
21*993b0882SAndroid Build Coastguard Worker
22*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/mutable.h"
23*993b0882SAndroid Build Coastguard Worker #include "utils/intents/intent-generator.h"
24*993b0882SAndroid Build Coastguard Worker #include "utils/intents/remote-action-template.h"
25*993b0882SAndroid Build Coastguard Worker #include "utils/java/jni-helper.h"
26*993b0882SAndroid Build Coastguard Worker #include "utils/jvm-test-utils.h"
27*993b0882SAndroid Build Coastguard Worker #include "utils/resources_generated.h"
28*993b0882SAndroid Build Coastguard Worker #include "utils/testing/logging_event_listener.h"
29*993b0882SAndroid Build Coastguard Worker #include "utils/variant.h"
30*993b0882SAndroid Build Coastguard Worker #include "gmock/gmock.h"
31*993b0882SAndroid Build Coastguard Worker #include "gtest/gtest.h"
32*993b0882SAndroid Build Coastguard Worker #include "flatbuffers/reflection.h"
33*993b0882SAndroid Build Coastguard Worker
34*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
35*993b0882SAndroid Build Coastguard Worker namespace {
36*993b0882SAndroid Build Coastguard Worker
37*993b0882SAndroid Build Coastguard Worker using ::testing::ElementsAre;
38*993b0882SAndroid Build Coastguard Worker using ::testing::IsEmpty;
39*993b0882SAndroid Build Coastguard Worker using ::testing::SizeIs;
40*993b0882SAndroid Build Coastguard Worker
BuildTestIntentFactoryModel(const std::string & entity_type,const std::string & generator_code)41*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer BuildTestIntentFactoryModel(
42*993b0882SAndroid Build Coastguard Worker const std::string& entity_type, const std::string& generator_code) {
43*993b0882SAndroid Build Coastguard Worker // Test intent generation options.
44*993b0882SAndroid Build Coastguard Worker IntentFactoryModelT options;
45*993b0882SAndroid Build Coastguard Worker options.generator.emplace_back(new IntentFactoryModel_::IntentGeneratorT());
46*993b0882SAndroid Build Coastguard Worker options.generator.back()->type = entity_type;
47*993b0882SAndroid Build Coastguard Worker options.generator.back()->lua_template_generator = std::vector<unsigned char>(
48*993b0882SAndroid Build Coastguard Worker generator_code.data(), generator_code.data() + generator_code.size());
49*993b0882SAndroid Build Coastguard Worker flatbuffers::FlatBufferBuilder builder;
50*993b0882SAndroid Build Coastguard Worker builder.Finish(IntentFactoryModel::Pack(builder, &options));
51*993b0882SAndroid Build Coastguard Worker return builder.Release();
52*993b0882SAndroid Build Coastguard Worker }
53*993b0882SAndroid Build Coastguard Worker
BuildTestResources()54*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer BuildTestResources() {
55*993b0882SAndroid Build Coastguard Worker // Custom string resources.
56*993b0882SAndroid Build Coastguard Worker ResourcePoolT test_resources;
57*993b0882SAndroid Build Coastguard Worker test_resources.locale.emplace_back(new LanguageTagT);
58*993b0882SAndroid Build Coastguard Worker test_resources.locale.back()->language = "en";
59*993b0882SAndroid Build Coastguard Worker test_resources.locale.emplace_back(new LanguageTagT);
60*993b0882SAndroid Build Coastguard Worker test_resources.locale.back()->language = "de";
61*993b0882SAndroid Build Coastguard Worker
62*993b0882SAndroid Build Coastguard Worker // Add `add_calendar_event`
63*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.emplace_back(new ResourceEntryT);
64*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->name = "add_calendar_event";
65*993b0882SAndroid Build Coastguard Worker
66*993b0882SAndroid Build Coastguard Worker // en
67*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.emplace_back(new ResourceT);
68*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->content = "Schedule";
69*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->locale.push_back(0);
70*993b0882SAndroid Build Coastguard Worker
71*993b0882SAndroid Build Coastguard Worker // Add `add_calendar_event_desc`
72*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.emplace_back(new ResourceEntryT);
73*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->name = "add_calendar_event_desc";
74*993b0882SAndroid Build Coastguard Worker
75*993b0882SAndroid Build Coastguard Worker // en
76*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.emplace_back(new ResourceT);
77*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->content =
78*993b0882SAndroid Build Coastguard Worker "Schedule event for selected time";
79*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->locale.push_back(0);
80*993b0882SAndroid Build Coastguard Worker
81*993b0882SAndroid Build Coastguard Worker // Add `map`.
82*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.emplace_back(new ResourceEntryT);
83*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->name = "map";
84*993b0882SAndroid Build Coastguard Worker
85*993b0882SAndroid Build Coastguard Worker // en
86*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.emplace_back(new ResourceT);
87*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->content = "Map";
88*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->locale.push_back(0);
89*993b0882SAndroid Build Coastguard Worker
90*993b0882SAndroid Build Coastguard Worker // de
91*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.emplace_back(new ResourceT);
92*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->content = "Karte";
93*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->locale.push_back(1);
94*993b0882SAndroid Build Coastguard Worker
95*993b0882SAndroid Build Coastguard Worker // Add `map_desc`.
96*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.emplace_back(new ResourceEntryT);
97*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->name = "map_desc";
98*993b0882SAndroid Build Coastguard Worker
99*993b0882SAndroid Build Coastguard Worker // en
100*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.emplace_back(new ResourceT);
101*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->content =
102*993b0882SAndroid Build Coastguard Worker "Locate selected address";
103*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->locale.push_back(0);
104*993b0882SAndroid Build Coastguard Worker
105*993b0882SAndroid Build Coastguard Worker // de
106*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.emplace_back(new ResourceT);
107*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->content =
108*993b0882SAndroid Build Coastguard Worker "Ausgewählte Adresse finden";
109*993b0882SAndroid Build Coastguard Worker test_resources.resource_entry.back()->resource.back()->locale.push_back(1);
110*993b0882SAndroid Build Coastguard Worker
111*993b0882SAndroid Build Coastguard Worker flatbuffers::FlatBufferBuilder builder;
112*993b0882SAndroid Build Coastguard Worker builder.Finish(ResourcePool::Pack(builder, &test_resources));
113*993b0882SAndroid Build Coastguard Worker return builder.Release();
114*993b0882SAndroid Build Coastguard Worker }
115*993b0882SAndroid Build Coastguard Worker
116*993b0882SAndroid Build Coastguard Worker // Common methods for intent generator tests.
117*993b0882SAndroid Build Coastguard Worker class IntentGeneratorTest : public testing::Test {
118*993b0882SAndroid Build Coastguard Worker protected:
IntentGeneratorTest()119*993b0882SAndroid Build Coastguard Worker explicit IntentGeneratorTest()
120*993b0882SAndroid Build Coastguard Worker : jni_cache_(JniCache::Create(GetJenv())),
121*993b0882SAndroid Build Coastguard Worker resource_buffer_(BuildTestResources()),
122*993b0882SAndroid Build Coastguard Worker resources_(
123*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<ResourcePool>(resource_buffer_.data())) {}
124*993b0882SAndroid Build Coastguard Worker
125*993b0882SAndroid Build Coastguard Worker const std::shared_ptr<JniCache> jni_cache_;
126*993b0882SAndroid Build Coastguard Worker const flatbuffers::DetachedBuffer resource_buffer_;
127*993b0882SAndroid Build Coastguard Worker const ResourcePool* resources_;
128*993b0882SAndroid Build Coastguard Worker };
129*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesDefaultClassification)130*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesDefaultClassification) {
131*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
132*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("unused", "");
133*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
134*993b0882SAndroid Build Coastguard Worker /*options=*/flatbuffers::GetRoot<IntentFactoryModel>(
135*993b0882SAndroid Build Coastguard Worker intent_factory_model.data()),
136*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_,
137*993b0882SAndroid Build Coastguard Worker /*jni_cache=*/jni_cache_);
138*993b0882SAndroid Build Coastguard Worker ClassificationResult classification;
139*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
140*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
141*993b0882SAndroid Build Coastguard Worker /*device_locales=*/nullptr, classification, /*reference_time_ms_utc=*/0,
142*993b0882SAndroid Build Coastguard Worker /*text=*/"", /*selection_indices=*/{kInvalidIndex, kInvalidIndex},
143*993b0882SAndroid Build Coastguard Worker /*context=*/nullptr,
144*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
145*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
146*993b0882SAndroid Build Coastguard Worker &intents));
147*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, IsEmpty());
148*993b0882SAndroid Build Coastguard Worker }
149*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,FailsGracefully)150*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, FailsGracefully) {
151*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
152*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("test", R"lua(
153*993b0882SAndroid Build Coastguard Worker return {
154*993b0882SAndroid Build Coastguard Worker {
155*993b0882SAndroid Build Coastguard Worker -- Should fail, as no app GetAndroidContext() is provided.
156*993b0882SAndroid Build Coastguard Worker data = external.android.package_name,
157*993b0882SAndroid Build Coastguard Worker }
158*993b0882SAndroid Build Coastguard Worker })lua");
159*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
160*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
161*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
162*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"test", 1.0};
163*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
164*993b0882SAndroid Build Coastguard Worker EXPECT_FALSE(generator->GenerateIntents(
165*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
166*993b0882SAndroid Build Coastguard Worker classification,
167*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "test", {0, 4}, /*context=*/nullptr,
168*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
169*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
170*993b0882SAndroid Build Coastguard Worker &intents));
171*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, IsEmpty());
172*993b0882SAndroid Build Coastguard Worker }
173*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesEntityIntentGeneration)174*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesEntityIntentGeneration) {
175*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
176*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("address", R"lua(
177*993b0882SAndroid Build Coastguard Worker return {
178*993b0882SAndroid Build Coastguard Worker {
179*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.map,
180*993b0882SAndroid Build Coastguard Worker title_with_entity = external.entity.text,
181*993b0882SAndroid Build Coastguard Worker description = external.android.R.map_desc,
182*993b0882SAndroid Build Coastguard Worker action = "android.intent.action.VIEW",
183*993b0882SAndroid Build Coastguard Worker data = "geo:0,0?q=" ..
184*993b0882SAndroid Build Coastguard Worker external.android.urlencode(external.entity.text),
185*993b0882SAndroid Build Coastguard Worker }
186*993b0882SAndroid Build Coastguard Worker })lua");
187*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
188*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
189*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
190*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"address", 1.0};
191*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
192*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
193*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
194*993b0882SAndroid Build Coastguard Worker classification,
195*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "333 E Wonderview Ave", {0, 20},
196*993b0882SAndroid Build Coastguard Worker GetAndroidContext(),
197*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
198*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
199*993b0882SAndroid Build Coastguard Worker &intents));
200*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
201*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].title_without_entity.value(), "Map");
202*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].title_with_entity.value(), "333 E Wonderview Ave");
203*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].description.value(), "Locate selected address");
204*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].action.value(), "android.intent.action.VIEW");
205*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].data.value(), "geo:0,0?q=333%20E%20Wonderview%20Ave");
206*993b0882SAndroid Build Coastguard Worker }
207*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesAddContactIntentEnabledGeneration)208*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesAddContactIntentEnabledGeneration) {
209*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
210*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("address", R"lua(
211*993b0882SAndroid Build Coastguard Worker if external.enable_add_contact_intent then return {
212*993b0882SAndroid Build Coastguard Worker {
213*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.map,
214*993b0882SAndroid Build Coastguard Worker title_with_entity = external.entity.text,
215*993b0882SAndroid Build Coastguard Worker description = external.android.R.map_desc,
216*993b0882SAndroid Build Coastguard Worker action = "android.intent.action.VIEW",
217*993b0882SAndroid Build Coastguard Worker data = "geo:0,0?q=" ..
218*993b0882SAndroid Build Coastguard Worker external.android.urlencode(external.entity.text),
219*993b0882SAndroid Build Coastguard Worker }
220*993b0882SAndroid Build Coastguard Worker } else return {} end)lua");
221*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
222*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
223*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
224*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"address", 1.0};
225*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
226*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
227*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
228*993b0882SAndroid Build Coastguard Worker classification,
229*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "333 E Wonderview Ave", {0, 20},
230*993b0882SAndroid Build Coastguard Worker GetAndroidContext(),
231*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
232*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/true, /*enable_search_intent=*/false,
233*993b0882SAndroid Build Coastguard Worker &intents));
234*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
235*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].title_without_entity.value(), "Map");
236*993b0882SAndroid Build Coastguard Worker }
237*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesAddContactIntentDisabledGeneration)238*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesAddContactIntentDisabledGeneration) {
239*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
240*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("address", R"lua(
241*993b0882SAndroid Build Coastguard Worker if external.enable_add_contact_intent then return {
242*993b0882SAndroid Build Coastguard Worker {
243*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.map,
244*993b0882SAndroid Build Coastguard Worker title_with_entity = external.entity.text,
245*993b0882SAndroid Build Coastguard Worker description = external.android.R.map_desc,
246*993b0882SAndroid Build Coastguard Worker action = "android.intent.action.VIEW",
247*993b0882SAndroid Build Coastguard Worker data = "geo:0,0?q=" ..
248*993b0882SAndroid Build Coastguard Worker external.android.urlencode(external.entity.text),
249*993b0882SAndroid Build Coastguard Worker }
250*993b0882SAndroid Build Coastguard Worker } else return {} end)lua");
251*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
252*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
253*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
254*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"address", 1.0};
255*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
256*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
257*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
258*993b0882SAndroid Build Coastguard Worker classification,
259*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "333 E Wonderview Ave", {0, 20},
260*993b0882SAndroid Build Coastguard Worker GetAndroidContext(),
261*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
262*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
263*993b0882SAndroid Build Coastguard Worker &intents));
264*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(0));
265*993b0882SAndroid Build Coastguard Worker }
266*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesAddSearchIntentEnabledGeneration)267*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesAddSearchIntentEnabledGeneration) {
268*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
269*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("address", R"lua(
270*993b0882SAndroid Build Coastguard Worker if external.enable_search_intent then return {
271*993b0882SAndroid Build Coastguard Worker {
272*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.map,
273*993b0882SAndroid Build Coastguard Worker title_with_entity = external.entity.text,
274*993b0882SAndroid Build Coastguard Worker description = external.android.R.map_desc,
275*993b0882SAndroid Build Coastguard Worker action = "android.intent.action.VIEW",
276*993b0882SAndroid Build Coastguard Worker data = "geo:0,0?q=" ..
277*993b0882SAndroid Build Coastguard Worker external.android.urlencode(external.entity.text),
278*993b0882SAndroid Build Coastguard Worker }
279*993b0882SAndroid Build Coastguard Worker } else return {} end)lua");
280*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
281*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
282*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
283*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"address", 1.0};
284*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
285*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
286*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
287*993b0882SAndroid Build Coastguard Worker classification,
288*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "333 E Wonderview Ave", {0, 20},
289*993b0882SAndroid Build Coastguard Worker GetAndroidContext(),
290*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
291*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/true,
292*993b0882SAndroid Build Coastguard Worker &intents));
293*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
294*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].title_without_entity.value(), "Map");
295*993b0882SAndroid Build Coastguard Worker }
296*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesSearchIntentDisabledGeneration)297*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesSearchIntentDisabledGeneration) {
298*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
299*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("address", R"lua(
300*993b0882SAndroid Build Coastguard Worker if external.enable_search_intent then return {
301*993b0882SAndroid Build Coastguard Worker {
302*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.map,
303*993b0882SAndroid Build Coastguard Worker title_with_entity = external.entity.text,
304*993b0882SAndroid Build Coastguard Worker description = external.android.R.map_desc,
305*993b0882SAndroid Build Coastguard Worker action = "android.intent.action.VIEW",
306*993b0882SAndroid Build Coastguard Worker data = "geo:0,0?q=" ..
307*993b0882SAndroid Build Coastguard Worker external.android.urlencode(external.entity.text),
308*993b0882SAndroid Build Coastguard Worker }
309*993b0882SAndroid Build Coastguard Worker } else return {} end)lua");
310*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
311*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
312*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
313*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"address", 1.0};
314*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
315*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
316*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
317*993b0882SAndroid Build Coastguard Worker classification,
318*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "333 E Wonderview Ave", {0, 20},
319*993b0882SAndroid Build Coastguard Worker GetAndroidContext(),
320*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
321*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
322*993b0882SAndroid Build Coastguard Worker &intents));
323*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(0));
324*993b0882SAndroid Build Coastguard Worker }
325*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesCallbacks)326*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesCallbacks) {
327*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
328*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("test", R"lua(
329*993b0882SAndroid Build Coastguard Worker local test = external.entity["text"]
330*993b0882SAndroid Build Coastguard Worker return {
331*993b0882SAndroid Build Coastguard Worker {
332*993b0882SAndroid Build Coastguard Worker data = "encoded=" .. external.android.urlencode(test),
333*993b0882SAndroid Build Coastguard Worker category = { "test_category" },
334*993b0882SAndroid Build Coastguard Worker extra = {
335*993b0882SAndroid Build Coastguard Worker { name = "package", string_value = external.android.package_name},
336*993b0882SAndroid Build Coastguard Worker { name = "scheme",
337*993b0882SAndroid Build Coastguard Worker string_value = external.android.url_schema("https://google.com")},
338*993b0882SAndroid Build Coastguard Worker { name = "host",
339*993b0882SAndroid Build Coastguard Worker string_value = external.android.url_host("https://google.com/search")},
340*993b0882SAndroid Build Coastguard Worker { name = "permission",
341*993b0882SAndroid Build Coastguard Worker bool_value = external.android.user_restrictions["no_sms"] },
342*993b0882SAndroid Build Coastguard Worker { name = "language",
343*993b0882SAndroid Build Coastguard Worker string_value = external.android.device_locales[1].language },
344*993b0882SAndroid Build Coastguard Worker { name = "description",
345*993b0882SAndroid Build Coastguard Worker string_value = external.format("$1 $0", "hello", "world") },
346*993b0882SAndroid Build Coastguard Worker },
347*993b0882SAndroid Build Coastguard Worker request_code = external.hash(test)
348*993b0882SAndroid Build Coastguard Worker }
349*993b0882SAndroid Build Coastguard Worker })lua");
350*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
351*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
352*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
353*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"test", 1.0};
354*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
355*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
356*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
357*993b0882SAndroid Build Coastguard Worker classification,
358*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "this is a test", {0, 14},
359*993b0882SAndroid Build Coastguard Worker GetAndroidContext(),
360*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
361*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
362*993b0882SAndroid Build Coastguard Worker &intents));
363*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
364*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].data.value(), "encoded=this%20is%20a%20test");
365*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents[0].category, ElementsAre("test_category"));
366*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents[0].extra, SizeIs(6));
367*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["package"].ConstRefValue<std::string>(),
368*993b0882SAndroid Build Coastguard Worker "com.google.android.textclassifier.tests"
369*993b0882SAndroid Build Coastguard Worker );
370*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["scheme"].ConstRefValue<std::string>(), "https");
371*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["host"].ConstRefValue<std::string>(),
372*993b0882SAndroid Build Coastguard Worker "google.com");
373*993b0882SAndroid Build Coastguard Worker EXPECT_FALSE(intents[0].extra["permission"].Value<bool>());
374*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["language"].ConstRefValue<std::string>(), "en");
375*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(intents[0].request_code.has_value());
376*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["description"].ConstRefValue<std::string>(),
377*993b0882SAndroid Build Coastguard Worker "world hello");
378*993b0882SAndroid Build Coastguard Worker }
379*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesActionIntentGeneration)380*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesActionIntentGeneration) {
381*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
382*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("view_map", R"lua(
383*993b0882SAndroid Build Coastguard Worker return {
384*993b0882SAndroid Build Coastguard Worker {
385*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.map,
386*993b0882SAndroid Build Coastguard Worker description = external.android.R.map_desc,
387*993b0882SAndroid Build Coastguard Worker description_with_app_name = external.android.R.map,
388*993b0882SAndroid Build Coastguard Worker action = "android.intent.action.VIEW",
389*993b0882SAndroid Build Coastguard Worker data = "geo:0,0?q=" ..
390*993b0882SAndroid Build Coastguard Worker external.android.urlencode(external.entity.annotation["location"].text),
391*993b0882SAndroid Build Coastguard Worker }
392*993b0882SAndroid Build Coastguard Worker })lua");
393*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
394*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
395*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
396*993b0882SAndroid Build Coastguard Worker Conversation conversation = {{{/*user_id=*/1, "hello there"}}};
397*993b0882SAndroid Build Coastguard Worker ActionSuggestionAnnotation annotation;
398*993b0882SAndroid Build Coastguard Worker annotation.entity = {"address", 1.0};
399*993b0882SAndroid Build Coastguard Worker annotation.span = {/*message_index=*/0,
400*993b0882SAndroid Build Coastguard Worker /*span=*/{6, 11},
401*993b0882SAndroid Build Coastguard Worker /*text=*/"there"};
402*993b0882SAndroid Build Coastguard Worker annotation.name = "location";
403*993b0882SAndroid Build Coastguard Worker ActionSuggestion suggestion = {/*response_text=""*/ "",
404*993b0882SAndroid Build Coastguard Worker /*type=*/"view_map",
405*993b0882SAndroid Build Coastguard Worker /*score=*/1.0,
406*993b0882SAndroid Build Coastguard Worker /*priority_score=*/0.0,
407*993b0882SAndroid Build Coastguard Worker /*annotations=*/
408*993b0882SAndroid Build Coastguard Worker {annotation}};
409*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
410*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
411*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
412*993b0882SAndroid Build Coastguard Worker suggestion, conversation, GetAndroidContext(),
413*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
414*993b0882SAndroid Build Coastguard Worker /*actions_entity_data_schema=*/nullptr, &intents));
415*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
416*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].title_without_entity.value(), "Map");
417*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].description.value(), "Locate selected address");
418*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].description_with_app_name.value(), "Map");
419*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].action.value(), "android.intent.action.VIEW");
420*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].data.value(), "geo:0,0?q=there");
421*993b0882SAndroid Build Coastguard Worker }
422*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesTimezoneAndReferenceTime)423*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesTimezoneAndReferenceTime) {
424*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
425*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("test", R"lua(
426*993b0882SAndroid Build Coastguard Worker local conversation = external.conversation
427*993b0882SAndroid Build Coastguard Worker return {
428*993b0882SAndroid Build Coastguard Worker {
429*993b0882SAndroid Build Coastguard Worker extra = {
430*993b0882SAndroid Build Coastguard Worker { name = "timezone", string_value = conversation[#conversation].timezone },
431*993b0882SAndroid Build Coastguard Worker { name = "num_messages", int_value = #conversation },
432*993b0882SAndroid Build Coastguard Worker { name = "reference_time", long_value = conversation[#conversation].time_ms_utc }
433*993b0882SAndroid Build Coastguard Worker },
434*993b0882SAndroid Build Coastguard Worker }
435*993b0882SAndroid Build Coastguard Worker })lua");
436*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
437*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
438*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
439*993b0882SAndroid Build Coastguard Worker Conversation conversation = {
440*993b0882SAndroid Build Coastguard Worker {{/*user_id=*/0, "hello there", /*reference_time_ms_utc=*/0,
441*993b0882SAndroid Build Coastguard Worker /*reference_timezone=*/"Testing/Test"},
442*993b0882SAndroid Build Coastguard Worker {/*user_id=*/1, "general retesti", /*reference_time_ms_utc=*/1000,
443*993b0882SAndroid Build Coastguard Worker /*reference_timezone=*/"Europe/Zurich"}}};
444*993b0882SAndroid Build Coastguard Worker ActionSuggestion suggestion = {/*response_text=""*/ "",
445*993b0882SAndroid Build Coastguard Worker /*type=*/"test",
446*993b0882SAndroid Build Coastguard Worker /*score=*/1.0,
447*993b0882SAndroid Build Coastguard Worker /*priority_score=*/0.0,
448*993b0882SAndroid Build Coastguard Worker /*annotations=*/
449*993b0882SAndroid Build Coastguard Worker {}};
450*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
451*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
452*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
453*993b0882SAndroid Build Coastguard Worker suggestion, conversation, GetAndroidContext(),
454*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
455*993b0882SAndroid Build Coastguard Worker /*actions_entity_data_schema=*/nullptr, &intents));
456*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
457*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["timezone"].ConstRefValue<std::string>(),
458*993b0882SAndroid Build Coastguard Worker "Europe/Zurich");
459*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["num_messages"].Value<int>(), 2);
460*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["reference_time"].Value<int64>(), 1000);
461*993b0882SAndroid Build Coastguard Worker }
462*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesActionIntentGenerationMultipleAnnotations)463*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesActionIntentGenerationMultipleAnnotations) {
464*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
465*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("create_event", R"lua(
466*993b0882SAndroid Build Coastguard Worker return {
467*993b0882SAndroid Build Coastguard Worker {
468*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.add_calendar_event,
469*993b0882SAndroid Build Coastguard Worker description = external.android.R.add_calendar_event_desc,
470*993b0882SAndroid Build Coastguard Worker extra = {
471*993b0882SAndroid Build Coastguard Worker {name = "time", string_value =
472*993b0882SAndroid Build Coastguard Worker external.entity.annotation["time"].text},
473*993b0882SAndroid Build Coastguard Worker {name = "location",
474*993b0882SAndroid Build Coastguard Worker string_value = external.entity.annotation["location"].text},
475*993b0882SAndroid Build Coastguard Worker }
476*993b0882SAndroid Build Coastguard Worker }
477*993b0882SAndroid Build Coastguard Worker })lua");
478*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
479*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
480*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
481*993b0882SAndroid Build Coastguard Worker Conversation conversation = {{{/*user_id=*/1, "hello there at 1pm"}}};
482*993b0882SAndroid Build Coastguard Worker ActionSuggestionAnnotation location_annotation, time_annotation;
483*993b0882SAndroid Build Coastguard Worker location_annotation.entity = {"address", 1.0};
484*993b0882SAndroid Build Coastguard Worker location_annotation.span = {/*message_index=*/0,
485*993b0882SAndroid Build Coastguard Worker /*span=*/{6, 11},
486*993b0882SAndroid Build Coastguard Worker /*text=*/"there"};
487*993b0882SAndroid Build Coastguard Worker location_annotation.name = "location";
488*993b0882SAndroid Build Coastguard Worker time_annotation.entity = {"datetime", 1.0};
489*993b0882SAndroid Build Coastguard Worker time_annotation.span = {/*message_index=*/0,
490*993b0882SAndroid Build Coastguard Worker /*span=*/{15, 18},
491*993b0882SAndroid Build Coastguard Worker /*text=*/"1pm"};
492*993b0882SAndroid Build Coastguard Worker time_annotation.name = "time";
493*993b0882SAndroid Build Coastguard Worker ActionSuggestion suggestion = {/*response_text=""*/ "",
494*993b0882SAndroid Build Coastguard Worker /*type=*/"create_event",
495*993b0882SAndroid Build Coastguard Worker /*score=*/1.0,
496*993b0882SAndroid Build Coastguard Worker /*priority_score=*/0.0,
497*993b0882SAndroid Build Coastguard Worker /*annotations=*/
498*993b0882SAndroid Build Coastguard Worker {location_annotation, time_annotation}};
499*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
500*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
501*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
502*993b0882SAndroid Build Coastguard Worker suggestion, conversation, GetAndroidContext(),
503*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
504*993b0882SAndroid Build Coastguard Worker /*actions_entity_data_schema=*/nullptr, &intents));
505*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
506*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].title_without_entity.value(), "Schedule");
507*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents[0].extra, SizeIs(2));
508*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["location"].ConstRefValue<std::string>(), "there");
509*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["time"].ConstRefValue<std::string>(), "1pm");
510*993b0882SAndroid Build Coastguard Worker }
511*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesActionIntentGenerationMultipleAnnotationsWithIndices)512*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest,
513*993b0882SAndroid Build Coastguard Worker HandlesActionIntentGenerationMultipleAnnotationsWithIndices) {
514*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
515*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("time_range", R"lua(
516*993b0882SAndroid Build Coastguard Worker return {
517*993b0882SAndroid Build Coastguard Worker {
518*993b0882SAndroid Build Coastguard Worker title_without_entity = "test",
519*993b0882SAndroid Build Coastguard Worker description = "test",
520*993b0882SAndroid Build Coastguard Worker extra = {
521*993b0882SAndroid Build Coastguard Worker {name = "from", string_value = external.entity.annotation[1].text},
522*993b0882SAndroid Build Coastguard Worker {name = "to", string_value = external.entity.annotation[2].text},
523*993b0882SAndroid Build Coastguard Worker }
524*993b0882SAndroid Build Coastguard Worker }
525*993b0882SAndroid Build Coastguard Worker })lua");
526*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
527*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
528*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
529*993b0882SAndroid Build Coastguard Worker Conversation conversation = {{{/*user_id=*/1, "from 1pm to 2pm"}}};
530*993b0882SAndroid Build Coastguard Worker ActionSuggestionAnnotation from_annotation, to_annotation;
531*993b0882SAndroid Build Coastguard Worker from_annotation.entity = {"datetime", 1.0};
532*993b0882SAndroid Build Coastguard Worker from_annotation.span = {/*message_index=*/0,
533*993b0882SAndroid Build Coastguard Worker /*span=*/{5, 8},
534*993b0882SAndroid Build Coastguard Worker /*text=*/"1pm"};
535*993b0882SAndroid Build Coastguard Worker to_annotation.entity = {"datetime", 1.0};
536*993b0882SAndroid Build Coastguard Worker to_annotation.span = {/*message_index=*/0,
537*993b0882SAndroid Build Coastguard Worker /*span=*/{12, 15},
538*993b0882SAndroid Build Coastguard Worker /*text=*/"2pm"};
539*993b0882SAndroid Build Coastguard Worker ActionSuggestion suggestion = {/*response_text=""*/ "",
540*993b0882SAndroid Build Coastguard Worker /*type=*/"time_range",
541*993b0882SAndroid Build Coastguard Worker /*score=*/1.0,
542*993b0882SAndroid Build Coastguard Worker /*priority_score=*/0.0,
543*993b0882SAndroid Build Coastguard Worker /*annotations=*/
544*993b0882SAndroid Build Coastguard Worker {from_annotation, to_annotation}};
545*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
546*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
547*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
548*993b0882SAndroid Build Coastguard Worker suggestion, conversation, GetAndroidContext(),
549*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
550*993b0882SAndroid Build Coastguard Worker /*actions_entity_data_schema=*/nullptr, &intents));
551*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
552*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents[0].extra, SizeIs(2));
553*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["from"].ConstRefValue<std::string>(), "1pm");
554*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["to"].ConstRefValue<std::string>(), "2pm");
555*993b0882SAndroid Build Coastguard Worker }
556*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesResources)557*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesResources) {
558*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
559*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("address", R"lua(
560*993b0882SAndroid Build Coastguard Worker return {
561*993b0882SAndroid Build Coastguard Worker {
562*993b0882SAndroid Build Coastguard Worker title_without_entity = external.android.R.map,
563*993b0882SAndroid Build Coastguard Worker description = external.android.R.map_desc,
564*993b0882SAndroid Build Coastguard Worker action = "android.intent.action.VIEW",
565*993b0882SAndroid Build Coastguard Worker data = "geo:0,0?q=" ..
566*993b0882SAndroid Build Coastguard Worker external.android.urlencode(external.entity.text),
567*993b0882SAndroid Build Coastguard Worker }
568*993b0882SAndroid Build Coastguard Worker })lua");
569*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
570*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
571*993b0882SAndroid Build Coastguard Worker resources_, jni_cache_);
572*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"address", 1.0};
573*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
574*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
575*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "de-DE").ValueOrDie().get(),
576*993b0882SAndroid Build Coastguard Worker classification,
577*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "333 E Wonderview Ave", {0, 20},
578*993b0882SAndroid Build Coastguard Worker GetAndroidContext(),
579*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
580*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
581*993b0882SAndroid Build Coastguard Worker &intents));
582*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
583*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].title_without_entity.value(), "Karte");
584*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].description.value(), "Ausgewählte Adresse finden");
585*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].action.value(), "android.intent.action.VIEW");
586*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].data.value(), "geo:0,0?q=333%20E%20Wonderview%20Ave");
587*993b0882SAndroid Build Coastguard Worker }
588*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesIteration)589*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesIteration) {
590*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
591*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("iteration_test", R"lua(
592*993b0882SAndroid Build Coastguard Worker local extra = {{ name = "length", int_value = #external.entity.annotation }}
593*993b0882SAndroid Build Coastguard Worker for annotation_id, annotation in pairs(external.entity.annotation) do
594*993b0882SAndroid Build Coastguard Worker table.insert(extra,
595*993b0882SAndroid Build Coastguard Worker { name = annotation.name,
596*993b0882SAndroid Build Coastguard Worker string_value = annotation.text })
597*993b0882SAndroid Build Coastguard Worker end
598*993b0882SAndroid Build Coastguard Worker return {{ extra = extra }})lua");
599*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
600*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
601*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
602*993b0882SAndroid Build Coastguard Worker Conversation conversation = {{{/*user_id=*/1, "hello there"}}};
603*993b0882SAndroid Build Coastguard Worker ActionSuggestionAnnotation location_annotation;
604*993b0882SAndroid Build Coastguard Worker location_annotation.entity = {"address", 1.0};
605*993b0882SAndroid Build Coastguard Worker location_annotation.span = {/*message_index=*/0,
606*993b0882SAndroid Build Coastguard Worker /*span=*/{6, 11},
607*993b0882SAndroid Build Coastguard Worker /*text=*/"there"};
608*993b0882SAndroid Build Coastguard Worker location_annotation.name = "location";
609*993b0882SAndroid Build Coastguard Worker ActionSuggestionAnnotation greeting_annotation;
610*993b0882SAndroid Build Coastguard Worker greeting_annotation.entity = {"greeting", 1.0};
611*993b0882SAndroid Build Coastguard Worker greeting_annotation.span = {/*message_index=*/0,
612*993b0882SAndroid Build Coastguard Worker /*span=*/{0, 5},
613*993b0882SAndroid Build Coastguard Worker /*text=*/"hello"};
614*993b0882SAndroid Build Coastguard Worker greeting_annotation.name = "greeting";
615*993b0882SAndroid Build Coastguard Worker ActionSuggestion suggestion = {/*response_text=""*/ "",
616*993b0882SAndroid Build Coastguard Worker /*type=*/"iteration_test",
617*993b0882SAndroid Build Coastguard Worker /*score=*/1.0,
618*993b0882SAndroid Build Coastguard Worker /*priority_score=*/0.0,
619*993b0882SAndroid Build Coastguard Worker /*annotations=*/
620*993b0882SAndroid Build Coastguard Worker {location_annotation, greeting_annotation}};
621*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
622*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
623*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
624*993b0882SAndroid Build Coastguard Worker suggestion, conversation, GetAndroidContext(),
625*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
626*993b0882SAndroid Build Coastguard Worker /*actions_entity_data_schema=*/nullptr, &intents));
627*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
628*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["length"].Value<int>(), 2);
629*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["location"].ConstRefValue<std::string>(), "there");
630*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["greeting"].ConstRefValue<std::string>(), "hello");
631*993b0882SAndroid Build Coastguard Worker }
632*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,HandlesEntityDataLookups)633*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, HandlesEntityDataLookups) {
634*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
635*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("fake", R"lua(
636*993b0882SAndroid Build Coastguard Worker local person = external.entity.person
637*993b0882SAndroid Build Coastguard Worker return {
638*993b0882SAndroid Build Coastguard Worker {
639*993b0882SAndroid Build Coastguard Worker title_without_entity = "Add to contacts",
640*993b0882SAndroid Build Coastguard Worker extra = {
641*993b0882SAndroid Build Coastguard Worker {name = "name", string_value = string.lower(person.name)},
642*993b0882SAndroid Build Coastguard Worker {name = "encoded_phone", string_value = external.android.urlencode(person.phone)},
643*993b0882SAndroid Build Coastguard Worker {name = "age", int_value = person.age_years},
644*993b0882SAndroid Build Coastguard Worker }
645*993b0882SAndroid Build Coastguard Worker }
646*993b0882SAndroid Build Coastguard Worker })lua");
647*993b0882SAndroid Build Coastguard Worker
648*993b0882SAndroid Build Coastguard Worker // Create fake entity data schema meta data.
649*993b0882SAndroid Build Coastguard Worker // Cannot use object oriented API here as that is not available for the
650*993b0882SAndroid Build Coastguard Worker // reflection schema.
651*993b0882SAndroid Build Coastguard Worker flatbuffers::FlatBufferBuilder schema_builder;
652*993b0882SAndroid Build Coastguard Worker std::vector<flatbuffers::Offset<reflection::Field>> person_fields = {
653*993b0882SAndroid Build Coastguard Worker reflection::CreateField(
654*993b0882SAndroid Build Coastguard Worker schema_builder,
655*993b0882SAndroid Build Coastguard Worker /*name=*/schema_builder.CreateString("name"),
656*993b0882SAndroid Build Coastguard Worker /*type=*/
657*993b0882SAndroid Build Coastguard Worker reflection::CreateType(schema_builder,
658*993b0882SAndroid Build Coastguard Worker /*base_type=*/reflection::String),
659*993b0882SAndroid Build Coastguard Worker /*id=*/0,
660*993b0882SAndroid Build Coastguard Worker /*offset=*/4),
661*993b0882SAndroid Build Coastguard Worker reflection::CreateField(
662*993b0882SAndroid Build Coastguard Worker schema_builder,
663*993b0882SAndroid Build Coastguard Worker /*name=*/schema_builder.CreateString("phone"),
664*993b0882SAndroid Build Coastguard Worker /*type=*/
665*993b0882SAndroid Build Coastguard Worker reflection::CreateType(schema_builder,
666*993b0882SAndroid Build Coastguard Worker /*base_type=*/reflection::String),
667*993b0882SAndroid Build Coastguard Worker /*id=*/1,
668*993b0882SAndroid Build Coastguard Worker /*offset=*/6),
669*993b0882SAndroid Build Coastguard Worker reflection::CreateField(
670*993b0882SAndroid Build Coastguard Worker schema_builder,
671*993b0882SAndroid Build Coastguard Worker /*name=*/schema_builder.CreateString("age_years"),
672*993b0882SAndroid Build Coastguard Worker /*type=*/
673*993b0882SAndroid Build Coastguard Worker reflection::CreateType(schema_builder,
674*993b0882SAndroid Build Coastguard Worker /*base_type=*/reflection::Int),
675*993b0882SAndroid Build Coastguard Worker /*id=*/2,
676*993b0882SAndroid Build Coastguard Worker /*offset=*/8),
677*993b0882SAndroid Build Coastguard Worker };
678*993b0882SAndroid Build Coastguard Worker std::vector<flatbuffers::Offset<reflection::Field>> entity_data_fields = {
679*993b0882SAndroid Build Coastguard Worker reflection::CreateField(
680*993b0882SAndroid Build Coastguard Worker schema_builder,
681*993b0882SAndroid Build Coastguard Worker /*name=*/schema_builder.CreateString("person"),
682*993b0882SAndroid Build Coastguard Worker /*type=*/
683*993b0882SAndroid Build Coastguard Worker reflection::CreateType(schema_builder,
684*993b0882SAndroid Build Coastguard Worker /*base_type=*/reflection::Obj,
685*993b0882SAndroid Build Coastguard Worker /*element=*/reflection::None,
686*993b0882SAndroid Build Coastguard Worker /*index=*/1),
687*993b0882SAndroid Build Coastguard Worker /*id=*/0,
688*993b0882SAndroid Build Coastguard Worker /*offset=*/4)};
689*993b0882SAndroid Build Coastguard Worker std::vector<flatbuffers::Offset<reflection::Enum>> enums;
690*993b0882SAndroid Build Coastguard Worker std::vector<flatbuffers::Offset<reflection::Object>> objects = {
691*993b0882SAndroid Build Coastguard Worker reflection::CreateObject(
692*993b0882SAndroid Build Coastguard Worker schema_builder,
693*993b0882SAndroid Build Coastguard Worker /*name=*/schema_builder.CreateString("EntityData"),
694*993b0882SAndroid Build Coastguard Worker /*fields=*/
695*993b0882SAndroid Build Coastguard Worker schema_builder.CreateVectorOfSortedTables(&entity_data_fields)),
696*993b0882SAndroid Build Coastguard Worker reflection::CreateObject(
697*993b0882SAndroid Build Coastguard Worker schema_builder,
698*993b0882SAndroid Build Coastguard Worker /*name=*/schema_builder.CreateString("person"),
699*993b0882SAndroid Build Coastguard Worker /*fields=*/
700*993b0882SAndroid Build Coastguard Worker schema_builder.CreateVectorOfSortedTables(&person_fields))};
701*993b0882SAndroid Build Coastguard Worker schema_builder.Finish(reflection::CreateSchema(
702*993b0882SAndroid Build Coastguard Worker schema_builder, schema_builder.CreateVectorOfSortedTables(&objects),
703*993b0882SAndroid Build Coastguard Worker schema_builder.CreateVectorOfSortedTables(&enums),
704*993b0882SAndroid Build Coastguard Worker /*(unused) file_ident=*/0,
705*993b0882SAndroid Build Coastguard Worker /*(unused) file_ext=*/0,
706*993b0882SAndroid Build Coastguard Worker /*root_table*/ objects[0]));
707*993b0882SAndroid Build Coastguard Worker const reflection::Schema* entity_data_schema =
708*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<reflection::Schema>(
709*993b0882SAndroid Build Coastguard Worker schema_builder.GetBufferPointer());
710*993b0882SAndroid Build Coastguard Worker
711*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
712*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
713*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
714*993b0882SAndroid Build Coastguard Worker
715*993b0882SAndroid Build Coastguard Worker ClassificationResult classification = {"fake", 1.0};
716*993b0882SAndroid Build Coastguard Worker
717*993b0882SAndroid Build Coastguard Worker // Build test entity data.
718*993b0882SAndroid Build Coastguard Worker MutableFlatbufferBuilder entity_data_builder(entity_data_schema);
719*993b0882SAndroid Build Coastguard Worker std::unique_ptr<MutableFlatbuffer> entity_data_buffer =
720*993b0882SAndroid Build Coastguard Worker entity_data_builder.NewRoot();
721*993b0882SAndroid Build Coastguard Worker MutableFlatbuffer* person = entity_data_buffer->Mutable("person");
722*993b0882SAndroid Build Coastguard Worker person->Set("name", "Kenobi");
723*993b0882SAndroid Build Coastguard Worker person->Set("phone", "1 800 HIGHGROUND");
724*993b0882SAndroid Build Coastguard Worker person->Set("age_years", 38);
725*993b0882SAndroid Build Coastguard Worker classification.serialized_entity_data = entity_data_buffer->Serialize();
726*993b0882SAndroid Build Coastguard Worker
727*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
728*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
729*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
730*993b0882SAndroid Build Coastguard Worker classification,
731*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "highground", {0, 10}, GetAndroidContext(),
732*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/entity_data_schema,
733*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
734*993b0882SAndroid Build Coastguard Worker &intents));
735*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
736*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents[0].extra, SizeIs(3));
737*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["name"].ConstRefValue<std::string>(), "kenobi");
738*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["encoded_phone"].ConstRefValue<std::string>(),
739*993b0882SAndroid Build Coastguard Worker "1%20800%20HIGHGROUND");
740*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(intents[0].extra["age"].Value<int>(), 38);
741*993b0882SAndroid Build Coastguard Worker }
742*993b0882SAndroid Build Coastguard Worker
TEST_F(IntentGeneratorTest,ReadExtras)743*993b0882SAndroid Build Coastguard Worker TEST_F(IntentGeneratorTest, ReadExtras) {
744*993b0882SAndroid Build Coastguard Worker flatbuffers::DetachedBuffer intent_factory_model =
745*993b0882SAndroid Build Coastguard Worker BuildTestIntentFactoryModel("test", R"lua(
746*993b0882SAndroid Build Coastguard Worker return {
747*993b0882SAndroid Build Coastguard Worker {
748*993b0882SAndroid Build Coastguard Worker extra = {
749*993b0882SAndroid Build Coastguard Worker { name = "languages", string_array_value = {"en", "zh"}},
750*993b0882SAndroid Build Coastguard Worker { name = "scores", float_array_value = {0.6, 0.4}},
751*993b0882SAndroid Build Coastguard Worker { name = "ints", int_array_value = {7, 2, 1}},
752*993b0882SAndroid Build Coastguard Worker { name = "bundle",
753*993b0882SAndroid Build Coastguard Worker named_variant_array_value =
754*993b0882SAndroid Build Coastguard Worker {
755*993b0882SAndroid Build Coastguard Worker { name = "inner_string", string_value = "a" },
756*993b0882SAndroid Build Coastguard Worker { name = "inner_int", int_value = 42 }
757*993b0882SAndroid Build Coastguard Worker }
758*993b0882SAndroid Build Coastguard Worker }
759*993b0882SAndroid Build Coastguard Worker }
760*993b0882SAndroid Build Coastguard Worker }}
761*993b0882SAndroid Build Coastguard Worker )lua");
762*993b0882SAndroid Build Coastguard Worker std::unique_ptr<IntentGenerator> generator = IntentGenerator::Create(
763*993b0882SAndroid Build Coastguard Worker flatbuffers::GetRoot<IntentFactoryModel>(intent_factory_model.data()),
764*993b0882SAndroid Build Coastguard Worker /*resources=*/resources_, jni_cache_);
765*993b0882SAndroid Build Coastguard Worker const ClassificationResult classification = {"test", 1.0};
766*993b0882SAndroid Build Coastguard Worker std::vector<RemoteActionTemplate> intents;
767*993b0882SAndroid Build Coastguard Worker
768*993b0882SAndroid Build Coastguard Worker EXPECT_TRUE(generator->GenerateIntents(
769*993b0882SAndroid Build Coastguard Worker JniHelper::NewStringUTF(GetJenv(), "en-US").ValueOrDie().get(),
770*993b0882SAndroid Build Coastguard Worker classification,
771*993b0882SAndroid Build Coastguard Worker /*reference_time_ms_utc=*/0, "test", {0, 4}, GetAndroidContext(),
772*993b0882SAndroid Build Coastguard Worker /*annotations_entity_data_schema=*/nullptr,
773*993b0882SAndroid Build Coastguard Worker /*enable_add_contact_intent=*/false, /*enable_search_intent=*/false,
774*993b0882SAndroid Build Coastguard Worker &intents));
775*993b0882SAndroid Build Coastguard Worker
776*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intents, SizeIs(1));
777*993b0882SAndroid Build Coastguard Worker RemoteActionTemplate intent = intents[0];
778*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intent.extra, SizeIs(4));
779*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(
780*993b0882SAndroid Build Coastguard Worker intent.extra["languages"].ConstRefValue<std::vector<std::string>>(),
781*993b0882SAndroid Build Coastguard Worker ElementsAre("en", "zh"));
782*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intent.extra["scores"].ConstRefValue<std::vector<float>>(),
783*993b0882SAndroid Build Coastguard Worker ElementsAre(0.6, 0.4));
784*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(intent.extra["ints"].ConstRefValue<std::vector<int>>(),
785*993b0882SAndroid Build Coastguard Worker ElementsAre(7, 2, 1));
786*993b0882SAndroid Build Coastguard Worker const std::map<std::string, Variant>& map =
787*993b0882SAndroid Build Coastguard Worker intent.extra["bundle"].ConstRefValue<std::map<std::string, Variant>>();
788*993b0882SAndroid Build Coastguard Worker EXPECT_THAT(map, SizeIs(2));
789*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(map.at("inner_string").ConstRefValue<std::string>(), "a");
790*993b0882SAndroid Build Coastguard Worker EXPECT_EQ(map.at("inner_int").Value<int>(), 42);
791*993b0882SAndroid Build Coastguard Worker }
792*993b0882SAndroid Build Coastguard Worker
793*993b0882SAndroid Build Coastguard Worker } // namespace
794*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3
795