blob: 3592c9605f59f7d31f6a5fbaa3258a3ef01021e8 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view.textclassifier.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.os.Bundle;
import android.os.LocaleList;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.URLSpan;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TextLinksTest {
private static final float EPSILON = 0.000001f;
private static final String BUNDLE_KEY = "key";
private static final String BUNDLE_VALUE = "value";
private static final Bundle BUNDLE = new Bundle();
static {
BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
}
private static final double ACCEPTED_DELTA = 0.0000001;
private static final String TEXT = "abcdefghijklmnopqrstuvwxyz";
private static final int START = 5;
private static final int END = 20;
private static final int ANOTHER_START = 22;
private static final int ANOTHER_END = 24;
private static final LocaleList LOCALES = LocaleList.forLanguageTags("fr,en,de,es");
@Test
public void testTextLinks_defaultValues() {
final TextLinks textLinks = new TextLinks.Builder(TEXT).build();
assertEquals(TEXT, textLinks.getText());
assertTrue(textLinks.getExtras().isEmpty());
assertTrue(textLinks.getLinks().isEmpty());
}
@Test
public void testTextLinks_full() {
final TextLinks textLinks = new TextLinks.Builder(TEXT)
.setExtras(BUNDLE)
.addLink(START, END, Collections.singletonMap(TextClassifier.TYPE_ADDRESS, 1.0f))
.addLink(START, END, Collections.singletonMap(TextClassifier.TYPE_PHONE, 1.0f),
BUNDLE)
.build();
assertEquals(TEXT, textLinks.getText());
assertEquals(BUNDLE_VALUE, textLinks.getExtras().getString(BUNDLE_KEY));
assertEquals(2, textLinks.getLinks().size());
final List<TextLinks.TextLink> resultList = new ArrayList<>(textLinks.getLinks());
final TextLinks.TextLink textLinkNoExtra = resultList.get(0);
assertEquals(TextClassifier.TYPE_ADDRESS, textLinkNoExtra.getEntity(0));
assertEquals(1.0f, textLinkNoExtra.getConfidenceScore(TextClassifier.TYPE_ADDRESS),
EPSILON);
assertEquals(Bundle.EMPTY, textLinkNoExtra.getExtras());
final TextLinks.TextLink textLinkHasExtra = resultList.get(1);
assertEquals(TextClassifier.TYPE_PHONE, textLinkHasExtra.getEntity(0));
assertEquals(1.0f, textLinkHasExtra.getConfidenceScore(TextClassifier.TYPE_PHONE),
EPSILON);
assertEquals(BUNDLE_VALUE, textLinkHasExtra.getExtras().getString(BUNDLE_KEY));
}
@Test
public void testTextLinks_clearTextLinks() {
final TextLinks textLinks = new TextLinks.Builder(TEXT)
.setExtras(BUNDLE)
.addLink(START, END, Collections.singletonMap(TextClassifier.TYPE_ADDRESS, 1.0f))
.clearTextLinks()
.build();
assertEquals(0, textLinks.getLinks().size());
}
@Test
public void testTextLinks_apply() {
final SpannableString spannableString = SpannableString.valueOf(TEXT);
final TextLinks textLinks = new TextLinks.Builder(TEXT)
.addLink(START, END, Collections.singletonMap(TextClassifier.TYPE_ADDRESS, 1.0f))
.addLink(ANOTHER_START, ANOTHER_END,
ImmutableMap.of(TextClassifier.TYPE_PHONE, 1.0f,
TextClassifier.TYPE_ADDRESS, 0.5f))
.build();
final int status = textLinks.apply(
spannableString, TextLinks.APPLY_STRATEGY_IGNORE, null);
final TextLinks.TextLinkSpan[] textLinkSpans = spannableString.getSpans(0,
spannableString.length() - 1,
TextLinks.TextLinkSpan.class);
assertEquals(TextLinks.STATUS_LINKS_APPLIED, status);
assertEquals(2, textLinkSpans.length);
final TextLinks.TextLink textLink = textLinkSpans[0].getTextLink();
final TextLinks.TextLink anotherTextLink = textLinkSpans[1].getTextLink();
assertEquals(START, textLink.getStart());
assertEquals(END, textLink.getEnd());
assertEquals(1, textLink.getEntityCount());
assertEquals(TextClassifier.TYPE_ADDRESS, textLink.getEntity(0));
assertEquals(1.0f, textLink.getConfidenceScore(TextClassifier.TYPE_ADDRESS),
ACCEPTED_DELTA);
assertEquals(ANOTHER_START, anotherTextLink.getStart());
assertEquals(ANOTHER_END, anotherTextLink.getEnd());
assertEquals(2, anotherTextLink.getEntityCount());
assertEquals(TextClassifier.TYPE_PHONE, anotherTextLink.getEntity(0));
assertEquals(1.0f, anotherTextLink.getConfidenceScore(TextClassifier.TYPE_PHONE),
ACCEPTED_DELTA);
assertEquals(TextClassifier.TYPE_ADDRESS, anotherTextLink.getEntity(1));
assertEquals(0.5f, anotherTextLink.getConfidenceScore(TextClassifier.TYPE_ADDRESS),
ACCEPTED_DELTA);
}
@Test
public void testTextLinks_applyStrategyReplace() {
final SpannableString spannableString = SpannableString.valueOf(TEXT);
final URLSpan urlSpan = new URLSpan("http://www.google.com");
spannableString.setSpan(urlSpan, START, END, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
final TextLinks textLinks = new TextLinks.Builder(TEXT)
.addLink(START, END, Collections.singletonMap(TextClassifier.TYPE_ADDRESS, 1.0f))
.build();
final int status = textLinks.apply(
spannableString, TextLinks.APPLY_STRATEGY_REPLACE, null);
final TextLinks.TextLinkSpan[] textLinkSpans = spannableString.getSpans(0,
spannableString.length() - 1,
TextLinks.TextLinkSpan.class);
final URLSpan[] urlSpans = spannableString.getSpans(0, spannableString.length() - 1,
URLSpan.class);
assertEquals(TextLinks.STATUS_LINKS_APPLIED, status);
assertEquals(1, textLinkSpans.length);
assertEquals(0, urlSpans.length);
}
@Test
public void testTextLinks_applyStrategyIgnore() {
final SpannableString spannableString = SpannableString.valueOf(TEXT);
final URLSpan urlSpan = new URLSpan("http://www.google.com");
spannableString.setSpan(urlSpan, START, END, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
final TextLinks textLinks = new TextLinks.Builder(TEXT)
.addLink(START, END, Collections.singletonMap(TextClassifier.TYPE_ADDRESS, 1.0f))
.build();
final int status = textLinks.apply(
spannableString, TextLinks.APPLY_STRATEGY_IGNORE, null);
final TextLinks.TextLinkSpan[] textLinkSpans = spannableString.getSpans(0,
spannableString.length() - 1,
TextLinks.TextLinkSpan.class);
final URLSpan[] urlSpans = spannableString.getSpans(0, spannableString.length() - 1,
URLSpan.class);
assertEquals(TextLinks.STATUS_NO_LINKS_APPLIED, status);
assertEquals(0, textLinkSpans.length);
assertEquals(1, urlSpans.length);
}
@Test
public void testTextLinks_applyWithCustomSpanFactory() {
final class CustomTextLinkSpan extends TextLinks.TextLinkSpan {
private CustomTextLinkSpan(TextLinks.TextLink textLink) {
super(textLink);
}
}
final SpannableString spannableString = SpannableString.valueOf(TEXT);
final TextLinks textLinks = new TextLinks.Builder(TEXT)
.addLink(START, END, Collections.singletonMap(TextClassifier.TYPE_ADDRESS, 1.0f))
.build();
final int status = textLinks.apply(
spannableString, TextLinks.APPLY_STRATEGY_IGNORE, CustomTextLinkSpan::new);
final CustomTextLinkSpan[] customTextLinkSpans = spannableString.getSpans(0,
spannableString.length() - 1,
CustomTextLinkSpan.class);
assertEquals(TextLinks.STATUS_LINKS_APPLIED, status);
assertEquals(1, customTextLinkSpans.length);
final TextLinks.TextLink textLink = customTextLinkSpans[0].getTextLink();
assertEquals(START, textLink.getStart());
assertEquals(END, textLink.getEnd());
assertEquals(1, textLink.getEntityCount());
assertEquals(TextClassifier.TYPE_ADDRESS, textLink.getEntity(0));
assertEquals(1.0f, textLink.getConfidenceScore(TextClassifier.TYPE_ADDRESS),
ACCEPTED_DELTA);
}
@Test
public void testTextLinksRequest_defaultValues() {
final TextLinks.Request request = new TextLinks.Request.Builder(TEXT).build();
assertEquals(TEXT, request.getText());
assertNull(request.getDefaultLocales());
assertTrue(request.getExtras().isEmpty());
assertNull(request.getEntityConfig());
assertNull(request.getCallingPackageName());
}
@Test
public void testTextLinksRequest_full() {
final ZonedDateTime referenceTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(1000L),
ZoneId.of("UTC"));
final TextLinks.Request request = new TextLinks.Request.Builder(TEXT)
.setDefaultLocales(LOCALES)
.setExtras(BUNDLE)
.setEntityConfig(TextClassifier.EntityConfig.createWithHints(
Collections.singletonList(TextClassifier.HINT_TEXT_IS_EDITABLE)))
.setReferenceTime(referenceTime)
.build();
assertEquals(TEXT, request.getText());
assertEquals(LOCALES, request.getDefaultLocales());
assertEquals(BUNDLE_VALUE, request.getExtras().getString(BUNDLE_KEY));
assertEquals(1, request.getEntityConfig().getHints().size());
assertEquals(
TextClassifier.HINT_TEXT_IS_EDITABLE,
request.getEntityConfig().getHints().iterator().next());
assertEquals(referenceTime, request.getReferenceTime());
assertNull(request.getCallingPackageName());
}
}