/******************************************************************************* * Copyright (C) 2015, Thomas Wolf <thomas.wolf@paranor.ch> * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.eclipse.egit.ui.internal.dialogs; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.util.Arrays; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.TextAttribute; import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector; import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.jface.text.hyperlink.URLHyperlinkDetector; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.ui.texteditor.AbstractTextEditor; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class HyperlinkTokenScannerTest { @Mock private ISourceViewer viewer; @Mock private SourceViewerConfiguration configuration; @Mock private IPreferenceStore preferenceStore; private IHyperlinkDetector[] detectors = new IHyperlinkDetector[] { new URLHyperlinkDetector() }; private IHyperlinkDetector[] detectorsWithFailure = new IHyperlinkDetector[] { new URLHyperlinkDetector(), new CrashingHyperlinkDetector() }; @Test public void tokenizeEmpty() { String testString = ""; String expected = ""; assertTokens(testString, 0, testString.length(), expected); } @Test public void tokenizeNoHyperlinks() { String testString = "hello world"; String expected = "DDDDDDDDDDD"; assertTokens(testString, 0, testString.length(), expected); } @Test public void tokenizeLeadingHyperlink() { String testString = "http://foo bar"; String expected = "HHHHHHHHHHDDDD"; assertTokens(testString, 0, testString.length(), expected); } @Test public void tokenizeEmbeddedHyperlink() { String testString = "Link: http://foo bar"; String expected = "DDDDDDHHHHHHHHHHDDDD"; assertTokens(testString, 0, testString.length(), expected); } @Test public void tokenizeMultipleHyperlinksSimple() { String testString = "Link: http://foo http://www.example.com bar"; String expected = "DDDDDDHHHHHHHHHHDHHHHHHHHHHHHHHHHHHHHHHDDDD"; assertTokens(testString, 0, testString.length(), expected); } @Test public void tokenizeMultipleHyperlinksMultiline() { String testString = "Link: http://foo\n\n* http://foo\n* ftp://somewhere\n\nTwo links above."; String expected = "DDDDDDHHHHHHHHHHDDDDHHHHHHHHHHDDDHHHHHHHHHHHHHHHDDDDDDDDDDDDDDDDDD"; assertTokens(testString, 0, testString.length(), expected); } @Test public void tokenizeHyperlinksOutsideRegion() { String testString = "Link: http://foo\n\n* http://foo\n* ftp://somewhere\n\nTwo links above."; String expected = "DDDDD "; assertTokens(testString, 0, 5, expected); expected = " DDDDDDDDDDDD "; assertTokens(testString, 50, 12, expected); } @Test public void tokenizeHyperlinksCutByRegion() { String testString = "Link: http://foo\n\n* http://foo\n* ftp://somewhere\n\nTwo links above."; String expected = "DDDDDDHHHHHHHH "; assertTokens(testString, 0, 14, expected); expected = " HDDDDHHHHHHHHH "; assertTokens(testString, 15, 14, expected); } @Test public void tokenizeWithFailingDetector() { String testString = "Link: http://foo bar"; String expected = "DDDDDDHHHHHHHHHHDDDD"; assertTokens(testString, 0, testString.length(), detectorsWithFailure, expected); // With only a failing detector expected = "DDDDDDDDDDDDDDDDDDDD"; assertTokens(testString, 0, testString.length(), new IHyperlinkDetector[] { new CrashingHyperlinkDetector() }, expected); } @Test public void tokenizeWithoutDetectors() { String testString = "Link: http://foo bar"; String expected = "DDDDDDDDDDDDDDDDDDDD"; assertTokens(testString, 0, testString.length(), new IHyperlinkDetector[] {}, expected); } private void assertTokens(String text, int offset, int length, String expected) { assertTokens(text, offset, length, detectors, expected); } @SuppressWarnings("boxing") private void assertTokens(String text, int offset, int length, IHyperlinkDetector[] hyperlinkDetectors, String expected) { assertEquals("Test definition problem: 'expected' length mismatch", text.length(), expected.length()); IDocument testDocument = new Document(text); when(viewer.getDocument()).thenReturn(testDocument); when(configuration.getHyperlinkDetectors(viewer)) .thenReturn(hyperlinkDetectors); when(preferenceStore .getBoolean(AbstractTextEditor.PREFERENCE_HYPERLINKS_ENABLED)) .thenReturn(true); when(preferenceStore.getBoolean( "org.eclipse.ui.internal.editors.text.URLHyperlinkDetector")) .thenReturn(hyperlinkDetectors.length == 0 || (hyperlinkDetectors[0] instanceof CrashingHyperlinkDetector)); HyperlinkTokenScanner scanner = new HyperlinkTokenScanner(configuration, viewer, preferenceStore, null); scanner.setRangeAndColor(testDocument, offset, length, null); IToken token = null; char[] found = new char[text.length()]; Arrays.fill(found, ' '); while (!(token = scanner.nextToken()).isEOF()) { int tokenOffset = scanner.getTokenOffset(); int tokenLength = scanner.getTokenLength(); char ch = 'x'; Object data = token.getData(); if (data == null) { ch = 'D'; } else if (data instanceof TextAttribute) { int style = ((TextAttribute) data).getStyle(); if ((style & TextAttribute.UNDERLINE) != 0) { ch = 'H'; } } Arrays.fill(found, tokenOffset, tokenOffset + tokenLength, ch); } assertEquals("Unexpected tokens", expected, new String(found)); } private static class CrashingHyperlinkDetector extends AbstractHyperlinkDetector { @Override public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) { throw new IllegalStateException( "CrashingHyperlinkDetector fails on purpose"); } } }