Skip to content

Commit a9b1439

Browse files
committed
all kinds of test coverage updates
1 parent 2ef6e88 commit a9b1439

18 files changed

Lines changed: 1069 additions & 120 deletions

File tree

CONTRIBUTING.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ Please note that [ressa](https://github.com/freemasen/ressa) and [resast](https:
77

88
I do not work on this full time, please be patient if I am not able to respond quickly.
99

10-
The primary development branch is the `next` branch. It would be ideal to create any pull requests against that branch over `master` or one of the other feature branches that might have been missed when cleaning up.
11-
1210
For any PRs know that the code must pass ci tests before they will be reviewed/merged. These test include the following commands you could use to check your version.
13-
```sh
14-
$ npm i
15-
$ cargo test
16-
$ cargo run --example major_libs
11+
12+
```shell
13+
npm i
14+
cargo test
15+
cargo run --example major_libs
1716
```
17+
1818
The release flag in the above is due to the fact that this example is a naive benchmark to validate that changes haven't completely ruined the performance. Feel free to leave this flag off when you are testing for a PR.
1919

2020
This will run all of the project's unit tests as well as a test against some major js libraries, namely [Angular-js](angularjs.org), [Jquery](jquery.com), [React/React-Dom](reactjs.org), [Vue](vuejs.org), [Moment.js](momentjs.com) and [Dexie](dexie.org).
@@ -63,6 +63,7 @@ The overall code layout works like this.
6363
- `is_other_whitesapce`: the ECMA spec says that any Zs category character is valid whitespace. This function will test any exotic whitespaces
6464

6565
# Testing
66+
6667
There are a few sets of JavaScript files that are required to run the tests in this repository. The first set can be easily aquired by running `npm install` in the root of this project. An additional test is also available behind a feature flag `moz_central` that requires the JIT Test files from the FireFox repository, the expectation is that these will exist in the folder `moz-central` in the root of this project. To get these files you can either manually download and unzip them by following [this link](https://hg.mozilla.org/mozilla-central/archive/tip.zip/js/src/jit-test/tests/) or you can execute the following command.
6768

6869
```sh
@@ -74,4 +75,4 @@ To run these tests simple execute the following command.
7475

7576
```sh
7677
cargo test --features moz_central -- moz_central
77-
```
78+
```

examples/major_libs/src/main.rs

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::{
1212
time::{Duration, SystemTime},
1313
};
1414

15+
#[derive(Debug, Default, Clone, Copy, PartialEq)]
1516
struct Args {
1617
pub angular: bool,
1718
pub jquery: bool,
@@ -22,29 +23,19 @@ struct Args {
2223
pub dexie: bool,
2324
}
2425

25-
impl ::std::default::Default for Args {
26-
fn default() -> Args {
27-
Args {
28-
angular: false,
29-
jquery: false,
30-
react: false,
31-
react_dom: false,
32-
vue: false,
33-
moment: false,
34-
dexie: false,
35-
}
36-
}
37-
}
38-
3926
impl Args {
4027
fn pristine(&self) -> bool {
41-
!self.angular
42-
&& !self.jquery
43-
&& !self.react
44-
&& !self.react_dom
45-
&& !self.vue
46-
&& !self.moment
47-
&& !self.dexie
28+
self == &Self::default()
29+
}
30+
31+
fn mark_all_true(&mut self) {
32+
self.angular = true;
33+
self.jquery = true;
34+
self.react = true;
35+
self.react_dom = true;
36+
self.vue = true;
37+
self.moment = true;
38+
self.dexie = true;
4839
}
4940
}
5041

@@ -70,6 +61,9 @@ fn main() {
7061
a.dexie = true;
7162
}
7263
}
64+
if a.pristine() {
65+
a.mark_all_true();
66+
}
7367
if a.jquery {
7468
jquery();
7569
}
@@ -91,15 +85,6 @@ fn main() {
9185
if a.dexie {
9286
dexie();
9387
}
94-
if a.pristine() {
95-
jquery();
96-
angular1();
97-
react();
98-
react_dom();
99-
vue();
100-
moment();
101-
dexie();
102-
}
10388
}
10489

10590
fn jquery() {

src/error.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,30 @@ impl ::std::fmt::Display for RawError {
2727
write!(f, "{} at {}", self.msg, self.idx)
2828
}
2929
}
30+
31+
#[cfg(test)]
32+
mod tests {
33+
use super::*;
34+
35+
#[test]
36+
fn display() {
37+
assert_eq!(
38+
Error {
39+
line: 1,
40+
column: 1,
41+
msg: "err".to_string(),
42+
idx: 0,
43+
}
44+
.to_string(),
45+
"err at 1:1"
46+
);
47+
assert_eq!(
48+
RawError {
49+
msg: "err".to_string(),
50+
idx: 0,
51+
}
52+
.to_string(),
53+
"err at 0"
54+
);
55+
}
56+
}

src/lib.rs

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ impl<T> Item<T> {
141141
location,
142142
}
143143
}
144+
144145
fn new_(
145146
token: Token<T>,
146147
span_start: usize,
@@ -262,7 +263,7 @@ impl<'b> Scanner<'b> {
262263
return Some(Err(e));
263264
}
264265
};
265-
266+
debug!("get_next_token\n{:?}\n{:?}", self.last_three, next.token);
266267
let ret = if next.token.is_div_punct() && self.is_regex_start() {
267268
self.manual_scanner.next_regex(next.span.len())?
268269
} else {
@@ -454,6 +455,7 @@ impl<'b> Scanner<'b> {
454455
///
455456
/// > used in determining if we are at a regex or not
456457
fn check_for_expression(token: MetaToken) -> bool {
458+
debug!("check_for_expression {:?}", token);
457459
if Self::is_op(token) {
458460
true
459461
} else {
@@ -710,7 +712,7 @@ this.y = 0;
710712
fn validate(s: Scanner, expected: Vec<Token<&str>>) {
711713
for (i, (lhs, rhs)) in s.zip(expected.into_iter()).enumerate() {
712714
let lhs = lhs.unwrap();
713-
println!("{:?}, {:?}", lhs.token, rhs);
715+
debug!("{:?}, {:?}", lhs.token, rhs);
714716
assert_eq!((i, lhs.token), (i, rhs));
715717
}
716718
}
@@ -755,6 +757,7 @@ this.y = 0;
755757
let r = s.next().unwrap().unwrap();
756758
assert_eq!(r.token, Token::RegEx(regex));
757759
}
760+
758761
#[test]
759762
fn regex_replace() {
760763
let expect = vec![
@@ -837,6 +840,7 @@ f`;
837840
assert_eq!(format!("{}", Position::new(1, 25)), "1:25".to_string(),);
838841
assert_eq!(format!("{}", Position::new(25, 0)), "25:0".to_string(),);
839842
}
843+
840844
#[test]
841845
fn position_ord() {
842846
assert!(
@@ -933,4 +937,79 @@ ley z = 9;";
933937
let re = s.next().unwrap().unwrap();
934938
assert!(re.token.is_regex(), "regex was not a regex: {:?}", re);
935939
}
940+
941+
#[test]
942+
fn is_helpers() {
943+
assert!(!Item::new(
944+
Token::Ident(Ident::from("ident")),
945+
Span::new(0, 1),
946+
SourceLocation::new(Position::new(1, 1), Position::new(1, 2))
947+
)
948+
.is_string());
949+
assert!(Item::new(
950+
Token::String(StringLit::double("ident", false)),
951+
Span::new(0, 1),
952+
SourceLocation::new(Position::new(1, 1), Position::new(1, 2))
953+
)
954+
.is_string());
955+
assert!(!Item::new(
956+
Token::String(StringLit::double("ident", false)),
957+
Span::new(0, 1),
958+
SourceLocation::new(Position::new(1, 1), Position::new(1, 2))
959+
)
960+
.is_template());
961+
assert!(Item::new(
962+
Token::Template(Template::no_sub_template("ident", false, false, false)),
963+
Span::new(0, 1),
964+
SourceLocation::new(Position::new(1, 1), Position::new(1, 2))
965+
)
966+
.is_template());
967+
}
968+
969+
#[test]
970+
fn function_division() {
971+
let div2 = "let b = function() {} / 100;";
972+
run_regex_test(div2, false);
973+
}
974+
975+
#[test]
976+
#[ignore = "regex detection is broken... should fix that..."]
977+
fn regex() {
978+
let div1 = "let a = 0 / 1";
979+
let div2 = "let b = function() {} / 100;";
980+
let re1 = "let c = /.+/";
981+
let re2 = "let d = /asdf/g";
982+
run_regex_test(div1, false);
983+
run_regex_test(div2, false);
984+
run_regex_test(re1, true);
985+
run_regex_test(re2, true);
986+
}
987+
988+
fn run_regex_test(js: &str, should_include: bool) {
989+
for item in Scanner::new(js) {
990+
match item {
991+
Ok(item) => {
992+
if !should_include && item.token.is_regex() {
993+
let leading = item.span.start.saturating_sub(1);
994+
let region = item.span.end - item.span.start;
995+
let trailing = js.len() - (leading + region);
996+
panic!(
997+
"Unexpected regex:\n`{}`\n{}{}{}",
998+
js,
999+
" ".repeat(leading),
1000+
"^".repeat(region),
1001+
" ".repeat(trailing),
1002+
)
1003+
}
1004+
}
1005+
Err(e) => {
1006+
let mut cursor = " ".repeat(js.len());
1007+
if let Some(cursor) = unsafe { cursor.as_bytes_mut() }.get_mut(e.idx) {
1008+
*cursor = b'^';
1009+
}
1010+
panic!("Invalid JS: {}\n`{}`\n{}", e.msg, js, cursor,);
1011+
}
1012+
}
1013+
}
1014+
}
9361015
}

src/look_behind.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
use crate::tokenizer::RawKeyword;
22
use crate::tokens::Punct;
3+
use std::fmt::Debug;
34
use std::rc::Rc;
45

56
/// A 2 element buffer of
67
/// MetaTokens, this will use a
78
/// "ring buffer"-esque scheme
89
/// for automatically overwriting
910
/// any element after 2
10-
#[derive(Clone, Debug)]
11+
#[derive(Clone)]
1112
pub struct LookBehind {
1213
list: [Option<MetaToken>; 3],
1314
pointer: u8,
1415
}
1516

17+
impl Debug for LookBehind {
18+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19+
f.debug_list()
20+
.entry(self.one())
21+
.entry(self.two())
22+
.entry(self.three())
23+
.finish()
24+
}
25+
}
26+
1627
impl LookBehind {
1728
#[inline]
1829
pub const fn new() -> Self {

src/manual_scanner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ impl<'b> ManualScanner<'b> {
434434
}
435435
}
436436

437-
#[derive(Clone)]
437+
#[derive(Clone, Debug)]
438438
/// All of the important state
439439
/// for the scanner, used to
440440
/// cache and reset a `Scanner`

src/tokenizer/mod.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,7 +1559,10 @@ mod test {
15591559

15601560
#[test]
15611561
fn tokenizer_idents() {
1562-
let _ = pretty_env_logger::try_init();
1562+
pretty_env_logger::formatted_builder()
1563+
.is_test(true)
1564+
.try_init()
1565+
.ok();
15631566
static IDENTS: &[&str] = &[
15641567
r#"$"#,
15651568
r#"_"#,
@@ -1707,7 +1710,10 @@ mod test {
17071710

17081711
#[test]
17091712
fn validated_regex() {
1710-
pretty_env_logger::try_init().ok();
1713+
pretty_env_logger::formatted_builder()
1714+
.is_test(true)
1715+
.try_init()
1716+
.ok();
17111717
const REGEX: &[&str] = &[
17121718
r#"/([.+*?=^!:${}()[\]|/\\])/g"#,
17131719
r#"/[\]\}\n\s\d\e\3]/"#,
@@ -1730,7 +1736,10 @@ mod test {
17301736

17311737
#[test]
17321738
fn tokenizer_regex_term_in_class() {
1733-
pretty_env_logger::try_init().ok();
1739+
pretty_env_logger::formatted_builder()
1740+
.is_test(true)
1741+
.try_init()
1742+
.ok();
17341743
let regex = r#"/([.+*?=^!:${}()[\]|/\\])/g"#;
17351744
let mut t = Tokenizer::new(regex);
17361745
let next = t.next(true).unwrap();
@@ -1742,7 +1751,10 @@ mod test {
17421751

17431752
#[test]
17441753
fn tokenizer_regex_out_of_order() {
1745-
pretty_env_logger::try_init().ok();
1754+
pretty_env_logger::formatted_builder()
1755+
.is_test(true)
1756+
.try_init()
1757+
.ok();
17461758
let regex = r#"/((?:[^BEGHLMOSWYZabcdhmswyz']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|Y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|c{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/"#;
17471759
let mut t = Tokenizer::new(regex);
17481760
let next = t.next(true).unwrap();

0 commit comments

Comments
 (0)