176f614720db6a282c3e890969a600585122cdcc5Marc Blank/*
276f614720db6a282c3e890969a600585122cdcc5Marc Blank * Copyright (C) 2010 The Android Open Source Project
376f614720db6a282c3e890969a600585122cdcc5Marc Blank *
476f614720db6a282c3e890969a600585122cdcc5Marc Blank * Licensed under the Apache License, Version 2.0 (the "License");
576f614720db6a282c3e890969a600585122cdcc5Marc Blank * you may not use this file except in compliance with the License.
676f614720db6a282c3e890969a600585122cdcc5Marc Blank * You may obtain a copy of the License at
776f614720db6a282c3e890969a600585122cdcc5Marc Blank *
876f614720db6a282c3e890969a600585122cdcc5Marc Blank *      http://www.apache.org/licenses/LICENSE-2.0
976f614720db6a282c3e890969a600585122cdcc5Marc Blank *
1076f614720db6a282c3e890969a600585122cdcc5Marc Blank * Unless required by applicable law or agreed to in writing, software
1176f614720db6a282c3e890969a600585122cdcc5Marc Blank * distributed under the License is distributed on an "AS IS" BASIS,
1276f614720db6a282c3e890969a600585122cdcc5Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1376f614720db6a282c3e890969a600585122cdcc5Marc Blank * See the License for the specific language governing permissions and
1476f614720db6a282c3e890969a600585122cdcc5Marc Blank * limitations under the License.
1576f614720db6a282c3e890969a600585122cdcc5Marc Blank */
1676f614720db6a282c3e890969a600585122cdcc5Marc Blank
1776f614720db6a282c3e890969a600585122cdcc5Marc Blank/**
1876f614720db6a282c3e890969a600585122cdcc5Marc Blank * This is a series of unit tests for snippet creation and highlighting
1976f614720db6a282c3e890969a600585122cdcc5Marc Blank *
2076f614720db6a282c3e890969a600585122cdcc5Marc Blank * You can run this entire test case with:
2176f614720db6a282c3e890969a600585122cdcc5Marc Blank *   runtest -c com.android.emailcommon.utility.TextUtilitiesTests email
2276f614720db6a282c3e890969a600585122cdcc5Marc Blank */
2376f614720db6a282c3e890969a600585122cdcc5Marc Blankpackage com.android.emailcommon.utility;
2476f614720db6a282c3e890969a600585122cdcc5Marc Blank
2576f614720db6a282c3e890969a600585122cdcc5Marc Blankimport android.test.AndroidTestCase;
263555dc03bf2243dc275c9c832702abbee3b64387Jerry Xieimport android.test.suitebuilder.annotation.SmallTest;
273555dc03bf2243dc275c9c832702abbee3b64387Jerry Xie
2876f614720db6a282c3e890969a600585122cdcc5Marc Blankimport android.text.SpannableStringBuilder;
2976f614720db6a282c3e890969a600585122cdcc5Marc Blankimport android.text.style.BackgroundColorSpan;
3076f614720db6a282c3e890969a600585122cdcc5Marc Blank
313555dc03bf2243dc275c9c832702abbee3b64387Jerry Xie@SmallTest
3276f614720db6a282c3e890969a600585122cdcc5Marc Blankpublic class TextUtilitiesTests extends AndroidTestCase {
3376f614720db6a282c3e890969a600585122cdcc5Marc Blank
3476f614720db6a282c3e890969a600585122cdcc5Marc Blank    public void testPlainSnippet() {
3576f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test the simplest cases
3676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("", TextUtilities.makeSnippetFromPlainText(null));
3776f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("", TextUtilities.makeSnippetFromPlainText(""));
3876f614720db6a282c3e890969a600585122cdcc5Marc Blank
3976f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test handling leading, trailing, and duplicated whitespace
4076f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Just test common whitespace characters; we calls Character.isWhitespace() internally, so
4176f614720db6a282c3e890969a600585122cdcc5Marc Blank        // other whitespace should be fine as well
4276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("", TextUtilities.makeSnippetFromPlainText(" \n\r\t\r\t\n"));
4376f614720db6a282c3e890969a600585122cdcc5Marc Blank        char c = TextUtilities.NON_BREAKING_SPACE_CHARACTER;
4476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("foo", TextUtilities.makeSnippetFromPlainText(c + "\r\n\tfoo \n\t\r" + c));
4576f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("foo bar",
4676f614720db6a282c3e890969a600585122cdcc5Marc Blank                TextUtilities.makeSnippetFromPlainText(c + "\r\n\tfoo \r\n bar\n\t\r" + c));
4776f614720db6a282c3e890969a600585122cdcc5Marc Blank
4876f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Handle duplicated - and =
4976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("Foo-Bar=Bletch",
5076f614720db6a282c3e890969a600585122cdcc5Marc Blank                TextUtilities.makeSnippetFromPlainText("Foo-----Bar=======Bletch"));
5176f614720db6a282c3e890969a600585122cdcc5Marc Blank
5276f614720db6a282c3e890969a600585122cdcc5Marc Blank        // We shouldn't muck with HTML entities
5376f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(" >", TextUtilities.makeSnippetFromPlainText(" >"));
5476f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
5576f614720db6a282c3e890969a600585122cdcc5Marc Blank
5676f614720db6a282c3e890969a600585122cdcc5Marc Blank    public void testHtmlSnippet() {
5776f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test the simplest cases
5876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("", TextUtilities.makeSnippetFromHtmlText(null));
5976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("", TextUtilities.makeSnippetFromHtmlText(""));
6076f614720db6a282c3e890969a600585122cdcc5Marc Blank
6176f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test handling leading, trailing, and duplicated whitespace
6276f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Just test common whitespace characters; we calls Character.isWhitespace() internally, so
6376f614720db6a282c3e890969a600585122cdcc5Marc Blank        // other whitespace should be fine as well
6476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("", TextUtilities.makeSnippetFromHtmlText(" \n\r\t\r\t\n"));
6576f614720db6a282c3e890969a600585122cdcc5Marc Blank        char c = TextUtilities.NON_BREAKING_SPACE_CHARACTER;
6676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("foo", TextUtilities.makeSnippetFromHtmlText(c + "\r\n\tfoo \n\t\r" + c));
6776f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("foo bar",
6876f614720db6a282c3e890969a600585122cdcc5Marc Blank                TextUtilities.makeSnippetFromHtmlText(c + "\r\n\tfoo \r\n bar\n\t\r" + c));
6976f614720db6a282c3e890969a600585122cdcc5Marc Blank
7076f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Handle duplicated - and =
7176f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("Foo-Bar=Bletch",
7276f614720db6a282c3e890969a600585122cdcc5Marc Blank                TextUtilities.makeSnippetFromPlainText("Foo-----Bar=======Bletch"));
7376f614720db6a282c3e890969a600585122cdcc5Marc Blank
7476f614720db6a282c3e890969a600585122cdcc5Marc Blank        // We should catch HTML entities in these tests
7576f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(">", TextUtilities.makeSnippetFromHtmlText(" >"));
7676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("&<> \"", TextUtilities.makeSnippetFromHtmlText("&amp;&lt;&gt;&nbsp;&quot;"));
7776f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test for decimal and hex entities
7876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("ABC", TextUtilities.makeSnippetFromHtmlText("&#65;&#66;&#67;"));
7976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("ABC", TextUtilities.makeSnippetFromHtmlText("&#x41;&#x42;&#x43;"));
8076f614720db6a282c3e890969a600585122cdcc5Marc Blank
8176f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test for stripping simple tags
8276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("Hi there", TextUtilities.makeSnippetFromHtmlText("<html>Hi there</html>"));
8376f614720db6a282c3e890969a600585122cdcc5Marc Blank        // TODO: Add tests here if/when we find problematic HTML
8476f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
8576f614720db6a282c3e890969a600585122cdcc5Marc Blank
8676f614720db6a282c3e890969a600585122cdcc5Marc Blank    public void testStripHtmlEntityEdgeCases() {
8776f614720db6a282c3e890969a600585122cdcc5Marc Blank        int[] skipCount = new int[1];
8876f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Bare & isn't an entity
8976f614720db6a282c3e890969a600585122cdcc5Marc Blank        char c = TextUtilities.stripHtmlEntity("&", 0, skipCount);
9076f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
9176f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
9276f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Also not legal
9376f614720db6a282c3e890969a600585122cdcc5Marc Blank        c = TextUtilities.stripHtmlEntity("&;", 0, skipCount);
9476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
9576f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
9676f614720db6a282c3e890969a600585122cdcc5Marc Blank        // This is an entity, but shouldn't be found
9776f614720db6a282c3e890969a600585122cdcc5Marc Blank        c = TextUtilities.stripHtmlEntity("&nosuch;", 0, skipCount);
9876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
9976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
10076f614720db6a282c3e890969a600585122cdcc5Marc Blank        // This is too long for an entity, even though it starts like a valid one
10176f614720db6a282c3e890969a600585122cdcc5Marc Blank        c = TextUtilities.stripHtmlEntity("&nbspandmore;", 0, skipCount);
10276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
10376f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
10476f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Illegal decimal entities
10576f614720db6a282c3e890969a600585122cdcc5Marc Blank        c = TextUtilities.stripHtmlEntity("&#ABC", 0, skipCount);
10676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
10776f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
10876f614720db6a282c3e890969a600585122cdcc5Marc Blank        c = TextUtilities.stripHtmlEntity("&#12B", 0, skipCount);
10976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
11076f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
11176f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Illegal hex entities
11276f614720db6a282c3e890969a600585122cdcc5Marc Blank        c = TextUtilities.stripHtmlEntity("&#xABC", 0, skipCount);
11376f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
11476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
11576f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Illegal hex entities
11676f614720db6a282c3e890969a600585122cdcc5Marc Blank        c = TextUtilities.stripHtmlEntity("&#x19G", 0, skipCount);
11776f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(c, '&');
11876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(0, skipCount[0]);
11976f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
12076f614720db6a282c3e890969a600585122cdcc5Marc Blank
12176f614720db6a282c3e890969a600585122cdcc5Marc Blank    public void testStripContent() {
12276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("Visible", TextUtilities.makeSnippetFromHtmlText(
12376f614720db6a282c3e890969a600585122cdcc5Marc Blank            "<html><style foo=\"bar\">Not</style>Visible</html>"));
12476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("Visible", TextUtilities.makeSnippetFromHtmlText(
12576f614720db6a282c3e890969a600585122cdcc5Marc Blank            "<html><STYLE foo=\"bar\">Not</STYLE>Visible</html>"));
12676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("IsVisible", TextUtilities.makeSnippetFromHtmlText(
12776f614720db6a282c3e890969a600585122cdcc5Marc Blank            "<html><nostrip foo=\"bar\">Is</nostrip>Visible</html>"));
12876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("Visible", TextUtilities.makeSnippetFromHtmlText(
12976f614720db6a282c3e890969a600585122cdcc5Marc Blank            "<html>Visible<style foo=\"bar\">Not"));
13076f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("VisibleAgainVisible", TextUtilities.makeSnippetFromHtmlText(
13176f614720db6a282c3e890969a600585122cdcc5Marc Blank            "<html>Visible<style foo=\"bar\">Not</style>AgainVisible"));
13276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("VisibleAgainVisible", TextUtilities.makeSnippetFromHtmlText(
13376f614720db6a282c3e890969a600585122cdcc5Marc Blank            "<html>Visible<style foo=\"bar\"/>AgainVisible"));
13476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("VisibleAgainVisible", TextUtilities.makeSnippetFromHtmlText(
13576f614720db6a282c3e890969a600585122cdcc5Marc Blank            "<html>Visible<style foo=\"bar\"/><head><//blah<style>Not</head>AgainVisible"));
13676f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
13776f614720db6a282c3e890969a600585122cdcc5Marc Blank
13876f614720db6a282c3e890969a600585122cdcc5Marc Blank    /**
13976f614720db6a282c3e890969a600585122cdcc5Marc Blank     * We pass in HTML text in which an ampersand (@) is two chars ahead of the correct end position
14076f614720db6a282c3e890969a600585122cdcc5Marc Blank     * for the tag named 'tag' and then check whether the calculated end position matches the known
14176f614720db6a282c3e890969a600585122cdcc5Marc Blank     * correct position.  HTML text not containing an ampersand should generate a calculated end of
14276f614720db6a282c3e890969a600585122cdcc5Marc Blank     * -1
14376f614720db6a282c3e890969a600585122cdcc5Marc Blank     * @param text the HTML text to test
14476f614720db6a282c3e890969a600585122cdcc5Marc Blank     */
14576f614720db6a282c3e890969a600585122cdcc5Marc Blank    private void findTagEnd(String text, String tag) {
14676f614720db6a282c3e890969a600585122cdcc5Marc Blank        int calculatedEnd = TextUtilities.findTagEnd(text , tag, 0);
14776f614720db6a282c3e890969a600585122cdcc5Marc Blank        int knownEnd = text.indexOf('@') + 2;
14876f614720db6a282c3e890969a600585122cdcc5Marc Blank        if (knownEnd == 1) {
14976f614720db6a282c3e890969a600585122cdcc5Marc Blank            // indexOf will return -1, so we'll get 1 as knownEnd
15076f614720db6a282c3e890969a600585122cdcc5Marc Blank            assertEquals(-1, calculatedEnd);
15176f614720db6a282c3e890969a600585122cdcc5Marc Blank        } else {
15276f614720db6a282c3e890969a600585122cdcc5Marc Blank            assertEquals(calculatedEnd, knownEnd);
15376f614720db6a282c3e890969a600585122cdcc5Marc Blank        }
15476f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
15576f614720db6a282c3e890969a600585122cdcc5Marc Blank
15676f614720db6a282c3e890969a600585122cdcc5Marc Blank    public void testFindTagEnd() {
15776f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test with <tag ... />
15876f614720db6a282c3e890969a600585122cdcc5Marc Blank        findTagEnd("<tag foo=\"bar\"@ /> <blah blah>", "tag");
15976f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test with <tag ...> ... </tag>
16076f614720db6a282c3e890969a600585122cdcc5Marc Blank        findTagEnd("<tag foo=\"bar\">some text@</tag>some more text", "tag");
16176f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test with incomplete tag
16276f614720db6a282c3e890969a600585122cdcc5Marc Blank        findTagEnd("<tag foo=\"bar\">some more text but no end tag", "tag");
16376f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test with space at end of tag
16476f614720db6a282c3e890969a600585122cdcc5Marc Blank        findTagEnd("<tag foo=\"bar\">some more text but no end tag", "tag ");
16576f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
16676f614720db6a282c3e890969a600585122cdcc5Marc Blank
16776f614720db6a282c3e890969a600585122cdcc5Marc Blank    private void assertHighlightUnchanged(String str) {
16876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(str, TextUtilities.highlightTermsInHtml(str, null));
16976f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
17076f614720db6a282c3e890969a600585122cdcc5Marc Blank
17176f614720db6a282c3e890969a600585122cdcc5Marc Blank    public void testHighlightNoTerm() {
17276f614720db6a282c3e890969a600585122cdcc5Marc Blank        // With no search terms, the html should be unchanged
17376f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertHighlightUnchanged("<html><style foo=\"bar\">Not</style>Visible</html>");
17476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertHighlightUnchanged("<html><nostrip foo=\"bar\">Is</nostrip>Visible</html>");
17576f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertHighlightUnchanged("<html>Visible<style foo=\"bar\">Not");
17676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertHighlightUnchanged("<html>Visible<style foo=\"bar\">Not</style>AgainVisible");
17776f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertHighlightUnchanged("<html>Visible<style foo=\"bar\"/>AgainVisible");
17876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertHighlightUnchanged(
17976f614720db6a282c3e890969a600585122cdcc5Marc Blank                "<html>Visible<style foo=\"bar\"/><head><//blah<style>Not</head>AgainVisible");
18076f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
18176f614720db6a282c3e890969a600585122cdcc5Marc Blank
18276f614720db6a282c3e890969a600585122cdcc5Marc Blank    public void testHighlightSingleTermHtml() {
18376f614720db6a282c3e890969a600585122cdcc5Marc Blank        String str = "<html><style foo=\"bar\">Not</style>Visible</html>";
18476f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test that tags aren't highlighted
18576f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(str, TextUtilities.highlightTermsInHtml(
18676f614720db6a282c3e890969a600585122cdcc5Marc Blank                "<html><style foo=\"bar\">Not</style>Visible</html>", "style"));
18776f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Test that non-tags are
18876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("<html><style foo=\"bar\">Not</style><span " +
18976f614720db6a282c3e890969a600585122cdcc5Marc Blank                "style=\"background-color: " + TextUtilities.HIGHLIGHT_COLOR_STRING +
19076f614720db6a282c3e890969a600585122cdcc5Marc Blank                "\">Visi</span>ble</html>",
19176f614720db6a282c3e890969a600585122cdcc5Marc Blank                TextUtilities.highlightTermsInHtml(str, "Visi"));
19276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals("<html>Visible<style foo=\"bar\">Not</style>A<span" +
19376f614720db6a282c3e890969a600585122cdcc5Marc Blank                " style=\"background-color: " + TextUtilities.HIGHLIGHT_COLOR_STRING +
19476f614720db6a282c3e890969a600585122cdcc5Marc Blank                "\">gain</span>Visible",
19576f614720db6a282c3e890969a600585122cdcc5Marc Blank                TextUtilities.highlightTermsInHtml(
19676f614720db6a282c3e890969a600585122cdcc5Marc Blank                        "<html>Visible<style foo=\"bar\">Not</style>AgainVisible", "gain"));
19776f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
19876f614720db6a282c3e890969a600585122cdcc5Marc Blank
1997037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestHighlightSingleTermText() {
20076f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Sprinkle text with a few HTML characters to make sure they're ignored
20176f614720db6a282c3e890969a600585122cdcc5Marc Blank        String text = "This< should be visibl>e";
20276f614720db6a282c3e890969a600585122cdcc5Marc Blank        // We should find this, because search terms are case insensitive
20376f614720db6a282c3e890969a600585122cdcc5Marc Blank        SpannableStringBuilder ssb =
20476f614720db6a282c3e890969a600585122cdcc5Marc Blank            (SpannableStringBuilder)TextUtilities.highlightTermsInText(text, "Visi");
20576f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan[] spans = ssb.getSpans(0, ssb.length(), BackgroundColorSpan.class);
20676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(1, spans.length);
20776f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan span = spans[0];
20876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("visi"), ssb.getSpanStart(span));
20976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("bl>e"), ssb.getSpanEnd(span));
21076f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Heh; this next test fails.. we use the search term!
21176f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text, ssb.toString());
21276f614720db6a282c3e890969a600585122cdcc5Marc Blank
21376f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Multiple instances of the term
21476f614720db6a282c3e890969a600585122cdcc5Marc Blank        text = "The research word should be a search result";
21576f614720db6a282c3e890969a600585122cdcc5Marc Blank        ssb = (SpannableStringBuilder)TextUtilities.highlightTermsInText(text, "Search");
21676f614720db6a282c3e890969a600585122cdcc5Marc Blank        spans = ssb.getSpans(0, ssb.length(), BackgroundColorSpan.class);
21776f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(2, spans.length);
21876f614720db6a282c3e890969a600585122cdcc5Marc Blank        span = spans[0];
21976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("search word"), ssb.getSpanStart(span));
22076f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf(" word"), ssb.getSpanEnd(span));
22176f614720db6a282c3e890969a600585122cdcc5Marc Blank        span = spans[1];
22276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("search result"), ssb.getSpanStart(span));
22376f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf(" result"), ssb.getSpanEnd(span));
22476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text, ssb.toString());
22576f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
22676f614720db6a282c3e890969a600585122cdcc5Marc Blank
2277037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestHighlightTwoTermText() {
22876f614720db6a282c3e890969a600585122cdcc5Marc Blank        String text = "This should be visible";
22976f614720db6a282c3e890969a600585122cdcc5Marc Blank        // We should find this, because search terms are case insensitive
23076f614720db6a282c3e890969a600585122cdcc5Marc Blank        SpannableStringBuilder ssb =
23176f614720db6a282c3e890969a600585122cdcc5Marc Blank            (SpannableStringBuilder)TextUtilities.highlightTermsInText(text, "visi should");
23276f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan[] spans = ssb.getSpans(0, ssb.length(), BackgroundColorSpan.class);
23376f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(2, spans.length);
23476f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan span = spans[0];
23576f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("should"), ssb.getSpanStart(span));
23676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf(" be"), ssb.getSpanEnd(span));
23776f614720db6a282c3e890969a600585122cdcc5Marc Blank        span = spans[1];
23876f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("visi"), ssb.getSpanStart(span));
23976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("ble"), ssb.getSpanEnd(span));
24076f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text, ssb.toString());
24176f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
24276f614720db6a282c3e890969a600585122cdcc5Marc Blank
2437037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestHighlightDuplicateTermText() {
24476f614720db6a282c3e890969a600585122cdcc5Marc Blank        String text = "This should be visible";
24576f614720db6a282c3e890969a600585122cdcc5Marc Blank        // We should find this, because search terms are case insensitive
24676f614720db6a282c3e890969a600585122cdcc5Marc Blank        SpannableStringBuilder ssb =
24776f614720db6a282c3e890969a600585122cdcc5Marc Blank            (SpannableStringBuilder)TextUtilities.highlightTermsInText(text, "should should");
24876f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan[] spans = ssb.getSpans(0, ssb.length(), BackgroundColorSpan.class);
24976f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(1, spans.length);
25076f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan span = spans[0];
25176f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("should"), ssb.getSpanStart(span));
25276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf(" be"), ssb.getSpanEnd(span));
25376f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
25476f614720db6a282c3e890969a600585122cdcc5Marc Blank
2557037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestHighlightOverlapTermText() {
25676f614720db6a282c3e890969a600585122cdcc5Marc Blank        String text = "This shoulder is visible";
25776f614720db6a282c3e890969a600585122cdcc5Marc Blank        // We should find this, because search terms are case insensitive
25876f614720db6a282c3e890969a600585122cdcc5Marc Blank        SpannableStringBuilder ssb =
25976f614720db6a282c3e890969a600585122cdcc5Marc Blank            (SpannableStringBuilder)TextUtilities.highlightTermsInText(text, "should ould");
26076f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan[] spans = ssb.getSpans(0, ssb.length(), BackgroundColorSpan.class);
26176f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(1, spans.length);
26276f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan span = spans[0];
26376f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("should"), ssb.getSpanStart(span));
26476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("er is"), ssb.getSpanEnd(span));
26576f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
26676f614720db6a282c3e890969a600585122cdcc5Marc Blank
26776f614720db6a282c3e890969a600585122cdcc5Marc Blank
2687037a0bd3d8e925a9115f475f5c0d05ddae2eeeeJerry Xie    public void brokentestHighlightOverlapTermText2() {
26976f614720db6a282c3e890969a600585122cdcc5Marc Blank        String text = "The shoulders are visible";
27076f614720db6a282c3e890969a600585122cdcc5Marc Blank        // We should find this, because search terms are case insensitive
27176f614720db6a282c3e890969a600585122cdcc5Marc Blank        SpannableStringBuilder ssb =
27276f614720db6a282c3e890969a600585122cdcc5Marc Blank            (SpannableStringBuilder)TextUtilities.highlightTermsInText(text, "shoulder shoulders");
27376f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan[] spans = ssb.getSpans(0, ssb.length(), BackgroundColorSpan.class);
27476f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(2, spans.length);
27576f614720db6a282c3e890969a600585122cdcc5Marc Blank        BackgroundColorSpan span = spans[0];
27676f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("shoulder"), ssb.getSpanStart(span));
27776f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("s are visible"), ssb.getSpanEnd(span));
27876f614720db6a282c3e890969a600585122cdcc5Marc Blank        span = spans[1];
27976f614720db6a282c3e890969a600585122cdcc5Marc Blank        // Just the 's' should be caught in the 2nd span
28076f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf("s are visible"), ssb.getSpanStart(span));
28176f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text.indexOf(" are visible"), ssb.getSpanEnd(span));
28276f614720db6a282c3e890969a600585122cdcc5Marc Blank        assertEquals(text, ssb.toString());
28376f614720db6a282c3e890969a600585122cdcc5Marc Blank    }
28476f614720db6a282c3e890969a600585122cdcc5Marc Blank    // For debugging large HTML samples
28576f614720db6a282c3e890969a600585122cdcc5Marc Blank
28676f614720db6a282c3e890969a600585122cdcc5Marc Blank//    private String readLargeSnippet(String fn) {
28776f614720db6a282c3e890969a600585122cdcc5Marc Blank//        File file = mContext.getFileStreamPath(fn);
28876f614720db6a282c3e890969a600585122cdcc5Marc Blank//        StringBuffer sb = new StringBuffer();
28976f614720db6a282c3e890969a600585122cdcc5Marc Blank//        BufferedReader reader = null;
29076f614720db6a282c3e890969a600585122cdcc5Marc Blank//        try {
29176f614720db6a282c3e890969a600585122cdcc5Marc Blank//            String text;
29276f614720db6a282c3e890969a600585122cdcc5Marc Blank//            reader = new BufferedReader(new FileReader(file));
29376f614720db6a282c3e890969a600585122cdcc5Marc Blank//            while ((text = reader.readLine()) != null) {
29476f614720db6a282c3e890969a600585122cdcc5Marc Blank//                sb.append(text);
29576f614720db6a282c3e890969a600585122cdcc5Marc Blank//                sb.append(" ");
29676f614720db6a282c3e890969a600585122cdcc5Marc Blank//            }
29776f614720db6a282c3e890969a600585122cdcc5Marc Blank//        } catch (IOException e) {
29876f614720db6a282c3e890969a600585122cdcc5Marc Blank//        }
29976f614720db6a282c3e890969a600585122cdcc5Marc Blank//        return sb.toString();
30076f614720db6a282c3e890969a600585122cdcc5Marc Blank//    }
30176f614720db6a282c3e890969a600585122cdcc5Marc Blank }
302