1#[macro_use]
5extern crate lazy_static;
6
7mod reader;
8mod unicode;
9mod validator;
10
11pub use validator::{EcmaRegexValidator, EcmaVersion};
12
13#[cfg(test)]
14mod tests {
15 use super::*;
16
17 #[test]
18 fn valid_flags() {
19 let validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
20 assert_eq!(validator.validate_flags("gimuys"), Ok(()));
21 assert_eq!(validator.validate_flags("gimuy"), Ok(()));
22 assert_eq!(validator.validate_flags("gim"), Ok(()));
23 assert_eq!(validator.validate_flags("g"), Ok(()));
24 assert_eq!(validator.validate_flags("i"), Ok(()));
25 assert_eq!(validator.validate_flags("m"), Ok(()));
26 assert_eq!(validator.validate_flags("s"), Ok(()));
27 assert_eq!(validator.validate_flags("u"), Ok(()));
28 assert_eq!(validator.validate_flags("y"), Ok(()));
29
30 assert_eq!(validator.validate_flags("gy"), Ok(()));
31 assert_eq!(validator.validate_flags("iy"), Ok(()));
32 assert_eq!(validator.validate_flags("my"), Ok(()));
33 assert_eq!(validator.validate_flags("uy"), Ok(()));
34 }
35
36 #[test]
37 fn duplicate_flags() {
38 let validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
39 assert_eq!(validator.validate_flags("gimgu"), Err("Duplicated flag g".to_string()));
40 assert_eq!(validator.validate_flags("migg"), Err("Duplicated flag g".to_string()));
41 assert_eq!(validator.validate_flags("igi"), Err("Duplicated flag i".to_string()));
42
43 assert_eq!(validator.validate_flags("ii"), Err("Duplicated flag i".to_string()));
44 assert_eq!(validator.validate_flags("mm"), Err("Duplicated flag m".to_string()));
45 assert_eq!(validator.validate_flags("ss"), Err("Duplicated flag s".to_string()));
46 assert_eq!(validator.validate_flags("uu"), Err("Duplicated flag u".to_string()));
47 assert_eq!(validator.validate_flags("yy"), Err("Duplicated flag y".to_string()));
48 }
49
50 #[test]
51 fn invalid_flags() {
52 let validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
53 assert_eq!(validator.validate_flags("gimuf"), Err("Invalid flag f".to_string()));
54 assert_eq!(validator.validate_flags("gI"), Err("Invalid flag I".to_string()));
55 assert_eq!(validator.validate_flags("a"), Err("Invalid flag a".to_string()));
56 assert_eq!(validator.validate_flags("1"), Err("Invalid flag 1".to_string()));
57 }
58
59 #[test]
60 fn validate_pattern_test() {
61 let mut validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
62 assert_eq!(validator.validate_pattern("", false), Ok(()));
63 assert_eq!(validator.validate_pattern("[abc]de|fg", false), Ok(()));
64 assert_eq!(validator.validate_pattern("[abc]de|fg", true), Ok(()));
65 assert_eq!(validator.validate_pattern("^.$", false), Ok(()));
66 assert_eq!(validator.validate_pattern("^.$", true), Ok(()));
67 assert_eq!(validator.validate_pattern("foo\\[bar", false), Ok(()));
68 assert_eq!(validator.validate_pattern("foo\\[bar", true), Ok(()));
69 assert_eq!(validator.validate_pattern("\\w+\\s", false), Ok(()));
70 assert_eq!(validator.validate_pattern("(\\w+), (\\w+)", false), Ok(()));
71 assert_eq!(validator.validate_pattern("\\/\\/.*|\\/\\*[^]*\\*\\/", false), Ok(()));
72 assert_eq!(validator.validate_pattern("(\\d{1,2})-(\\d{1,2})-(\\d{4})", false), Ok(()));
73 assert_eq!(validator.validate_pattern("(?:\\d{3}|\\(\\d{3}\\))([-\\/\\.])\\d{3}\\1\\d{4}", false), Ok(()));
74 assert_eq!(validator.validate_pattern("https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)", false), Ok(()));
75
76 assert_eq!(validator.validate_pattern("\\p{Script=Greek}", true), Ok(()));
77 assert_eq!(validator.validate_pattern("\\p{Alphabetic}", true), Ok(()));
78
79 assert_ne!(validator.validate_pattern("\\", false), Ok(()));
80 assert_ne!(validator.validate_pattern("a**", false), Ok(()));
81 assert_ne!(validator.validate_pattern("++a", false), Ok(()));
82 assert_ne!(validator.validate_pattern("?a", false), Ok(()));
83 assert_ne!(validator.validate_pattern("a***", false), Ok(()));
84 assert_ne!(validator.validate_pattern("a++", false), Ok(()));
85 assert_ne!(validator.validate_pattern("a+++", false), Ok(()));
86 assert_ne!(validator.validate_pattern("a???", false), Ok(()));
87 assert_ne!(validator.validate_pattern("a????", false), Ok(()));
88 assert_ne!(validator.validate_pattern("*a", false), Ok(()));
89 assert_ne!(validator.validate_pattern("**a", false), Ok(()));
90 assert_ne!(validator.validate_pattern("+a", false), Ok(()));
91 assert_ne!(validator.validate_pattern("[{-z]", false), Ok(()));
92 assert_ne!(validator.validate_pattern("[a--z]", false), Ok(()));
93
94 assert_ne!(validator.validate_pattern("0{2,1}", false), Ok(()));
95 assert_ne!(validator.validate_pattern("x{1}{1,}", false), Ok(()));
96 assert_ne!(validator.validate_pattern("x{1,2}{1}", false), Ok(()));
97 assert_ne!(validator.validate_pattern("x{1,}{1}", false), Ok(()));
98 assert_ne!(validator.validate_pattern("x{0,1}{1,}", false), Ok(()));
99
100 assert_ne!(validator.validate_pattern("\\1(\\P{P\0[}()/", true), Ok(()));
101 }
102
103 #[test]
104 fn character_range_order() {
105 let mut validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
106 assert_ne!(validator.validate_pattern("^[z-a]$", false), Ok(()));
107 assert_ne!(validator.validate_pattern("[b-ac-e]", false), Ok(()));
108 assert_ne!(validator.validate_pattern("[c-eb-a]", false), Ok(()));
109 assert_ne!(validator.validate_pattern("[a-dc-b]", false), Ok(()));
110
111 assert_ne!(validator.validate_pattern("[\\10b-G]", false), Ok(()));
112 assert_ne!(validator.validate_pattern("[\\ad-G]", false), Ok(()));
113 assert_ne!(validator.validate_pattern("[\\bd-G]", false), Ok(()));
114 assert_ne!(validator.validate_pattern("[\\Bd-G]", false), Ok(()));
115 assert_ne!(validator.validate_pattern("[\\db-G]", false), Ok(()));
116 assert_ne!(validator.validate_pattern("[\\Db-G]", false), Ok(()));
117 assert_ne!(validator.validate_pattern("[\\sb-G]", false), Ok(()));
118 assert_ne!(validator.validate_pattern("[\\Sb-G]", false), Ok(()));
119 assert_ne!(validator.validate_pattern("[\\wb-G]", false), Ok(()));
120 assert_ne!(validator.validate_pattern("[\\Wb-G]", false), Ok(()));
121 assert_ne!(validator.validate_pattern("[\\0b-G]", false), Ok(()));
122 assert_ne!(validator.validate_pattern("[\\td-G]", false), Ok(()));
123 assert_ne!(validator.validate_pattern("[\\nd-G]", false), Ok(()));
124 assert_ne!(validator.validate_pattern("[\\vd-G]", false), Ok(()));
125 assert_ne!(validator.validate_pattern("[\\fd-G]", false), Ok(()));
126 assert_ne!(validator.validate_pattern("[\\rd-G]", false), Ok(()));
127 assert_ne!(validator.validate_pattern("[\\c0001d-G]", false), Ok(()));
128 assert_ne!(validator.validate_pattern("[\\x0061d-G]", false), Ok(()));
129 assert_ne!(validator.validate_pattern("[\\u0061d-G]", false), Ok(()));
130
131 assert_ne!(validator.validate_pattern("[b-G\\10]", false), Ok(()));
132 assert_ne!(validator.validate_pattern("[d-G\\a]", false), Ok(()));
133 assert_ne!(validator.validate_pattern("[d-G\\b]", false), Ok(()));
134 assert_ne!(validator.validate_pattern("[d-G\\B]", false), Ok(()));
135 assert_ne!(validator.validate_pattern("[b-G\\d]", false), Ok(()));
136 assert_ne!(validator.validate_pattern("[b-G\\D]", false), Ok(()));
137 assert_ne!(validator.validate_pattern("[b-G\\s]", false), Ok(()));
138 assert_ne!(validator.validate_pattern("[b-G\\S]", false), Ok(()));
139 assert_ne!(validator.validate_pattern("[b-G\\w]", false), Ok(()));
140 assert_ne!(validator.validate_pattern("[b-G\\W]", false), Ok(()));
141 assert_ne!(validator.validate_pattern("[b-G\\0]", false), Ok(()));
142 assert_ne!(validator.validate_pattern("[d-G\\t]", false), Ok(()));
143 assert_ne!(validator.validate_pattern("[d-G\\n]", false), Ok(()));
144 assert_ne!(validator.validate_pattern("[d-G\\v]", false), Ok(()));
145 assert_ne!(validator.validate_pattern("[d-G\\f]", false), Ok(()));
146 assert_ne!(validator.validate_pattern("[d-G\\r]", false), Ok(()));
147 assert_ne!(validator.validate_pattern("[d-G\\c0001]", false), Ok(()));
148 assert_ne!(validator.validate_pattern("[d-G\\x0061]", false), Ok(()));
149 assert_ne!(validator.validate_pattern("[d-G\\u0061]", false), Ok(()));
150 }
151
152 #[test]
153 fn unicode_quantifier_without_atom() {
154 let mut validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
155 assert_ne!(validator.validate_pattern("*", true), Ok(()));
156 assert_ne!(validator.validate_pattern("+", true), Ok(()));
157 assert_ne!(validator.validate_pattern("?", true), Ok(()));
158 assert_ne!(validator.validate_pattern("{1}", true), Ok(()));
159 assert_ne!(validator.validate_pattern("{1,}", true), Ok(()));
160 assert_ne!(validator.validate_pattern("{1,2}", true), Ok(()));
161
162 assert_ne!(validator.validate_pattern("*?", true), Ok(()));
163 assert_ne!(validator.validate_pattern("+?", true), Ok(()));
164 assert_ne!(validator.validate_pattern("??", true), Ok(()));
165 assert_ne!(validator.validate_pattern("{1}?", true), Ok(()));
166 assert_ne!(validator.validate_pattern("{1,}?", true), Ok(()));
167 assert_ne!(validator.validate_pattern("{1,2}?", true), Ok(()));
168 }
169
170 #[test]
171 fn unicode_incomplete_quantifier() {
172 let mut validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
173 assert_ne!(validator.validate_pattern("a{", true), Ok(()));
174 assert_ne!(validator.validate_pattern("a{1", true), Ok(()));
175 assert_ne!(validator.validate_pattern("a{1,", true), Ok(()));
176 assert_ne!(validator.validate_pattern("a{1,2", true), Ok(()));
177
178 assert_ne!(validator.validate_pattern("{", true), Ok(()));
179 assert_ne!(validator.validate_pattern("{1", true), Ok(()));
180 assert_ne!(validator.validate_pattern("{1,", true), Ok(()));
181 assert_ne!(validator.validate_pattern("{1,2", true), Ok(()));
182 }
183
184 #[test]
185 fn unicode_single_bracket() {
186 let mut validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
187 assert_ne!(validator.validate_pattern("(", true), Ok(()));
188 assert_ne!(validator.validate_pattern(")", true), Ok(()));
189 assert_ne!(validator.validate_pattern("[", true), Ok(()));
190 assert_ne!(validator.validate_pattern("]", true), Ok(()));
191 assert_ne!(validator.validate_pattern("{", true), Ok(()));
192 assert_ne!(validator.validate_pattern("}", true), Ok(()));
193 }
194
195 #[test]
196 fn unicode_escapes() {
197 let mut validator = EcmaRegexValidator::new(EcmaVersion::ES2018);
198 assert_eq!(validator.validate_pattern("\\u{10ffff}", true), Ok(()));
199 assert_ne!(validator.validate_pattern("\\u{110000}", true), Ok(()));
200 assert_eq!(validator.validate_pattern("\\u{110000}", false), Ok(()));
201 assert_eq!(validator.validate_pattern("foo\\ud803\\ude6dbar", true), Ok(()));
202 assert_eq!(validator.validate_pattern("(\u{12345}|\u{23456}).\\1", true), Ok(()));
203 assert_eq!(validator.validate_pattern("\u{12345}{3}", true), Ok(()));
204
205 assert_eq!(validator.validate_pattern("[\\u0062-\\u0066]oo", false), Ok(()));
207 assert_eq!(validator.validate_pattern("[\\u0062-\\u0066]oo", true), Ok(()));
208 assert_eq!(validator.validate_pattern("[\\u{0062}-\\u{0066}]oo", true), Ok(()));
209 assert_eq!(validator.validate_pattern("[\\u{62}-\\u{00000066}]oo", true), Ok(()));
210
211 assert_eq!(validator.validate_pattern("first\\u\\x\\z\\8\\9second", false), Ok(()));
213 assert_eq!(validator.validate_pattern("[\\u\\x\\z\\8\\9]", false), Ok(()));
214 assert_ne!(validator.validate_pattern("/\\u/u", true), Ok(()));
215 assert_ne!(validator.validate_pattern("/\\u12/u", true), Ok(()));
216 assert_ne!(validator.validate_pattern("/\\ufoo/u", true), Ok(()));
217 assert_ne!(validator.validate_pattern("/\\x/u", true), Ok(()));
218 assert_ne!(validator.validate_pattern("/\\xfoo/u", true), Ok(()));
219 assert_ne!(validator.validate_pattern("/\\z/u", true), Ok(()));
220 assert_ne!(validator.validate_pattern("/\\8/u", true), Ok(()));
221 assert_ne!(validator.validate_pattern("/\\9/u", true), Ok(()));
222 }
223}