1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2017, 2018, Chris Fraire <cfraire@me.com>. 23 */ 24 package org.opengrok.indexer.analysis.haskell; 25 26 import java.io.BufferedReader; 27 import java.io.ByteArrayOutputStream; 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.InputStreamReader; 31 import java.io.PrintStream; 32 import java.io.StringReader; 33 import java.io.StringWriter; 34 import java.io.Writer; 35 import java.nio.charset.StandardCharsets; 36 37 import org.junit.jupiter.api.Test; 38 import org.opengrok.indexer.analysis.AbstractAnalyzer; 39 import org.opengrok.indexer.analysis.CtagsReader; 40 import org.opengrok.indexer.analysis.Definitions; 41 import org.opengrok.indexer.analysis.WriteXrefArgs; 42 import org.opengrok.indexer.analysis.Xrefer; 43 44 import static org.junit.jupiter.api.Assertions.assertEquals; 45 import static org.junit.jupiter.api.Assertions.assertNotNull; 46 import static org.opengrok.indexer.util.CustomAssertions.assertLinesEqual; 47 import static org.opengrok.indexer.util.StreamUtils.copyStream; 48 49 /** 50 * Tests the {@link HaskellXref} class. 51 * 52 * @author Harry Pan 53 */ 54 public class HaskellXrefTest { 55 56 @Test basicTest()57 public void basicTest() throws IOException { 58 String s = "putStrLn \"Hello, world!\""; 59 Writer w = new StringWriter(); 60 HaskellAnalyzerFactory fac = new HaskellAnalyzerFactory(); 61 AbstractAnalyzer analyzer = fac.getAnalyzer(); 62 WriteXrefArgs xargs = new WriteXrefArgs(new StringReader(s), w); 63 Xrefer xref = analyzer.writeXref(xargs); 64 assertLinesEqual("Haskell basicTest", 65 "<a class=\"l\" name=\"1\" href=\"#1\">1</a>" + 66 "<a href=\"/source/s?defs=putStrLn\" class=\"intelliWindow-symbol\"" + 67 " data-definition-place=\"undefined-in-file\">putStrLn</a>" + 68 " <span class=\"s\">"Hello, world!"</span>\n", 69 w.toString()); 70 assertEquals(1, xref.getLOC(), "Haskell LOC"); 71 } 72 writeHaskellXref(InputStream is, PrintStream os, Definitions defs)73 private static int writeHaskellXref(InputStream is, PrintStream os, 74 Definitions defs) throws IOException { 75 os.println("<!DOCTYPE html><html lang=\"en\"><head><meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\" />" 76 + "<link rel=\"stylesheet\" type=\"text/css\" " 77 + "href=\"http://localhost:8080/source/default/style.css\" /><title>Haskell Xref Test</title></head>"); 78 os.println("<body><div id=\"src\"><pre>"); 79 Writer w = new StringWriter(); 80 HaskellAnalyzerFactory fac = new HaskellAnalyzerFactory(); 81 AbstractAnalyzer analyzer = fac.getAnalyzer(); 82 WriteXrefArgs args = new WriteXrefArgs(new InputStreamReader(is, StandardCharsets.UTF_8), w); 83 args.setDefs(defs); 84 Xrefer xref = analyzer.writeXref(args); 85 os.print(w.toString()); 86 os.println("</pre></div></body></html>"); 87 return xref.getLOC(); 88 } 89 90 @Test sampleTest()91 public void sampleTest() throws IOException { 92 // load sample source 93 InputStream sampleInputStream = getClass().getClassLoader().getResourceAsStream( 94 "analysis/haskell/sample.hs"); 95 ByteArrayOutputStream sampleOutputStream = new ByteArrayOutputStream(); 96 97 Definitions defs = new Definitions(); 98 defs.addTag(6, "x'y'", "functions", 99 "x'y' = let f' = 1; g'h = 2 in f' + g'h", 0, 0); 100 int actLOC; 101 try { 102 actLOC = writeHaskellXref(sampleInputStream, new PrintStream(sampleOutputStream), defs); 103 } finally { 104 sampleInputStream.close(); 105 sampleOutputStream.close(); 106 } 107 108 // load expected xref 109 InputStream expectedInputStream = getClass().getClassLoader().getResourceAsStream( 110 "analysis/haskell/sampleXrefExpected.html"); 111 ByteArrayOutputStream expectedOutputSteam = new ByteArrayOutputStream(); 112 try { 113 byte[] buffer = new byte[8192]; 114 int numBytesRead; 115 do { 116 numBytesRead = expectedInputStream.read(buffer, 0, buffer.length); 117 if (numBytesRead > 0) { 118 expectedOutputSteam.write(buffer, 0, numBytesRead); 119 } 120 } while (numBytesRead >= 0); 121 } finally { 122 expectedInputStream.close(); 123 expectedOutputSteam.close(); 124 } 125 126 String[] actual = new String(sampleOutputStream.toByteArray(), StandardCharsets.UTF_8).split("\\r?\\n"); 127 String[] expected = new String(expectedOutputSteam.toByteArray(), StandardCharsets.UTF_8).split("\\r?\\n"); 128 assertLinesEqual("Haskell sampleTest()", expected, actual); 129 assertEquals(3, actLOC, "Haskell LOC"); 130 } 131 132 @Test sampleTest2()133 public void sampleTest2() throws IOException { 134 writeAndCompare("analysis/haskell/sample2.hs", 135 "analysis/haskell/sample2_xref.html", 136 getTagsDefinitions(), 198); 137 } 138 139 @Test shouldCloseTruncatedStringSpan()140 public void shouldCloseTruncatedStringSpan() throws IOException { 141 writeAndCompare("analysis/haskell/truncated.hs", 142 "analysis/haskell/truncated_xref.html", 143 null, 1); 144 } 145 writeAndCompare(String sourceResource, String resultResource, Definitions defs, int expLOC)146 private void writeAndCompare(String sourceResource, String resultResource, 147 Definitions defs, int expLOC) throws IOException { 148 149 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 150 151 InputStream res = getClass().getClassLoader().getResourceAsStream( 152 sourceResource); 153 assertNotNull(res, sourceResource + " should get-as-stream"); 154 int actLOC = writeHaskellXref(res, new PrintStream(baos), defs); 155 res.close(); 156 157 InputStream exp = getClass().getClassLoader().getResourceAsStream( 158 resultResource); 159 assertNotNull(exp, resultResource + " should get-as-stream"); 160 byte[] expbytes = copyStream(exp); 161 exp.close(); 162 baos.close(); 163 164 String ostr = new String(baos.toByteArray(), StandardCharsets.UTF_8); 165 String[] gotten = ostr.split("\\r?\\n"); 166 167 String estr = new String(expbytes, StandardCharsets.UTF_8); 168 String[] expected = estr.split("\n"); 169 170 assertLinesEqual("Haskell xref", expected, gotten); 171 assertEquals(expLOC, actLOC, "Haskell LOC"); 172 } 173 getTagsDefinitions()174 private Definitions getTagsDefinitions() throws IOException { 175 InputStream res = getClass().getClassLoader().getResourceAsStream( 176 "analysis/haskell/sampletags"); 177 assertNotNull(res, "though sampletags should stream,"); 178 179 BufferedReader in = new BufferedReader(new InputStreamReader(res, StandardCharsets.UTF_8)); 180 181 CtagsReader rdr = new CtagsReader(); 182 String line; 183 while ((line = in.readLine()) != null) { 184 rdr.readLine(line); 185 } 186 return rdr.getDefinitions(); 187 } 188 } 189