1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.appsearch.app;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import org.junit.Test;
22 
23 import java.util.List;
24 import java.util.Map;
25 
26 public class SearchResultInternalTest {
27     @Test
testSearchResultBuilderCopyConstructor()28     public void testSearchResultBuilderCopyConstructor() {
29         GenericDocument document =
30                 new GenericDocument.Builder<>("namespace", "id", "schemaType").build();
31         SearchResult searchResult = new SearchResult.Builder("package", "database")
32                 .setGenericDocument(document)
33                 .setRankingSignal(1.23)
34                 .addJoinedResult(new SearchResult.Builder("pkg1", "db1").setGenericDocument(
35                         document).build())
36                 .addJoinedResult(new SearchResult.Builder("pkg2", "db2").setGenericDocument(
37                         document).build())
38                 .addMatchInfo(new SearchResult.MatchInfo.Builder("propertyPath1").build())
39                 .addMatchInfo(new SearchResult.MatchInfo.Builder("propertyPath2").build())
40                 .addMatchInfo(new SearchResult.MatchInfo.Builder("propertyPath3").build())
41                 .build();
42         SearchResult searchResultCopy = new SearchResult.Builder(searchResult).build();
43         assertThat(searchResultCopy.getGenericDocument()).isEqualTo(
44                 searchResult.getGenericDocument());
45         assertThat(searchResultCopy.getRankingSignal()).isEqualTo(searchResult.getRankingSignal());
46         // Specifically test JoinedResults and MatchInfos with different sizes since briefly had
47         // a bug where we looped through joinedResults using matchInfos.size()
48         assertThat(searchResultCopy.getJoinedResults().size()).isEqualTo(
49                 searchResult.getJoinedResults().size());
50         assertThat(searchResultCopy.getJoinedResults().get(0).getPackageName()).isEqualTo("pkg1");
51         assertThat(searchResultCopy.getJoinedResults().get(0).getDatabaseName()).isEqualTo("db1");
52         assertThat(searchResultCopy.getJoinedResults().get(1).getPackageName()).isEqualTo("pkg2");
53         assertThat(searchResultCopy.getJoinedResults().get(1).getDatabaseName()).isEqualTo("db2");
54         assertThat(searchResultCopy.getMatchInfos().size()).isEqualTo(
55                 searchResult.getMatchInfos().size());
56         assertThat(searchResultCopy.getMatchInfos().get(0).getPropertyPath()).isEqualTo(
57                 "propertyPath1");
58         assertThat(searchResultCopy.getMatchInfos().get(1).getPropertyPath()).isEqualTo(
59                 "propertyPath2");
60         assertThat(searchResultCopy.getMatchInfos().get(2).getPropertyPath()).isEqualTo(
61                 "propertyPath3");
62     }
63 
64     @Test
testSearchResultBuilderCopyConstructor_informationalRankingSignal()65     public void testSearchResultBuilderCopyConstructor_informationalRankingSignal() {
66         GenericDocument document =
67                 new GenericDocument.Builder<>("namespace", "id", "schemaType").build();
68         SearchResult searchResult = new SearchResult.Builder("package", "database")
69                 .setGenericDocument(document)
70                 .setRankingSignal(1.23)
71                 .addInformationalRankingSignal(2)
72                 .addInformationalRankingSignal(3)
73                 .build();
74         SearchResult searchResultCopy = new SearchResult.Builder(searchResult).build();
75         assertThat(searchResultCopy.getRankingSignal()).isEqualTo(searchResult.getRankingSignal());
76         assertThat(searchResultCopy.getInformationalRankingSignals()).isEqualTo(
77                 searchResult.getInformationalRankingSignals());
78     }
79 
80     @Test
testSearchResultBuilderCopyConstructor_parentType()81     public void testSearchResultBuilderCopyConstructor_parentType() {
82         GenericDocument document =
83                 new GenericDocument.Builder<>("namespace", "id", "schemaType1").build();
84         SearchResult searchResult = new SearchResult.Builder("package", "database")
85                 .setGenericDocument(document)
86                 .setParentTypeMap(Map.of(
87                         "schemaType1", List.of("parent1", "parent2"),
88                         "schemaType2", List.of("parent3", "parent4")
89                 ))
90                 .build();
91         SearchResult searchResultCopy = new SearchResult.Builder(searchResult).build();
92         assertThat(searchResultCopy.getParentTypeMap()).containsExactlyEntriesIn(
93                 searchResult.getParentTypeMap());
94     }
95 
96     @Test
testSearchResultBuilder_clearJoinedResults()97     public void testSearchResultBuilder_clearJoinedResults() {
98         GenericDocument document =
99                 new GenericDocument.Builder<>("namespace", "id", "schemaType").build();
100         SearchResult searchResult = new SearchResult.Builder("package", "database")
101                 .setGenericDocument(document)
102                 .addJoinedResult(new SearchResult.Builder("pkg", "db").setGenericDocument(
103                         document).build())
104                 .clearJoinedResults()
105                 .build();
106         assertThat(searchResult.getJoinedResults()).isEmpty();
107     }
108 
109     @Test
testMatchInfoBuilderCopyConstructor()110     public void testMatchInfoBuilderCopyConstructor() {
111         SearchResult.MatchRange exactMatchRange = new SearchResult.MatchRange(3, 8);
112         SearchResult.MatchRange submatchRange = new SearchResult.MatchRange(3, 5);
113         SearchResult.MatchRange snippetMatchRange = new SearchResult.MatchRange(1, 10);
114         SearchResult.MatchInfo matchInfo =
115                 new SearchResult.MatchInfo.Builder("propertyPath1")
116                         .setExactMatchRange(exactMatchRange)
117                         .setSubmatchRange(submatchRange)
118                         .setSnippetRange(snippetMatchRange).build();
119         SearchResult.MatchInfo matchInfoCopy =
120                 new SearchResult.MatchInfo.Builder(matchInfo).build();
121         assertThat(matchInfoCopy.getPropertyPath()).isEqualTo("propertyPath1");
122         assertThat(matchInfoCopy.getExactMatchRange()).isEqualTo(exactMatchRange);
123         assertThat(matchInfoCopy.getSubmatchRange()).isEqualTo(submatchRange);
124         assertThat(matchInfoCopy.getSnippetRange()).isEqualTo(snippetMatchRange);
125     }
126 
127     @Test
testMatchInfoBuilderCopyConstructor_embeddingMatchInfoEnabled()128     public void testMatchInfoBuilderCopyConstructor_embeddingMatchInfoEnabled() {
129         SearchResult.MatchRange exactMatchRange = new SearchResult.MatchRange(3, 8);
130         SearchResult.MatchRange submatchRange = new SearchResult.MatchRange(3, 5);
131         SearchResult.MatchRange snippetMatchRange = new SearchResult.MatchRange(1, 10);
132 
133         double semanticScore = 1.1d;
134         int queryEmbeddingVectorIndex = 1;
135         int embeddingSearchMetricType = SearchSpec.EMBEDDING_SEARCH_METRIC_TYPE_COSINE;
136         SearchResult.EmbeddingMatchInfo embeddingMatchInfo =
137                 new SearchResult.EmbeddingMatchInfo(semanticScore, queryEmbeddingVectorIndex,
138                         embeddingSearchMetricType);
139 
140         SearchResult.MatchInfo matchInfo1 =
141                 new SearchResult.MatchInfo.Builder("propertyPath1")
142                         .setExactMatchRange(exactMatchRange)
143                         .setSubmatchRange(submatchRange)
144                         .setSnippetRange(snippetMatchRange)
145                         .build();
146 
147         SearchResult.MatchInfo matchInfo2 =
148                 new SearchResult.MatchInfo.Builder("propertyPath2")
149                         .setEmbeddingMatch(embeddingMatchInfo)
150                         .build();
151 
152         SearchResult.MatchInfo matchInfoCopy1 =
153                 new SearchResult.MatchInfo.Builder(matchInfo1).build();
154         assertThat(matchInfoCopy1.getPropertyPath()).isEqualTo("propertyPath1");
155         assertThat(matchInfoCopy1.getTextMatch()).isNotNull();
156         assertThat(matchInfoCopy1.getTextMatch().getExactMatchRange()).isEqualTo(exactMatchRange);
157         assertThat(matchInfoCopy1.getTextMatch().getSubmatchRange()).isEqualTo(submatchRange);
158         assertThat(matchInfoCopy1.getTextMatch().getSnippetRange()).isEqualTo(snippetMatchRange);
159         assertThat(matchInfoCopy1.getEmbeddingMatch()).isNull();
160 
161         SearchResult.MatchInfo matchInfoCopy2 =
162                 new SearchResult.MatchInfo.Builder(matchInfo2).build();
163         assertThat(matchInfoCopy2.getPropertyPath()).isEqualTo("propertyPath2");
164         assertThat(matchInfoCopy2.getEmbeddingMatch()).isNotNull();
165         assertThat(matchInfoCopy2.getEmbeddingMatch().getSemanticScore()).isEqualTo(semanticScore);
166         assertThat(matchInfoCopy2.getEmbeddingMatch().getQueryEmbeddingVectorIndex()).isEqualTo(
167                 queryEmbeddingVectorIndex);
168         assertThat(matchInfoCopy2.getEmbeddingMatch().getEmbeddingSearchMetricType()).isEqualTo(
169                 embeddingSearchMetricType);
170         assertThat(matchInfoCopy2.getTextMatch()).isNull();
171     }
172 }
173