Skip to content

Commit 9a6d010

Browse files
committed
Add RustXrefTest with one non-passing for dangling span
1 parent 91d0e02 commit 9a6d010

File tree

7 files changed

+521
-0
lines changed

7 files changed

+521
-0
lines changed

opengrok-indexer/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ Portions Copyright (c) 2017, Chris Fraire <[email protected]>.
137137
<exclude>*.java</exclude>
138138
</excludes>
139139
</testResource>
140+
<testResource>
141+
<targetPath>org/opensolaris/opengrok/analysis/rust/</targetPath>
142+
<directory>../test/org/opensolaris/opengrok/analysis/rust/</directory>
143+
<excludes>
144+
<exclude>*.java</exclude>
145+
</excludes>
146+
</testResource>
140147
<testResource>
141148
<targetPath>org/opensolaris/opengrok/analysis/haskell/</targetPath>
142149
<directory>../test/org/opensolaris/opengrok/analysis/haskell/</directory>
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2017, Chris Fraire <[email protected]>.
23+
*/
24+
25+
package org.opensolaris.opengrok.analysis.rust;
26+
27+
import java.io.BufferedReader;
28+
import java.io.ByteArrayOutputStream;
29+
import java.io.IOException;
30+
import java.io.InputStream;
31+
import java.io.InputStreamReader;
32+
import java.io.OutputStream;
33+
import java.io.PrintStream;
34+
import java.io.StringWriter;
35+
import java.io.Writer;
36+
37+
import org.opensolaris.opengrok.analysis.CtagsReader;
38+
import org.opensolaris.opengrok.analysis.Definitions;
39+
import org.opensolaris.opengrok.analysis.FileAnalyzer;
40+
import org.opensolaris.opengrok.analysis.WriteXrefArgs;
41+
import org.junit.Test;
42+
import static org.junit.Assert.assertNotNull;
43+
import static org.opensolaris.opengrok.util.CustomAssertions.assertLinesEqual;
44+
45+
/**
46+
* Tests the {@link RustXref} class.
47+
*/
48+
public class RustXrefTest {
49+
50+
@Test
51+
public void sampleTest() throws IOException {
52+
writeAndCompare("org/opensolaris/opengrok/analysis/rust/sample.rs",
53+
"org/opensolaris/opengrok/analysis/rust/sample_xref.html",
54+
getTagsDefinitions());
55+
}
56+
57+
@Test
58+
public void shouldCloseTruncatedStringSpan() throws IOException {
59+
writeAndCompare("org/opensolaris/opengrok/analysis/rust/truncated.rs",
60+
"org/opensolaris/opengrok/analysis/rust/truncated_xref.html",
61+
null);
62+
}
63+
64+
private void writeAndCompare(String sourceResource, String resultResource,
65+
Definitions defs)
66+
throws IOException {
67+
68+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
69+
ByteArrayOutputStream baosExp = new ByteArrayOutputStream();
70+
71+
InputStream res = getClass().getClassLoader().getResourceAsStream(
72+
sourceResource);
73+
assertNotNull(sourceResource + " should get-as-stream", res);
74+
writeRustXref(new PrintStream(baos), res, defs);
75+
res.close();
76+
77+
InputStream exp = getClass().getClassLoader().getResourceAsStream(
78+
resultResource);
79+
assertNotNull(resultResource + " should get-as-stream", exp);
80+
copyStream(exp, baosExp);
81+
exp.close();
82+
baosExp.close();
83+
baos.close();
84+
85+
String ostr = new String(baos.toByteArray(), "UTF-8");
86+
String gotten[] = ostr.split("\n");
87+
88+
String estr = new String(baosExp.toByteArray(), "UTF-8");
89+
String expected[] = estr.split("\n");
90+
91+
assertLinesEqual("Rust xref", expected, gotten);
92+
}
93+
94+
private void writeRustXref(PrintStream oss, InputStream iss,
95+
Definitions defs)
96+
throws IOException {
97+
98+
oss.print(getHtmlBegin());
99+
100+
Writer sw = new StringWriter();
101+
RustAnalyzerFactory fac = new RustAnalyzerFactory();
102+
FileAnalyzer analyzer = fac.getAnalyzer();
103+
analyzer.setScopesEnabled(true);
104+
analyzer.setFoldingEnabled(true);
105+
WriteXrefArgs wargs = new WriteXrefArgs(
106+
new InputStreamReader(iss, "UTF-8"), sw);
107+
wargs.setDefs(defs);
108+
analyzer.writeXref(wargs);
109+
oss.print(sw.toString());
110+
111+
oss.print(getHtmlEnd());
112+
}
113+
114+
private void copyStream(InputStream iss, OutputStream oss)
115+
throws IOException {
116+
117+
byte buffer[] = new byte[8192];
118+
int read;
119+
do {
120+
read = iss.read(buffer, 0, buffer.length);
121+
if (read > 0) {
122+
oss.write(buffer, 0, read);
123+
}
124+
} while (read >= 0);
125+
}
126+
127+
private Definitions getTagsDefinitions() throws IOException {
128+
InputStream res = getClass().getClassLoader().getResourceAsStream(
129+
"org/opensolaris/opengrok/analysis/rust/sampletags");
130+
assertNotNull("though sampletags should stream,", res);
131+
132+
BufferedReader in = new BufferedReader(new InputStreamReader(
133+
res, "UTF-8"));
134+
135+
CtagsReader rdr = new CtagsReader();
136+
String line;
137+
while ((line = in.readLine()) != null) {
138+
rdr.readLine(line);
139+
}
140+
return rdr.getDefinitions();
141+
}
142+
143+
private static String getHtmlBegin() {
144+
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
145+
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" +
146+
" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" +
147+
"<html xmlns=\"http://www.w3.org/1999/xhtml\"" +
148+
" xml:lang=\"en\" lang=\"en\"\n" +
149+
" class=\"xref\">\n" +
150+
"<head>\n" +
151+
"<title>sampleFile - OpenGrok cross reference" +
152+
" for /sampleFile</title></head><body>\n";
153+
}
154+
155+
private static String getHtmlEnd() {
156+
return "</body>\n" +
157+
"</html>\n";
158+
}
159+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/// The MIT License (MIT)
2+
///
3+
/// Copyright (c) 2015 Andrew Gallant
4+
///
5+
/// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
/// of this software and associated documentation files (the "Software"), to deal
7+
/// in the Software without restriction, including without limitation the rights
8+
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
/// copies of the Software, and to permit persons to whom the Software is
10+
/// furnished to do so, subject to the following conditions:
11+
///
12+
/// The above copyright notice and this permission notice shall be included in
13+
/// all copies or substantial portions of the Software.
14+
///
15+
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
/// THE SOFTWARE.
22+
23+
/// A single state in the state machine used by `unescape`.
24+
#[derive(Clone, Copy, Eq, PartialEq)]
25+
enum State {
26+
/// The state after seeing a `\`.
27+
Escape,
28+
/// The state after seeing a `\x`.
29+
HexFirst,
30+
/// The state after seeing a `\x[0-9A-Fa-f]`.
31+
HexSecond(char),
32+
/// Default state.
33+
Literal,
34+
}
35+
36+
/// Unescapes a string given on the command line. It supports a limited set of
37+
/// escape sequences:
38+
///
39+
/// * \t, \r and \n are mapped to their corresponding ASCII bytes.
40+
/// * \xZZ hexadecimal escapes are mapped to their byte.
41+
pub fn unescape(s: &str) -> Vec<u8> {
42+
use self::State::*;
43+
44+
let mut bytes = vec![];
45+
let mut state = Literal;
46+
for c in s.chars() {
47+
match state {
48+
Escape => {
49+
match c {
50+
'n' => { bytes.push(b'\n'); state = Literal; }
51+
'r' => { bytes.push(b'\r'); state = Literal; }
52+
't' => { bytes.push(b'\t'); state = Literal; }
53+
'x' => { state = HexFirst; }
54+
c => {
55+
bytes.extend(format!(r"\{}", c).into_bytes());
56+
state = Literal;
57+
}
58+
}
59+
}
60+
HexFirst => {
61+
match c {
62+
'0'...'9' | 'A'...'F' | 'a'...'f' => {
63+
state = HexSecond(c);
64+
}
65+
c => {
66+
bytes.extend(format!(r"\x{}", c).into_bytes());
67+
state = Literal;
68+
}
69+
}
70+
}
71+
HexSecond(first) => {
72+
match c {
73+
'0'...'9' | 'A'...'F' | 'a'...'f' => {
74+
let ordinal = format!("{}{}", first, c);
75+
let byte = u8::from_str_radix(&ordinal, 16).unwrap();
76+
bytes.push(byte);
77+
state = Literal;
78+
byte = 0xFF;
79+
}
80+
c => {
81+
let original = format!(r"\x{}{}", first, c);
82+
bytes.extend(original.into_bytes());
83+
state = Literal;
84+
}
85+
}
86+
}
87+
Literal => {
88+
match c {
89+
'\\' => { state = Escape; }
90+
c => { bytes.extend(c.to_string().as_bytes()); }
91+
}
92+
}
93+
}
94+
}
95+
match state {
96+
Escape => bytes.push(b'\\'),
97+
HexFirst => bytes.extend(b"\\x"),
98+
HexSecond(c) => bytes.extend(format!("\\x{}", c).into_bytes()),
99+
Literal => {}
100+
}
101+
bytes
102+
}
103+
104+
#[cfg(test)]
105+
mod tests {
106+
use super::unescape;
107+
108+
fn b(bytes: &'static [u8]) -> Vec<u8> {
109+
bytes.to_vec()
110+
}
111+
112+
#[test]
113+
fn unescape_nul() {
114+
assert_eq!(b(b"\x00"), unescape(r"\x00"));
115+
}
116+
117+
#[test]
118+
fn unescape_nl() {
119+
assert_eq!(b(b"\n"), unescape(r"\n"));
120+
}
121+
122+
#[test]
123+
fn unescape_tab() {
124+
assert_eq!(b(b"\t"), unescape(r"\t"));
125+
}
126+
127+
#[test]
128+
fn unescape_carriage() {
129+
assert_eq!(b(b"\r"), unescape(r"\r"));
130+
}
131+
132+
#[test]
133+
fn unescape_nothing_simple() {
134+
assert_eq!(b(b"\\a"), unescape(r"\a"));
135+
}
136+
137+
#[test]
138+
fn unescape_nothing_hex0() {
139+
assert_eq!(b(b"\\x"), unescape(r"\x"));
140+
}
141+
142+
#[test]
143+
fn unescape_nothing_hex1() {
144+
assert_eq!(b(b"\\xz"), unescape(r"\xz"));
145+
}
146+
147+
#[test]
148+
fn unescape_nothing_hex2() {
149+
assert_eq!(b(b"\\xzz"), unescape(r"\xzz"));
150+
}
151+
}

0 commit comments

Comments
 (0)