runtestdata/
runtestdata.rs

1// Copyright 2016 The xi-editor Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Run line break test data.
16
17// Run on:
18// http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/LineBreakTest.txt
19// or use randomized data from tools/gen_rand_icu.cc (same format)
20extern crate xi_unicode;
21
22use xi_unicode::{LineBreakIterator, LineBreakLeafIter};
23
24use std::fs::File;
25use std::io::prelude::*;
26use std::io::BufReader;
27
28fn quote_str(s: &str) -> String {
29    let mut result = String::new();
30    for c in s.chars() {
31        if c == '"' || c == '\\' {
32            result.push('\\');
33        }
34        if ' ' <= c && c <= '~' {
35            result.push(c);
36        } else {
37            result.push_str(&format!("\\u{{{:04x}}}", c as u32));
38        }
39    }
40    result
41}
42
43fn check_breaks(s: &str, breaks: &[usize]) -> bool {
44    let my_breaks = LineBreakIterator::new(s).map(|(bk, _hard)| bk).collect::<Vec<_>>();
45    if my_breaks != breaks {
46        println!("failed case: \"{}\"", quote_str(s));
47        println!("expected {:?} actual {:?}", breaks, my_breaks);
48        return false;
49    }
50    true
51}
52
53// Verify that starting iteration at a break is insensitive to look-behind.
54fn check_lb(s: &str) -> bool {
55    let breaks = LineBreakIterator::new(s).collect::<Vec<_>>();
56    for i in 0..breaks.len() - 1 {
57        let mut cursor = LineBreakLeafIter::new(s, breaks[i].0);
58        for &bk in &breaks[i + 1..] {
59            let mut next = cursor.next(s);
60            if next.0 == s.len() {
61                next = (s.len(), true);
62            }
63            if next != bk {
64                println!("failed case: \"{}\"", quote_str(s));
65                println!("expected {:?} actual {:?}", bk, next);
66                return false;
67            }
68        }
69    }
70    true
71}
72
73fn run_test(filename: &str, lb: bool) -> std::io::Result<()> {
74    let f = File::open(filename)?;
75    let mut reader = BufReader::new(f);
76    let mut pass = 0;
77    let mut total = 0;
78    loop {
79        let mut line = String::new();
80        if reader.read_line(&mut line)? == 0 {
81            break;
82        };
83        let mut s = String::new();
84        let mut breaks = Vec::new();
85        for token in line.split_whitespace() {
86            if token == "÷" {
87                breaks.push(s.len());
88            } else if token == "×" {
89            } else if token == "#" {
90                break;
91            } else if let Ok(cp) = u32::from_str_radix(token, 16) {
92                s.push(std::char::from_u32(cp).unwrap());
93            }
94        }
95        total += 1;
96        if lb {
97            if check_lb(&s) {
98                pass += 1;
99            }
100        } else {
101            if check_breaks(&s, &breaks) {
102                pass += 1;
103            }
104        }
105    }
106    println!("{}/{} pass", pass, total);
107    Ok(())
108}
109
110fn main() {
111    let mut args = std::env::args();
112    let _ = args.next();
113    let filename = args.next().unwrap();
114    match args.next() {
115        None => {
116            let _ = run_test(&filename, false);
117        }
118        Some(ref s) if s == "--lookbehind" => {
119            let _ = run_test(&filename, true);
120        }
121        _ => {
122            println!("unknown argument");
123        }
124    }
125}