1aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
4aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/**
5aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
6aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Copyright (C) 2005-2015, International Business Machines Corporation and
7aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * others. All Rights Reserved.
8aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
9aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
10aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpackage android.icu.dev.test.charsetdet;
11aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
12aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.ByteArrayInputStream;
13aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.ByteArrayOutputStream;
14aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.InputStream;
15aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.Reader;
16aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.io.UnsupportedEncodingException;
17aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.HashSet;
18aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Map;
19aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.TreeMap;
20aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
21aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport javax.xml.parsers.DocumentBuilder;
22aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport javax.xml.parsers.DocumentBuilderFactory;
23aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
24f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport org.junit.Test;
25aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport org.w3c.dom.Document;
26aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport org.w3c.dom.Element;
27aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport org.w3c.dom.NamedNodeMap;
28aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport org.w3c.dom.Node;
29aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport org.w3c.dom.NodeList;
30aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
31aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.test.TestFmwk;
32aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.test.TestUtil;
33aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.dev.test.TestUtil.JavaVendor;
34aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.impl.Utility;
35aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.CharsetDetector;
36aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.text.CharsetMatch;
37aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
38aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
39aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/**
40aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * @author andy
41aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
42aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpublic class TestCharsetDetector extends TestFmwk
43aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin{
44aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public TestCharsetDetector()
45aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
46aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
47aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
48aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private void CheckAssert(boolean exp) {
49aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (exp == false) {
50aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String msg;
51aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            try {
52aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                throw new Exception();
53aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
54aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            catch (Exception e) {
55aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                StackTraceElement failPoint = e.getStackTrace()[1];
56aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                msg = "Test failure in file " + failPoint.getFileName() +
57aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                             " at line " + failPoint.getLineNumber();
58aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
59aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln(msg);
60aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
61aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
62aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
63aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
64aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private String stringFromReader(Reader reader)
65aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
66aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer sb = new StringBuffer();
67aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        char[] buffer   = new char[1024];
68aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int bytesRead   = 0;
69aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
70aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
71aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            while ((bytesRead = reader.read(buffer, 0, 1024)) >= 0) {
72aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                sb.append(buffer, 0, bytesRead);
73aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
74aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
75aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return sb.toString();
76aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } catch (Exception e) {
77aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("stringFromReader() failed: " + e.toString());
78aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return null;
79aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
80aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
81aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
82f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
83aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestConstruction() {
84aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int i;
85aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector  det = new CharsetDetector();
86aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if(det==null){
87aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Could not construct a charset detector");
88aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
89aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String [] charsetNames = CharsetDetector.getAllDetectableCharsets();
90aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(charsetNames.length != 0);
91aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (i=0; i<charsetNames.length; i++) {
92aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(charsetNames[i].equals("") == false);
93aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // System.out.println("\"" + charsetNames[i] + "\"");
94aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
95aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
96aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        final String[] defDisabled = {
97aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "IBM420_rtl", "IBM420_ltr",
98aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "IBM424_rtl", "IBM424_ltr"
99aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        };
100aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String[] activeCharsetNames = det.getDetectableCharsets();
101aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (String cs : activeCharsetNames) {
102aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // the charset must be included in all list
103aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean found = false;
104aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (String cs0 : charsetNames) {
105aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (cs0.equals(cs)) {
106aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    found = true;
107aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
108aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
109aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
110aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (!found) {
111aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln(cs + " is not included in the all charset list." );
112aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
113aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
114aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // some charsets are disabled by default
115aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            found = false;
116aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (String cs1 : defDisabled) {
117aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (cs1.equals(cs)) {
118aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    found = true;
119aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    break;
120aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
121aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
122aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (found) {
123aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln(cs + " should not be included in the default charset list.");
124aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
125aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
126aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
127aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
128f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
129aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestInputFilter() throws Exception
130aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
131aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String s = "<a> <lot> <of> <English> <inside> <the> <markup> Un tr\u00E8s petit peu de Fran\u00E7ais. <to> <confuse> <the> <detector>";
132aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] bytes = s.getBytes("ISO-8859-1");
133aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
134aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m;
135aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
136aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.enableInputFilter(true);
137aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!det.inputFilterEnabled()){
138aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("input filter should be enabled");
139aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
140aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
141aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bytes);
142aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = det.detect();
143aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
144aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (! m.getLanguage().equals("fr")) {
145aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("input filter did not strip markup!");
146aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
147aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
148aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.enableInputFilter(false);
149aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bytes);
150aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = det.detect();
151aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
152aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (! m.getLanguage().equals("en")) {
153aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("unfiltered input did not detect as English!");
154aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
155aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
156aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
157f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
158aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestUTF8() throws Exception {
159aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
160aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String  s = "This is a string with some non-ascii characters that will " +
161aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    "be converted to UTF-8, then shoved through the detection process.  " +
162aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    "\u0391\u0392\u0393\u0394\u0395" +
163aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    "Sure would be nice if our source could contain Unicode directly!";
164aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte [] bytes = s.getBytes("UTF-8");
165aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
166aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String retrievedS;
167aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Reader reader;
168aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
169aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        retrievedS = det.getString(bytes, "UTF-8");
170aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(s.equals(retrievedS));
171aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
172aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        reader = det.getReader(new ByteArrayInputStream(bytes), "UTF-8");
173aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
174aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(s.equals(stringFromReader(reader)));
175aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } finally {
176aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            reader.close();
177aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
178aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDeclaredEncoding("UTF-8"); // Jitterbug 4451, for coverage
179aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
180aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
181f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
182aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestUTF16() throws Exception
183aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
184aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String source =
185aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                "u0623\u0648\u0631\u0648\u0628\u0627, \u0628\u0631\u0645\u062c\u064a\u0627\u062a " +
186aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                "\u0627\u0644\u062d\u0627\u0633\u0648\u0628 \u002b\u0020\u0627\u0646\u062a\u0631\u0646\u064a\u062a";
187aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
188aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] beBytes = source.getBytes("UnicodeBig");
189aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] leBytes = source.getBytes("UnicodeLittle");
190aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
191aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m;
192aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
193aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(beBytes);
194aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = det.detect();
195aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
196aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (! m.getName().equals("UTF-16BE")) {
197aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Encoding detection failure: expected UTF-16BE, got " + m.getName());
198aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
199aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
200aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(leBytes);
201aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = det.detect();
202aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
203aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (! m.getName().equals("UTF-16LE")) {
204aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Encoding detection failure: expected UTF-16LE, got " + m.getName());
205aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
206aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
207aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Jitterbug 4451, for coverage
208aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int confidence = m.getConfidence();
209aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if(confidence != 100){
210aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Did not get the expected confidence level " + confidence);
211aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
212aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
213aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
214f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
215aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestC1Bytes() throws Exception
216aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
217aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String sISO =
218aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "This is a small sample of some English text. Just enough to be sure that it detects correctly.";
219aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
220aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String sWindows =
221aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "This is another small sample of some English text. Just enough to be sure that it detects correctly. It also includes some \u201CC1\u201D bytes.";
222aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
223aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] bISO     = sISO.getBytes("ISO-8859-1");
224aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] bWindows = sWindows.getBytes("windows-1252");
225aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
226aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
227aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m;
228aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
229aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bWindows);
230aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = det.detect();
231aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
232aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!m.getName().equals("windows-1252")) {
233aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Text with C1 bytes not correctly detected as windows-1252.");
234aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return;
235aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
236aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
237aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bISO);
238aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = det.detect();
239aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
240aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!m.getName().equals("ISO-8859-1")) {
241aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Text without C1 bytes not correctly detected as ISO-8859-1.");
242aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
243aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
244aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
245f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
246aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestShortInput() {
247aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Test that detection with very short byte strings does not crash and burn.
248aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // The shortest input that should produce positive detection result is two bytes,
249aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //   a UTF-16 BOM.
250aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // TODO:  Detector confidence levels needs to be refined for very short input.
251aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //        Too high now, for some charsets that happen to be compatible with a few bytes of input.
252aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte [][]  shortBytes = new byte [][]
253aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {
254aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {},
255aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {(byte)0x0a},
256aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {(byte)'A', (byte)'B'},
257aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {(byte)'A', (byte)'B', (byte)'C'},
258aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                {(byte)'A', (byte)'B', (byte)'C', (byte)'D'}
259aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            };
260aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
261aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
262aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m;
263aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i=0; i<shortBytes.length; i++) {
264aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(shortBytes[i]);
265aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            m = det.detect();
266aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            logln("i=" + i + " -> " + m.getName());
267aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
268aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
269aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
270f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
271aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestBufferOverflow()
272aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
273aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte testStrings[][] = {
274aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0x80, (byte) 0x20, (byte) 0x54, (byte) 0x68, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x45, (byte) 0x6E, (byte) 0x67, (byte) 0x6C, (byte) 0x69, (byte) 0x73, (byte) 0x68, (byte) 0x20, (byte) 0x1b}, /* A partial ISO-2022 shift state at the end */
275aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0x80, (byte) 0x20, (byte) 0x54, (byte) 0x68, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x45, (byte) 0x6E, (byte) 0x67, (byte) 0x6C, (byte) 0x69, (byte) 0x73, (byte) 0x68, (byte) 0x20, (byte) 0x1b, (byte) 0x24}, /* A partial ISO-2022 shift state at the end */
276aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0x80, (byte) 0x20, (byte) 0x54, (byte) 0x68, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x45, (byte) 0x6E, (byte) 0x67, (byte) 0x6C, (byte) 0x69, (byte) 0x73, (byte) 0x68, (byte) 0x20, (byte) 0x1b, (byte) 0x24, (byte) 0x28}, /* A partial ISO-2022 shift state at the end */
277aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0x80, (byte) 0x20, (byte) 0x54, (byte) 0x68, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73, (byte) 0x20, (byte) 0x45, (byte) 0x6E, (byte) 0x67, (byte) 0x6C, (byte) 0x69, (byte) 0x73, (byte) 0x68, (byte) 0x20, (byte) 0x1b, (byte) 0x24, (byte) 0x28, (byte) 0x44}, /* A complete ISO-2022 shift state at the end with a bad one at the start */
278aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0x1b, (byte) 0x24, (byte) 0x28, (byte) 0x44}, /* A complete ISO-2022 shift state at the end */
279aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0xa1}, /* Could be a single byte shift-jis at the end */
280aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0x74, (byte) 0x68, (byte) 0xa1}, /* Could be a single byte shift-jis at the end */
281aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            {(byte) 0x74, (byte) 0x68, (byte) 0x65, (byte) 0xa1} /* Could be a single byte shift-jis at the end, but now we have English creeping in. */
282aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        };
283aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
284aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String testResults[] = {
285aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "windows-1252",
286aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "windows-1252",
287aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "windows-1252",
288aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "windows-1252",
289aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "ISO-2022-JP",
290aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            null,
291aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            null,
292aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "ISO-8859-1"
293aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        };
294aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
295aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
296aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch match;
297aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
298aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDeclaredEncoding("ISO-2022-JP");
299aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
300aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int idx = 0; idx < testStrings.length; idx += 1) {
301aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(testStrings[idx]);
302aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            match = det.detect();
303aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
304aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (match == null) {
305aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if (testResults[idx] != null) {
306aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    errln("Unexpectedly got no results at index " + idx);
307aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
308aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                else {
309aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    logln("Got no result as expected at index " + idx);
310aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
311aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                continue;
312aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
313aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
314aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (testResults[idx] == null || ! testResults[idx].equals(match.getName())) {
315aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln("Unexpectedly got " + match.getName() + " instead of " + testResults[idx] +
316aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                      " at index " + idx + " with confidence " + match.getConfidence());
317aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return;
318aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
319aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
320aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
321aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
322f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
323aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestDetection()
324aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    {
325aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //
326aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //  Open and read the test data file.
327aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //
328aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //InputStreamReader isr = null;
329aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
330aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
331aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            InputStream is = TestCharsetDetector.class.getResourceAsStream("CharsetDetectionTests.xml");
332aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (is == null) {
333aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln("Could not open test data file CharsetDetectionTests.xml");
334aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return;
335aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
336aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
337aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // Set up an xml parser.
338aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
339aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
340aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            factory.setIgnoringComments(true);
341aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
342aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            DocumentBuilder builder = factory.newDocumentBuilder();
343aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
344aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // Parse the xml content from the test case file.
345aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Document doc;
346aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            try {
347aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                doc = builder.parse(is, null);
348aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } finally {
349aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                is.close();
350aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
351aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Element root = doc.getDocumentElement();
352aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
353aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            NodeList testCases = root.getElementsByTagName("test-case");
354aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
355aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // Process each test case
356aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Map<String, byte[]> encToBytes = new TreeMap<String, byte[]>();
357aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int n = 0; n < testCases.getLength(); n += 1) {
358aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                Node testCase = testCases.item(n);
359aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                NamedNodeMap attrs = testCase.getAttributes();
360aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                NodeList testData  = testCase.getChildNodes();
361aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                StringBuffer testText = new StringBuffer();
362aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String id = attrs.getNamedItem("id").getNodeValue();
363aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String encodings = attrs.getNamedItem("encodings").getNodeValue();
364aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
365aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // Collect the test case text and optional bytes.
366aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // A <bytes encoding="name">ASCII with \xhh</bytes> element
367aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // specifies the byte sequence to be tested.
368aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // This is useful when not all platforms encode the test text the same way
369aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // (or do not support encoding for that charset).
370aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (int t = 0; t < testData.getLength(); t += 1) {
371aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    Node node = testData.item(t);
372aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (node.getNodeType() == Node.TEXT_NODE) {
373aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        testText.append(node.getNodeValue());
374aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    } else if (node.getNodeType() == Node.ELEMENT_NODE &&
375aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            node.getNodeName().equals("bytes")) {
376aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        String name = node.getAttributes().getNamedItem("encoding").getNodeValue();
377aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        Node valueNode = node.getFirstChild();
378aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        if (valueNode.getNodeType() != Node.TEXT_NODE) {
379aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            throw new IllegalArgumentException("<bytes> node does not contain text");
380aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        }
381aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        // The bytes are stored as ASCII characters and \xhh escaped bytes.
382aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        // We unescape the string to turn the \xhh into chars U+0000..U+00ff,
383aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        // then use the deprecated String.getBytes() to turn those into bytes
384aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        // by essentially casting each char to a byte.
385aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        String bytesString = Utility.unescape(valueNode.getNodeValue());
386aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        byte[] bytes = new byte[bytesString.length()];
387aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        bytesString.getBytes(0, bytesString.length(), bytes, 0);
388aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        encToBytes.put(name, bytes);
389aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    } else {
390aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        throw new IllegalArgumentException("unknown <test-case> child node: " + node);
391aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
392aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
393aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
394aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // Process test text with each encoding / language pair.
395aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String testString = testText.toString();
396aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String[] encodingList = encodings.split(" ");
397aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (int e = 0; e < encodingList.length; e += 1) {
398aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    String[] params = encodingList[e].split("/");
399aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    String encoding = params[0];
400aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    String language = params.length == 1 || params[1].length() == 0 ? null : params[1];
401aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
402aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    // With a few charsets, the conversion back to Unicode
403aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    // may depend on the implementation.
404aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    boolean checkRoundtrip =
405aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            !encoding.startsWith("UTF-32") &&
406aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            !(params.length >= 3 && params[2].equals("noroundtrip"));
407aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    checkEncoding(testString, encoding, language, checkRoundtrip,
408aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                            encToBytes.get(encoding), id);
409aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
410aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                encToBytes.clear();
411aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
412aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
413aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } catch (Exception e) {
414aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("exception while processing test cases: " + e.toString());
415aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
416aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
417aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
418aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private void checkMatch(CharsetDetector det, String testString,
419aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String encoding, String language, boolean checkRoundtrip, String id) throws Exception {
420aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m = det.detect();
421aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (! m.getName().equals(encoding)) {
422aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln(id + ": encoding detection failure - expected " + encoding + ", got " + m.getName());
423aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return;
424aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
425aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
426aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String charsetMatchLanguage = m.getLanguage();
427aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if ((language != null && !charsetMatchLanguage.equals(language))
428aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            || (language == null && charsetMatchLanguage != null)
429aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            || (language != null && charsetMatchLanguage == null))
430aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
431aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln(id + ", " + encoding + ": language detection failure - expected " + language + ", got " + m.getLanguage());
432aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
433aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
434aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!checkRoundtrip) {
435aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return;
436aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
437aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
438aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // TODO temporary workaround for IBM Java 8 ISO-2022-KR problem
439aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (encoding.equals("ISO-2022-KR") && TestUtil.getJavaVendor() == JavaVendor.IBM && TestUtil.getJavaVersion() == 8) {
440aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            logln("Skipping roundtrip check on IBM Java 8: " + id + ", " + encoding);
441aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return;
442aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
443aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
444aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String decoded = m.getString();
445aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
446aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (! testString.equals(decoded)) {
447aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln(id + ", " + encoding + ": getString() didn't return the original string!");
448aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
449aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
450aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        decoded = stringFromReader(m.getReader());
451aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
452aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (! testString.equals(decoded)) {
453aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln(id + ", " + encoding + ": getReader() didn't yield the original string!");
454aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
455aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
456aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
457aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private void checkEncoding(String testString,
458aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String encoding, String language, boolean checkRoundtrip,
459aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            byte[] bytes, String id) {
460aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (bytes == null) {
461aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            try {
462aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                bytes = testString.getBytes(encoding);
463aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } catch (UnsupportedOperationException uoe) {
464aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // Ignore any converters that can't
465aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // convert from Unicode.
466aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln("Unsupported encoding for conversion from Unicode: " + encoding);
467aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return;
468aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } catch (UnsupportedEncodingException uee) {
469aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // Ignore any encodings that this runtime
470aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // doesn't support.
471aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln("Unsupported encoding: " + encoding);
472aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return;
473aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
474aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
475aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
476aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
477aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CharsetDetector det = new CharsetDetector();
478aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
479aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(bytes);
480aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            checkMatch(det, testString, encoding, language, checkRoundtrip, id);
481aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
482aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(new ByteArrayInputStream(bytes));
483aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            checkMatch(det, testString, encoding, language, checkRoundtrip, id);
484aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin         } catch (Exception e) {
485aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln(id + ": " + e.toString() + "enc=" + encoding);
486aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            e.printStackTrace();
487aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
488aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
489aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
490f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
491aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestJapanese() throws Exception {
492aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String s = "\u3000\u3001\u3002\u3003\u3005\u3006\u3007\u3008\u3009\u300A\u300B\u300C\u300D\u300E\u300F\u3010\u3011\u3012\u3013\u3014" +
493aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u3015\u301C\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048\u3049\u304A\u304B\u304C\u304D\u304E\u304F\u3050\u3051\u3052" +
494aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u3053\u3054\u3055\u3056\u3057\u3058\u3059\u305A\u305B\u305C\u305D\u305E\u305F\u3060\u3061\u3062\u3063\u3064\u3065\u3066" +
495aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u3067\u3068\u3069\u306A\u306B\u306C\u306D\u306E\u306F\u3070\u3071\u3072\u3073\u3074\u3075\u3076\u3077\u3078\u3079\u307A" +
496aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u307B\u307C\u307D\u307E\u307F\u3080\u3081\u3082\u3083\u3084\u3085\u3086\u3087\u3088\u3089\u308A\u308B\u308C\u308D\u308E" +
497aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u308F\u3090\u3091\u3092\u3093\u309B\u309C\u309D\u309E\u30A1\u30A2\u30A3\u30A4\u30A5\u30A6\u30A7\u30A8\u30A9\u30AA\u30AB" +
498aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u30AC\u30AD\u30AE\u30AF\u30B0\u30B1\u30B2\u30B3\u30B4\u30B5\u30B6\u30B7\u30B8\u30B9\u30BA\u30BB\u30BC\u30BD\u30BE\u30BF" +
499aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u30C0\u30C1\u30C2\u30C3\u30C4\u30C5\u30C6\u30C7\u30C8\u30C9\u30CA\u30CB\u30CC\u30CD\u30CE\u30CF\u30D0\u30D1\u30D2\u30D3" +
500aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u30D4\u30D5\u30D6\u30D7\u30D8\u30D9\u30DA\u30DB\u30DC\u30DD\u30DE\u30DF\u30E0\u30E1\u30E2\u30E3\u30E4\u30E5\u30E6\u30E7" +
501aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u30E8\u30E9\u30EA\u30EB\u30EC\u30ED\u30EE\u30EF\u30F0\u30F1\u30F2\u30F3\u30F4\u30F5\u30F6\u30FB\u30FC\u30FD\u30FE\u4E00" +
502aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4E01\u4E02\u4E03\u4E04\u4E05\u4E07\u4E08\u4E09\u4E0A\u4E0B\u4E0C\u4E0D\u4E0E\u4E10\u4E11\u4E12\u4E14\u4E15\u4E16\u4E17" +
503aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4E18\u4E19\u4E1E\u4E1F\u4E21\u4E23\u4E24\u4E26\u4E28\u4E2A\u4E2B\u4E2D\u4E2E\u4E2F\u4E30\u4E31\u4E32\u4E35\u4E36\u4E38" +
504aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4E39\u4E3B\u4E3C\u4E3F\u4E40\u4E41\u4E42\u4E43\u4E44\u4E45\u4E47\u4E4B\u4E4D\u4E4E\u4E4F\u4E51\u4E55\u4E56\u4E57\u4E58" +
505aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4E59\u4E5A\u4E5C\u4E5D\u4E5E\u4E5F\u4E62\u4E63\u4E68\u4E69\u4E71\u4E73\u4E74\u4E75\u4E79\u4E7E\u4E7F\u4E80\u4E82\u4E85" +
506aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u4E86\u4E88\u4E89\u4E8A\u4E8B\u4E8C";
507aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
508aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
509aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m;
510aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String charsetMatch;
511aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] bytes;
512aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
513aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            bytes = s.getBytes("EUC-JP");
514aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(bytes);
515aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            m = det.detect();
516aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            charsetMatch = m.getName();
517aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(charsetMatch.equals("EUC-JP"));
518aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
519aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // Tests "public String getLanguage()"
520aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(m.getLanguage().equals("ja"));
521aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
522aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
523aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
524f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
525aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestArabic() throws Exception {
526aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String  s = "\u0648\u0636\u0639\u062A \u0648\u0646\u0641\u0630\u062A \u0628\u0631\u0627" +
527aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0645\u062C \u062A\u0623\u0645\u064A\u0646 \u0639\u062F\u064A\u062F\u0629 \u0641\u064A " +
528aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0645\u0624\u0633\u0633\u0629 \u0627\u0644\u062A\u0623\u0645\u064A\u0646 \u0627\u0644"  +
529aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0648\u0637\u0646\u064A, \u0645\u0639 \u0645\u0644\u0627\u0626\u0645\u062A\u0647\u0627 " +
530aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u062F\u0627\u0626\u0645\u0627 \u0644\u0644\u0627\u062D\u062A\u064A\u0627\u062C" +
531aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0627\u062A \u0627\u0644\u0645\u062A\u063A\u064A\u0631\u0629 \u0644\u0644\u0645\u062C" +
532aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u062A\u0645\u0639 \u0648\u0644\u0644\u062F\u0648\u0644\u0629. \u062A\u0648\u0633\u0639" +
533aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u062A \u0648\u062A\u0637\u0648\u0631\u062A \u0627\u0644\u0645\u0624\u0633\u0633\u0629 " +
534aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0628\u0647\u062F\u0641 \u0636\u0645\u0627\u0646 \u0634\u0628\u0643\u0629 \u0623\u0645" +
535aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0627\u0646 \u0644\u0633\u0643\u0627\u0646 \u062F\u0648\u0644\u0629 \u0627\u0633\u0631" +
536aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0627\u0626\u064A\u0644 \u0628\u0648\u062C\u0647 \u0627\u0644\u0645\u062E\u0627\u0637" +
537aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0631 \u0627\u0644\u0627\u0642\u062A\u0635\u0627\u062F\u064A\u0629 \u0648\u0627\u0644" +
538aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        "\u0627\u062C\u062A\u0645\u0627\u0639\u064A\u0629.";
539aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
540aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
541aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM424_rtl", true);
542aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM424_ltr", true);
543aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM420_rtl", true);
544aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM420_ltr", true);
545aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m;
546aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String charsetMatch;
547aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] bytes;
548aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
549aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            bytes = s.getBytes("windows-1256");
550aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(bytes);
551aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            m = det.detect();
552aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            charsetMatch = m.getName();
553aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(charsetMatch.equals("windows-1256"));
554aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
555aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // Tests "public String getLanguage()"
556aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(m.getLanguage().endsWith("ar"));
557aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
558aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
559aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
560aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // We cannot rely on IBM420 converter in Sun Java
561aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /*
562aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            bytes = s.getBytes("IBM420");
563aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            */
564aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            bytes = new byte[] {
565aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xCF, (byte)0x8D, (byte)0x9A, (byte)0x63, (byte)0x40, (byte)0xCF, (byte)0xBD, (byte)0xAB,
566aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x74, (byte)0x63, (byte)0x40, (byte)0x58, (byte)0x75, (byte)0x56, (byte)0xBB, (byte)0x67,
567aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0x63, (byte)0x49, (byte)0xBB, (byte)0xDC, (byte)0xBD, (byte)0x40, (byte)0x9A,
568aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x73, (byte)0xDC, (byte)0x73, (byte)0x62, (byte)0x40, (byte)0xAB, (byte)0xDC, (byte)0x40,
569aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xBB, (byte)0x52, (byte)0x77, (byte)0x77, (byte)0x62, (byte)0x40, (byte)0x56, (byte)0xB1,
570aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x63, (byte)0x49, (byte)0xBB, (byte)0xDC, (byte)0xBD, (byte)0x40, (byte)0x56, (byte)0xB1,
571aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xCF, (byte)0x8F, (byte)0xBD, (byte)0xDC, (byte)0x6B, (byte)0x40, (byte)0xBB, (byte)0x9A,
572aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0xBB, (byte)0xB1, (byte)0x56, (byte)0x55, (byte)0xBB, (byte)0x63, (byte)0xBF,
573aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x56, (byte)0x40, (byte)0x73, (byte)0x56, (byte)0x55, (byte)0xBB, (byte)0x56, (byte)0x40,
574aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xB1, (byte)0xB1, (byte)0x56, (byte)0x69, (byte)0x63, (byte)0xDC, (byte)0x56, (byte)0x67,
575aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x56, (byte)0x63, (byte)0x40, (byte)0x56, (byte)0xB1, (byte)0xBB, (byte)0x63, (byte)0x9E,
576aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xDC, (byte)0x75, (byte)0x62, (byte)0x40, (byte)0xB1, (byte)0xB1, (byte)0xBB, (byte)0x67,
577aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x63, (byte)0xBB, (byte)0x9A, (byte)0x40, (byte)0xCF, (byte)0xB1, (byte)0xB1, (byte)0x73,
578aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xCF, (byte)0xB1, (byte)0x62, (byte)0x4B, (byte)0x40, (byte)0x63, (byte)0xCF, (byte)0x77,
579aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x9A, (byte)0x63, (byte)0x40, (byte)0xCF, (byte)0x63, (byte)0x8F, (byte)0xCF, (byte)0x75,
580aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x63, (byte)0x40, (byte)0x56, (byte)0xB1, (byte)0xBB, (byte)0x52, (byte)0x77, (byte)0x77,
581aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x62, (byte)0x40, (byte)0x58, (byte)0xBF, (byte)0x73, (byte)0xAB, (byte)0x40, (byte)0x8D,
582aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xBB, (byte)0x56, (byte)0xBD, (byte)0x40, (byte)0x80, (byte)0x58, (byte)0xAF, (byte)0x62,
583aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0x49, (byte)0xBB, (byte)0x56, (byte)0xBD, (byte)0x40, (byte)0xB1, (byte)0x77,
584aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xAF, (byte)0x56, (byte)0xBD, (byte)0x40, (byte)0x73, (byte)0xCF, (byte)0xB1, (byte)0x62,
585aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0x56, (byte)0x77, (byte)0x75, (byte)0x56, (byte)0x55, (byte)0xDC, (byte)0xB1,
586aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0x58, (byte)0xCF, (byte)0x67, (byte)0xBF, (byte)0x40, (byte)0x56, (byte)0xB1,
587aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xBB, (byte)0x71, (byte)0x56, (byte)0x8F, (byte)0x75, (byte)0x40, (byte)0x56, (byte)0xB1,
588aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x56, (byte)0xAD, (byte)0x63, (byte)0x8B, (byte)0x56, (byte)0x73, (byte)0xDC, (byte)0x62,
589aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0xCF, (byte)0x56, (byte)0xB1, (byte)0x56, (byte)0x67, (byte)0x63, (byte)0xBB,
590aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x56, (byte)0x9A, (byte)0xDC, (byte)0x62, (byte)0x4B,
591aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            };
592aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(bytes);
593aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            m = det.detect();
594aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            charsetMatch = m.getName();
595aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(charsetMatch.equals("IBM420_rtl"));
596aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
597aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin         // Tests "public String getLanguage()"
598aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(m.getLanguage().endsWith("ar"));
599aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
600aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
601aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        {
602aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // We cannot rely on IBM420 converter in Sun Java
603aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            /*
604aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            StringBuffer ltrStrBuf = new StringBuffer(s);
605aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ltrStrBuf = ltrStrBuf.reverse();
606aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            bytes = ltrStrBuf.toString().getBytes("IBM420");
607aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            */
608aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            bytes = new byte[] {
609aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x4B, (byte)0x62, (byte)0xDC, (byte)0x9A, (byte)0x56, (byte)0xBB, (byte)0x63, (byte)0x67,
610aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x56, (byte)0xB1, (byte)0x56, (byte)0xCF, (byte)0x40, (byte)0x62, (byte)0xDC, (byte)0x73,
611aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x56, (byte)0x8B, (byte)0x63, (byte)0xAD, (byte)0x56, (byte)0xB1, (byte)0x56, (byte)0x40,
612aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x75, (byte)0x8F, (byte)0x56, (byte)0x71, (byte)0xBB, (byte)0xB1, (byte)0x56, (byte)0x40,
613aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xBF, (byte)0x67, (byte)0xCF, (byte)0x58, (byte)0x40, (byte)0xB1, (byte)0xDC, (byte)0x55,
614aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x56, (byte)0x75, (byte)0x77, (byte)0x56, (byte)0x40, (byte)0x62, (byte)0xB1, (byte)0xCF,
615aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x73, (byte)0x40, (byte)0xBD, (byte)0x56, (byte)0xAF, (byte)0x77, (byte)0xB1, (byte)0x40,
616aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xBD, (byte)0x56, (byte)0xBB, (byte)0x49, (byte)0x40, (byte)0x62, (byte)0xAF, (byte)0x58,
617aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x80, (byte)0x40, (byte)0xBD, (byte)0x56, (byte)0xBB, (byte)0x8D, (byte)0x40, (byte)0xAB,
618aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x73, (byte)0xBF, (byte)0x58, (byte)0x40, (byte)0x62, (byte)0x77, (byte)0x77, (byte)0x52,
619aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xBB, (byte)0xB1, (byte)0x56, (byte)0x40, (byte)0x63, (byte)0x75, (byte)0xCF, (byte)0x8F,
620aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x63, (byte)0xCF, (byte)0x40, (byte)0x63, (byte)0x9A, (byte)0x77, (byte)0xCF, (byte)0x63,
621aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0x4B, (byte)0x62, (byte)0xB1, (byte)0xCF, (byte)0x73, (byte)0xB1, (byte)0xB1,
622aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xCF, (byte)0x40, (byte)0x9A, (byte)0xBB, (byte)0x63, (byte)0x67, (byte)0xBB, (byte)0xB1,
623aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xB1, (byte)0x40, (byte)0x62, (byte)0x75, (byte)0xDC, (byte)0x9E, (byte)0x63, (byte)0xBB,
624aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xB1, (byte)0x56, (byte)0x40, (byte)0x63, (byte)0x56, (byte)0x67, (byte)0x56, (byte)0xDC,
625aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x63, (byte)0x69, (byte)0x56, (byte)0xB1, (byte)0xB1, (byte)0x40, (byte)0x56, (byte)0xBB,
626aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x55, (byte)0x56, (byte)0x73, (byte)0x40, (byte)0x56, (byte)0xBF, (byte)0x63, (byte)0xBB,
627aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x55, (byte)0x56, (byte)0xB1, (byte)0xBB, (byte)0x40, (byte)0x9A, (byte)0xBB, (byte)0x40,
628aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x6B, (byte)0xDC, (byte)0xBD, (byte)0x8F, (byte)0xCF, (byte)0xB1, (byte)0x56, (byte)0x40,
629aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xBD, (byte)0xDC, (byte)0xBB, (byte)0x49, (byte)0x63, (byte)0xB1, (byte)0x56, (byte)0x40,
630aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x62, (byte)0x77, (byte)0x77, (byte)0x52, (byte)0xBB, (byte)0x40, (byte)0xDC, (byte)0xAB,
631aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0x62, (byte)0x73, (byte)0xDC, (byte)0x73, (byte)0x9A, (byte)0x40, (byte)0xBD,
632aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0xDC, (byte)0xBB, (byte)0x49, (byte)0x63, (byte)0x40, (byte)0x67, (byte)0xBB, (byte)0x56,
633aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x75, (byte)0x58, (byte)0x40, (byte)0x63, (byte)0x74, (byte)0xAB, (byte)0xBD, (byte)0xCF,
634aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                (byte)0x40, (byte)0x63, (byte)0x9A, (byte)0x8D, (byte)0xCF,
635aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            };
636aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
637aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            det.setText(bytes);
638aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            m = det.detect();
639aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            charsetMatch = m.getName();
640aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            CheckAssert(charsetMatch.equals("IBM420_ltr"));
641aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
642aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
643aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
644f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
645aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestHebrew() throws Exception {
646aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String  s =  "\u05D4\u05E4\u05E8\u05E7\u05DC\u05D9\u05D8 \u05D4\u05E6\u05D1\u05D0\u05D9 \u05D4" +
647aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05E8\u05D0\u05E9\u05D9, \u05EA\u05EA \u05D0\u05DC\u05D5\u05E3 \u05D0\u05D1\u05D9" +
648aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05D7\u05D9 \u05DE\u05E0\u05D3\u05DC\u05D1\u05DC\u05D9\u05D8, \u05D4\u05D5\u05E8" +
649aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05D4 \u05E2\u05DC \u05E4\u05EA\u05D9\u05D7\u05EA \u05D7\u05E7\u05D9\u05E8\u05EA " +
650aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05DE\u05E6\"\u05D7 \u05D1\u05E2\u05E7\u05D1\u05D5\u05EA \u05E2\u05D3\u05D5\u05D9" +
651aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05D5\u05EA \u05D7\u05D9\u05D9\u05DC\u05D9 \u05E6\u05D4\"\u05DC \u05DE\u05DE\u05D1" +
652aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05E6\u05E2 \u05E2\u05D5\u05E4\u05E8\u05EA \u05D9\u05E6\u05D5\u05E7\u05D4 \u05D1+ " +
653aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05E8\u05E6\u05D5\u05E2\u05EA \u05E2\u05D6\u05D4. \u05DC\u05D3\u05D1\u05E8\u05D9 " +
654aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05D4\u05E4\u05E6\"\u05E8, \u05DE\u05D4\u05E2\u05D3\u05D5\u05D9\u05D5\u05EA \u05E2" +
655aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05D5\u05DC\u05D4 \u05EA\u05DE\u05D5\u05E0\u05D4 \u05E9\u05DC \"\u05D4\u05EA\u05E0" +
656aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05D4\u05D2\u05D5\u05EA \u05E4\u05E1\u05D5\u05DC\u05D4 \u05DC\u05DB\u05D0\u05D5\u05E8" +
657aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05D4 \u05E9\u05DC \u05D7\u05D9\u05D9\u05DC\u05D9\u05DD \u05D1\u05DE\u05D4\u05DC\u05DA" +
658aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            " \u05DE\u05D1\u05E6\u05E2 \u05E2\u05D5\u05E4\u05E8\u05EA \u05D9\u05E6\u05D5\u05E7\u05D4\"." +
659aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            " \u05DE\u05E0\u05D3\u05DC\u05D1\u05DC\u05D9\u05D8 \u05E7\u05D9\u05D1\u05DC \u05D0\u05EA" +
660aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            " \u05D4\u05D7\u05DC\u05D8\u05EA\u05D5 \u05DC\u05D0\u05D7\u05E8 \u05E9\u05E2\u05D9\u05D9" +
661aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "\u05DF \u05D1\u05EA\u05DE\u05DC\u05D9\u05DC \u05D4\u05E2\u05D3\u05D5\u05D9\u05D5\u05EA";
662aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
663aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m = _test1255(s);
664aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String charsetMatch = m.getName();
665aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(charsetMatch.equals("ISO-8859-8-I"));
666aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(m.getLanguage().equals("he"));
667aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
668aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = _test1255_reverse(s);
669aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        charsetMatch = m.getName();
670aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(charsetMatch.equals("ISO-8859-8"));
671aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(m.getLanguage().equals("he"));
672aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
673aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = _testIBM424_he_rtl(s);
674aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        charsetMatch = m.getName();
675aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(charsetMatch.equals("IBM424_rtl"));
676aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(m.getLanguage().equals("he"));
677aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
678aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            m.getString();
679aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } catch (Exception ex) {
680aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Error getting string for charsetMatch: " + charsetMatch);
681aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
682aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
683aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        m = _testIBM424_he_ltr(s);
684aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        charsetMatch = m.getName();
685aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(charsetMatch.equals("IBM424_ltr"));
686aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CheckAssert(m.getLanguage().equals("he"));
687aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
688aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            m.getString();
689aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } catch (Exception ex) {
690aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Error getting string for charsetMatch: " + charsetMatch);
691aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
692aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
693aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
694aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private CharsetMatch _test1255(String s) throws Exception {
695aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte [] bytes = s.getBytes("ISO-8859-8");
696aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
697aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bytes);
698aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m = det.detect();
699aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return m;
700aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
701aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
702aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private CharsetMatch _test1255_reverse(String s) throws Exception {
703aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer reverseStrBuf = new StringBuffer(s);
704aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        reverseStrBuf = reverseStrBuf.reverse();
705aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte [] bytes = reverseStrBuf.toString().getBytes("ISO-8859-8");
706aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
707aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
708aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bytes);
709aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m = det.detect();
710aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return m;
711aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
712aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
713aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private CharsetMatch _testIBM424_he_rtl(String s) throws Exception {
714aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte [] bytes = s.getBytes("IBM424");
715aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
716aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM424_rtl", true);
717aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM424_ltr", true);
718aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM420_rtl", true);
719aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM420_ltr", true);
720aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bytes);
721aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m = det.detect();
722aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return m;
723aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
724aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
725aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private CharsetMatch _testIBM424_he_ltr(String s) throws Exception {
726aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        /**
727aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin         * transformation of input string to CP420 left to right requires reversing the string
728aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin         */
729aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
730aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer ltrStrBuf = new StringBuffer(s);
731aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        ltrStrBuf = ltrStrBuf.reverse();
732aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte [] bytes = ltrStrBuf.toString().getBytes("IBM424");
733aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
734aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
735aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM424_rtl", true);
736aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM424_ltr", true);
737aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM420_rtl", true);
738aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setDetectableCharset("IBM420_ltr", true);
739aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(bytes);
740aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch m = det.detect();
741aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return m;
742aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
743aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
744aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /*
745aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Test the method int match(CharsetDetector det) in CharsetRecog_UTF_16_LE
746aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
747f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
748aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestCharsetRecog_UTF_16_LE_Match() {
749aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] in = { Byte.MIN_VALUE, Byte.MIN_VALUE, Byte.MIN_VALUE, Byte.MIN_VALUE };
750aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector cd = new CharsetDetector();
751aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Tests when if (input.length>=4 && input[2] == 0x00 && input[3] == 0x00) is true inside the
752aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // match(CharsetDetector) method of CharsetRecog_UTF_16_LE
753aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
754aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            cd.setText(in);
755aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        } catch (Exception e) {
756aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("CharsetRecog_UTF_16_LE.match(CharsetDetector) was not suppose to return an exception.");
757aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
758aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
759aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
760aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    //
761aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    //  Bug #8309, test case submitted with original bug report.
762aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    //
763f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
764f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void TestFreshDetectorEachTime() throws Exception
765aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      {
766aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetDetector detector1 = new CharsetDetector();
767aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          byte[] data1 = createData1();
768aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          detector1.setText(data1);
769aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetMatch match1 = detector1.detect();
770aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          assertEquals("Expected GB18030", "GB18030", match1.getName());
771aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
772aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetDetector detector2 = new CharsetDetector();
773aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          byte[] data2 = createData2();
774aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          detector2.setText(data2);
775aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetMatch match2 = detector2.detect();
776aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          // It is actually GB18030 but the sample size is way too small to be reliable.
777aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          assertEquals("Expected ISO-8859-1, even though that isn't strictly correct", "ISO-8859-1", match2.getName());
778aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      }
779aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
780f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
781f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void TestReusingDetector() throws Exception
782aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      {
783aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetDetector detector = new CharsetDetector();
784aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
785aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          byte[] data1 = createData1();
786aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          detector.setText(data1);
787aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetMatch match1 = detector.detect();
788aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          assertEquals("Expected GB18030", "GB18030", match1.getName());
789aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          byte[] data2 = createData2();
790aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          detector.setText(data2);
791aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetMatch match2 = detector.detect();
792aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          assertEquals("Expected ISO-8859-1, even though that isn't strictly correct", "ISO-8859-1", match2.getName());
793aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          // calling detect() one more time without changing the input data
794aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          CharsetMatch match2a = detector.detect();
795aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          assertEquals("[second]Expected ISO-8859-1, even though that isn't strictly correct", "ISO-8859-1", match2a.getName());
796aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      }
797aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
798aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      private static byte[] createData1()
799aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      {
800aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin         return bytesFromString("3B 3B 3B 20 2D 2A 2D 20 4D 6F 64 65 3A 20 4C 49 53 50 3B 20 53 79 6E 74 61 78 " +
801aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "3A 20 43 6F 6D 6D 6F 6E 2D 6C 69 73 70 3B 20 50 61 63 6B 61 67 65 3A 20 41 4C " +
802aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "45 4D 42 49 43 20 3B 20 42 61 73 65 3A 20 31 30 20 2D 2A 2D 0D 0A 0D 0A 28 69 " +
803aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "6E 2D 70 61 63 6B 61 67 65 20 22 41 4C 45 4D 42 49 43 22 29 0D 0A 0D 0A 28 6E " +
804aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "6F 74 69 63 65 20 22 43 6F 70 79 72 69 67 68 74 20 74 68 65 20 4D 49 54 52 45 " +
805aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 43 6F 72 70 6F 72 61 74 69 6F 6E 20 31 39 39 37 2D 31 39 39 38 2E 20 20 41 " +
806aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "6C 6C 20 72 69 67 68 74 73 20 72 65 73 65 72 76 65 64 2E 22 29 0D 0A 0D 0A 3B " +
807aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B " +
808aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B " +
809aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 0D 0A 3B 3B 3B 20 20 " +
810aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 " +
811aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 " +
812aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 20 20 20 20 20 20 3B 3B 3B 0D 0A 3B 3B 3B 20 20 20 43 68 69 " +
813aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "6E 65 73 65 20 73 75 66 66 69 78 2C 20 70 72 65 66 69 78 20 61 6E 64 20 61 66 " +
814aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "66 69 78 20 70 72 65 64 69 63 61 74 65 73 2E 09 09 20 20 20 20 20 3B 3B 3B 0D " +
815aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0A 3B 3B 3B 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 " +
816aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 " +
817aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 3B 3B 3B 0D 0A 3B 3B 3B " +
818aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B " +
819aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B " +
820aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 3B 0D 0A 0D 0A 28 64 65 66 76 " +
821aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "61 72 20 2A 7A 68 2D 6E 61 6D 65 2D 66 69 6E 61 6C 2D 63 68 61 72 73 2A 0D 0A " +
822aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 27 28 3B 3B 20 63 6F 6D 6D 6F 6E 20 4A 61 70 61 6E 65 73 65 20 50 " +
823aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "65 72 73 6E 61 6D 65 20 65 6E 64 69 6E 67 0D 0A 20 20 20 20 20 20 22 CC AB C0 " +
824aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C9 22 0D 0A 20 20 20 20 20 20 3B 3B 20 4D 65 79 65 72 3F 0D 0A 20 20 20 20 20 " +
825aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 3B 3B 20 C3 B7 C8 D5 0D 0A 20 20 20 20 20 20 22 B0 A2 22 20 22 B0 A3 22 20 " +
826aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B0 B2 22 20 22 B0 BA 22 20 22 B0 C2 22 20 22 B0 CD 22 0D 0A 20 20 20 20 20 " +
827aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B0 D7 22 20 22 B0 DD 22 20 22 B0 E0 22 20 22 B0 EE 22 20 22 B1 A4 22 20 " +
828aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B1 AB 22 0D 0A 20 20 20 20 20 20 22 B1 B4 22 20 22 B1 BE 22 20 22 B1 C8 22 " +
829aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B1 CF 22 20 22 B1 F6 22 20 22 B2 A8 22 0D 0A 20 20 20 20 20 20 22 B2 A9 " +
830aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B2 AA 22 20 22 B2 AE 22 20 22 B2 B7 22 20 22 B2 BC 22 20 22 B2 C9 22 " +
831aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 B2 DF 22 20 22 B2 E9 22 20 22 B2 EC 22 20 22 B2 EE " +
832aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B3 B9 22 20 22 B4 C4 22 0D 0A 20 20 20 20 20 20 22 B4 EF 22 20 22 B4 " +
833aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "F3 22 20 22 B4 F7 22 20 22 B4 FA 22 20 22 B5 A4 22 20 22 B5 B1 22 0D 0A 20 20 " +
834aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 B5 C0 22 20 22 B5 C2 22 20 22 B5 C3 22 20 22 B5 C7 22 20 22 B5 " +
835aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CF 22 20 22 B5 D0 22 0D 0A 20 20 20 20 20 20 22 B5 D9 22 20 22 B5 DA 22 20 22 " +
836aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B5 D8 22 20 22 B6 A1 22 20 22 B6 AB 22 20 22 B6 BC 22 0D 0A 20 20 20 20 20 20 " +
837aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B6 C5 22 20 22 B6 D6 22 20 22 B6 D8 22 20 22 B6 D9 22 20 22 B6 E0 22 20 22 " +
838aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B6 F2 22 0D 0A 20 20 20 20 20 20 22 B6 F7 22 20 22 B6 FA 22 20 22 B6 FB 22 20 " +
839aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B7 A8 22 20 22 B7 B2 22 20 22 B7 B6 22 0D 0A 20 20 20 20 20 20 22 B7 BD 22 " +
840aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B7 C6 22 20 22 B7 D1 22 20 22 B7 D2 22 20 22 B7 E1 22 20 22 B7 EB 22 0D " +
841aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0A 20 20 20 20 20 20 22 B7 F0 22 20 22 B7 F2 22 20 22 B8 A3 22 20 22 B8 A5 22 " +
842aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B8 BB 22 20 22 B8 C7 22 0D 0A 20 20 20 20 20 20 22 B8 D4 22 20 22 B8 DF " +
843aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B8 E7 22 20 22 B8 EA 22 20 22 B8 F1 22 20 22 B8 F7 22 0D 0A 20 20 20 " +
844aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 22 B8 F9 22 20 22 B9 B1 22 20 22 B9 C5 22 20 22 B9 E7 22 20 22 B9 FB " +
845aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B9 FE 22 0D 0A 20 20 20 20 20 20 22 BA A3 22 20 22 BA B2 22 20 22 BA " +
846aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "BA 22 20 22 BA C0 22 20 22 BA D5 22 20 22 BA DA 22 0D 0A 20 20 20 20 20 20 22 " +
847aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "BA E0 22 20 22 BA E9 22 20 22 BB AA 22 20 22 BB DD 22 20 22 BB F4 22 20 22 BB " +
848aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "F9 22 0D 0A 20 20 20 20 20 20 22 BC AA 22 20 22 BC BE 22 20 22 BC CE 22 20 22 " +
849aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "BC D3 22 20 22 BC D6 22 20 22 BC F2 22 0D 0A 20 20 20 20 20 20 22 BD AA 22 20 " +
850aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 BD DC 22 20 22 BD F0 22 20 22 BD F1 22 20 22 BD F2 22 20 22 BF A1 22 0D 0A " +
851aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 22 BF A8 22 20 22 BF AD 22 20 22 BF B2 22 20 22 BF B5 22 20 " +
852aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 BF BC 22 20 22 BF C6 22 0D 0A 20 20 20 20 20 20 22 BF CB 22 20 22 BF CF 22 " +
853aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 BF E2 22 20 22 BF E4 22 20 22 C0 A4 22 20 22 C0 A5 22 0D 0A 20 20 20 20 " +
854aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 22 C0 AD 22 20 22 C0 B0 22 20 22 C0 B3 22 20 22 C0 B5 22 20 22 C0 BC 22 " +
855aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C0 CA 22 0D 0A 20 20 20 20 20 20 22 C0 CD 22 20 22 C0 D5 22 20 22 C0 D6 " +
856aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C0 D7 22 20 22 C0 E8 22 20 22 C0 EE 22 0D 0A 20 20 20 20 20 20 22 C0 " +
857aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "EF 22 20 22 C0 F1 22 20 22 C0 F2 22 20 22 C0 F6 22 20 22 C0 FB 22 20 22 C1 AB " +
858aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 22 C1 AE 22 20 22 C1 BC 22 20 22 C1 D0 22 20 22 C1 " +
859aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D2 22 20 22 C1 D5 22 20 22 C1 D6 22 0D 0A 20 20 20 20 20 20 22 C1 F5 22 20 22 " +
860aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C1 F8 22 20 22 C1 FA 22 20 22 C2 A1 22 20 22 C2 AC 22 20 22 C2 B3 22 0D 0A 20 " +
861aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 22 C2 D4 22 20 22 C2 D7 22 20 22 C2 DE 22 20 22 C2 E5 22 20 22 " +
862aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C2 EA 22 20 22 C2 ED 22 0D 0A 20 20 20 20 20 20 22 C2 F5 22 20 22 C2 FC 22 20 " +
863aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C3 A2 22 20 22 C3 B7 22 20 22 C3 C5 22 20 22 C3 C9 22 0D 0A 20 20 20 20 20 " +
864aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C3 D7 22 20 22 C3 DC 22 20 22 C3 F7 22 20 22 C4 A6 22 20 22 C4 AA 22 20 " +
865aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C4 AC 22 0D 0A 20 20 20 20 20 20 22 C4 B7 22 20 22 C4 B8 22 20 22 C4 C3 22 " +
866aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C4 C7 22 20 22 C4 C8 22 20 22 C4 C9 22 0D 0A 20 20 20 20 20 20 22 C4 CE " +
867aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C4 CF 22 20 22 C4 DA 22 20 22 C4 DD 22 20 22 C4 E1 22 20 22 C4 F9 22 " +
868aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 C4 FE 22 20 22 C5 A6 22 20 22 C5 A9 22 20 22 C5 AC " +
869aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C5 B5 22 20 22 C5 B7 22 0D 0A 20 20 20 20 20 20 22 C5 C1 22 20 22 C5 " +
870aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CB 22 20 22 C5 D3 22 20 22 C5 E5 22 20 22 C5 ED 22 20 22 C5 EE 22 0D 0A 20 20 " +
871aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 C6 A4 22 20 22 C6 BD 22 20 22 C6 D5 22 20 22 C6 E6 22 20 22 C6 " +
872aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "EB 22 20 22 C6 F5 22 0D 0A 20 20 20 20 20 20 22 C7 A1 22 20 22 C7 C7 22 20 22 " +
873aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C7 D0 22 20 22 C7 D5 22 20 22 C7 D9 22 20 22 C7 E5 22 0D 0A 20 20 20 20 20 20 " +
874aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C7 ED 22 20 22 C7 F0 22 20 22 C7 F5 22 20 22 C8 AA 22 20 22 C8 C3 22 20 22 " +
875aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C8 C8 22 0D 0A 20 20 20 20 20 20 22 C8 E5 22 20 22 C8 F6 22 20 22 C8 F8 22 20 " +
876aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C8 FB 22 20 22 C8 FC 22 20 22 C9 A3 22 0D 0A 20 20 20 20 20 20 22 C9 AA 22 " +
877aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C9 AD 22 20 22 C9 AF 22 20 22 C9 B3 22 20 22 C9 BA 22 0D 0A 20 20 20 20 " +
878aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 3B 3B 20 22 C9 CF 22 0D 0A 20 20 20 20 20 20 22 C9 D0 22 20 22 C9 DC 22 " +
879aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C9 E1 22 20 22 C9 EA 22 20 22 C9 FA 22 20 22 CA A9 22 0D 0A 20 20 20 20 " +
880aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 22 CA AB 22 20 22 CA AF 22 20 22 CA B2 22 20 22 CA BF 22 20 22 CA D2 22 " +
881aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 CB B9 22 0D 0A 20 20 20 20 20 20 22 CB BC 22 20 22 CB BF 22 20 22 CB C9 " +
882aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 CB D5 22 20 22 CB D8 22 20 22 CB E7 22 0D 0A 20 20 20 20 20 20 22 CB " +
883aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "F7 22 20 22 CB FE 22 20 22 CC A9 22 20 22 CC AB 22 20 22 CC B9 22 20 22 CC C0 " +
884aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 22 CC C6 22 20 22 CC D5 22 20 22 CC D8 22 20 22 CC " +
885aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "E1 22 20 22 CD A1 22 20 22 CD A2 22 0D 0A 20 20 20 20 20 20 22 CD A8 22 20 22 " +
886aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CD B8 22 20 22 CD BC 22 20 22 CD D0 22 20 22 CD D1 22 20 22 CD DE 22 0D 0A 20 " +
887aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 22 CD DF 22 20 22 CD F2 22 20 22 CD FA 22 20 22 CD FE 22 20 22 " +
888aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CE A2 22 20 22 CE A4 22 0D 0A 20 20 20 20 20 20 22 CE AC 22 20 22 CE C0 22 20 " +
889aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 CE C2 22 20 22 CE C4 22 20 22 CE CC 22 20 22 CE D6 22 0D 0A 20 20 20 20 20 " +
890aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 CE DA 22 20 22 CE F7 22 20 22 CE FD 22 20 22 CF A3 22 20 22 CF BC 22 20 " +
891aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 CF C4 22 0D 0A 20 20 20 20 20 20 22 CF E3 22 0D 0A 20 20 20 20 20 20 3B 3B " +
892aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 70 72 65 70 6F 73 69 74 69 6F 6E 0D 0A 20 20 20 20 20 20 3B 3B 20 22 CF F2 " +
893aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 22 D0 A4 22 20 22 D0 AA 22 20 22 D0 BB 22 0D 0A 20 " +
894aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 22 D0 C0 22 20 22 D0 C1 22 20 22 D0 CB 22 20 22 D0 D0 22 20 22 " +
895aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D0 D2 22 20 22 D0 DB 22 0D 0A 20 20 20 20 20 20 22 D0 DD 22 20 22 D1 B7 22 20 " +
896aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 D1 C0 22 20 22 D1 C7 22 20 22 D1 D3 22 20 22 D1 EF 22 0D 0A 20 20 20 20 20 " +
897aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 D2 AE 22 20 22 D2 B6 22 20 22 D2 C1 22 20 22 D2 F2 22 20 22 D3 A2 22 20 " +
898aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 D3 C8 22 0D 0A 20 20 20 20 20 20 22 D4 BC 22 20 22 D4 D7 22 20 22 D4 DE 22 " +
899aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 D4 E7 22 20 22 D4 F3 22 20 22 D4 F8 22 0D 0A 20 20 20 20 20 20 22 D4 FA " +
900aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 D5 B2 22 20 22 D5 C2 22 20 22 D6 A5 22 20 22 D6 BA 22 20 22 D6 CE 22 " +
901aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 D6 E9 22 20 22 D7 C8 22 20 22 D7 CC 22 20 22 D7 DA " +
902aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 D7 F4 22 20 22 E1 AF 22 0D 0A 20 20 20 20 20 20 22 E6 AB 22 20 22 E6 " +
903aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "DA 22 20 22 E7 D1 22 20 22 E7 EA 22 20 22 E7 F7 22 20 22 E8 A7 22 0D 0A 20 20 " +
904aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 E9 AA 22 20 22 EB F8 22 20 22 F7 EB 22 0D 0A 20 20 20 20 20 20 " +
905aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "29 29 0D 0A 0D 0A 28 64 65 66 76 61 72 20 2A 7A 68 2D 6E 61 6D 65 2D 69 6E 69 " +
906aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "74 69 61 6C 2D 63 68 61 72 73 2A 0D 0A 20 20 20 20 27 28 22 B0 A2 22 20 22 B0 " +
907aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "A3 22 20 22 B0 AC 22 20 22 B0 AE 22 20 22 B0 B2 22 20 22 B0 BA 22 20 22 B0 C2 " +
908aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 22 B0 C4 22 20 22 B0 CD 22 20 22 B0 D7 22 20 22 B0 " +
909aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "DD 22 20 22 B0 E0 22 20 22 B0 EE 22 0D 0A 20 20 20 20 20 20 22 B1 A3 22 20 22 " +
910aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B1 AB 22 20 22 B1 B4 22 20 22 B1 BE 22 20 22 B1 C8 22 20 22 B1 CB 22 0D 0A 20 " +
911aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 22 B1 CF 22 20 22 B1 F6 22 20 22 B2 A8 22 20 22 B2 A9 22 20 22 " +
912aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B2 AE 22 20 22 B2 BC 22 0D 0A 20 20 20 20 20 20 22 B2 CC 22 20 22 B2 E9 22 20 " +
913aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B2 F1 22 20 22 B2 FD 22 20 22 B3 B9 22 20 22 B3 FE 22 0D 0A 20 20 20 20 20 " +
914aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B4 C4 22 20 22 B4 EF 22 20 22 B4 F7 22 20 22 B4 FA 22 20 22 B5 A4 22 20 " +
915aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B5 B1 22 0D 0A 20 20 20 20 20 20 22 B5 C0 22 20 22 B5 C2 22 20 22 B5 C7 22 " +
916aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B5 CB 22 20 22 B5 CF 22 20 22 B5 D2 22 0D 0A 20 20 20 20 20 20 22 B5 D9 " +
917aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B6 A1 22 20 22 B6 C5 22 20 22 B6 CB 22 20 22 B6 D8 22 20 22 B6 D9 22 " +
918aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 B6 E0 22 20 22 B6 F2 22 20 22 B6 F7 22 20 22 B7 A8 " +
919aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B7 B6 22 20 22 B7 BD 22 0D 0A 20 20 20 20 20 20 22 B7 C6 22 20 22 B7 " +
920aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D1 22 20 22 B7 D2 22 20 22 B7 EB 22 20 22 B7 F2 22 20 22 B7 F0 22 0D 0A 20 20 " +
921aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 B7 FC 22 20 22 B8 A3 22 20 22 B8 A5 22 20 22 B8 BB 22 20 22 B8 " +
922aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C7 22 20 22 B8 CA 22 0D 0A 20 20 20 20 20 20 22 B8 D4 22 20 22 B8 DF 22 20 22 " +
923aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B8 E7 22 20 22 B8 EA 22 20 22 B8 F1 22 20 22 B8 F9 22 0D 0A 20 20 20 20 20 20 " +
924aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B9 B1 22 20 22 B9 C5 22 20 22 B9 CF 22 20 22 B9 E7 22 20 22 B9 FA 22 20 22 " +
925aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B9 FE 22 0D 0A 20 20 20 20 20 20 22 BA A3 22 20 22 BA BA 22 20 22 BA BC 22 20 " +
926aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 BA C0 22 20 22 BA D5 22 20 22 BA DA 22 0D 0A 20 20 20 20 20 20 22 BA E0 22 " +
927aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 BA F4 22 20 22 BA FA 22 20 22 BB AA 22 20 22 BB B3 22 20 22 BB DD 22 0D " +
928aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0A 20 20 20 20 20 20 22 BB F4 22 20 22 BB F9 22 20 22 BC AA 22 20 22 BC B8 22 " +
929aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 BC D3 22 20 22 BC D6 22 0D 0A 20 20 20 20 20 20 22 BC F2 22 20 22 BC FB " +
930aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 BD AD 22 20 22 BD DC 22 20 22 BD F0 22 20 22 BD F2 22 0D 0A 20 20 20 " +
931aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 22 BE AE 22 20 22 BF A8 22 20 22 BF AD 22 20 22 BF B2 22 20 22 BF B5 " +
932aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 BF BC 22 0D 0A 20 20 20 20 20 20 22 BF C2 22 20 22 BF C6 22 20 22 BF " +
933aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CB 22 20 22 BF CF 22 20 22 BF D7 22 20 22 BF E2 22 0D 0A 20 20 20 20 20 20 22 " +
934aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "BF E4 22 20 22 BF EF 22 20 22 BF FC 22 20 22 BF FD 22 20 22 C0 A5 22 20 22 C0 " +
935aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "AD 22 0D 0A 20 20 20 20 20 20 22 C0 B0 22 20 22 C0 B3 22 20 22 C0 B5 22 20 22 " +
936aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C0 BC 22 20 22 C0 CA 22 20 22 C0 CD 22 0D 0A 20 20 20 20 20 20 22 C0 D5 22 20 " +
937aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C0 D7 22 20 22 C0 E8 22 20 22 C0 ED 22 20 22 C0 EE 22 20 22 C0 EF 22 0D 0A " +
938aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 22 C0 F2 22 20 22 C0 F6 22 20 22 C0 FB 22 20 22 C1 D0 22 20 " +
939aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C1 D5 22 20 22 C1 D6 22 0D 0A 20 20 20 20 20 20 22 C1 F5 22 20 22 C1 F8 22 " +
940aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C1 FA 22 20 22 C2 A1 22 20 22 C2 AC 22 20 22 C2 B3 22 0D 0A 20 20 20 20 " +
941aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 22 C2 B6 22 20 22 C2 B7 22 20 22 C2 C0 22 20 22 C2 D7 22 20 22 C2 DE 22 " +
942aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C2 E5 22 0D 0A 20 20 20 20 20 20 22 C2 EA 22 20 22 C2 ED 22 20 22 C2 F3 " +
943aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C2 F5 22 20 22 C2 FC 22 20 22 C3 A2 22 0D 0A 20 20 20 20 20 20 22 C3 " +
944aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "AB 22 20 22 C3 B7 22 20 22 C3 C5 22 20 22 C3 C9 22 20 22 C3 CF 22 20 22 C3 D7 " +
945aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 22 C3 F7 22 20 22 C4 A6 22 20 22 C4 AA 22 20 22 C4 " +
946aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "AB 22 20 22 C4 AC 22 20 22 C4 B7 22 0D 0A 20 20 20 20 20 20 22 C4 C2 22 20 22 " +
947aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C4 C9 22 20 22 C4 CE 22 20 22 C4 CF 22 20 22 C4 DA 22 20 22 C4 DD 22 0D 0A 20 " +
948aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 22 C4 E1 22 20 22 C4 FE 22 20 22 C5 A3 22 20 22 C5 A6 22 20 22 " +
949aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C5 A9 22 20 22 C5 AC 22 0D 0A 20 20 20 20 20 20 22 C5 B5 22 20 22 C5 B7 22 20 " +
950aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C5 C1 22 20 22 C5 C9 22 20 22 C5 CB 22 20 22 C5 D3 22 0D 0A 20 20 20 20 20 " +
951aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C5 E0 22 20 22 C5 E5 22 20 22 C5 ED 22 20 22 C6 A4 22 20 22 C6 BD 22 20 " +
952aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C6 D3 22 0D 0A 20 20 20 20 20 20 22 C6 D5 22 20 22 C6 CF 22 20 22 C6 E6 22 " +
953aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C6 EB 22 20 22 C7 A1 22 20 22 C7 AE 22 0D 0A 20 20 20 20 20 20 22 C7 C5 " +
954aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C7 C7 22 20 22 C7 D0 22 20 22 C7 D5 22 20 22 C7 ED 22 20 22 C7 F0 22 " +
955aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 C7 F1 22 20 22 C8 C8 22 20 22 C8 D9 22 20 22 C8 E5 " +
956aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C8 F0 22 20 22 C8 F6 22 0D 0A 20 20 20 20 20 20 22 C8 F8 22 20 22 C8 " +
957aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "FB 22 20 22 C8 FC 22 20 22 C9 A3 22 20 22 C9 AA 22 20 22 C9 AD 22 0D 0A 20 20 " +
958aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 C9 AF 22 20 22 C9 B3 22 20 22 C9 DC 22 20 22 C9 E1 22 20 22 C9 " +
959aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "EA 22 20 22 CA A5 22 0D 0A 20 20 20 20 20 20 22 CA A9 22 20 22 CA B7 22 20 22 " +
960aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CA E6 22 20 22 CB B7 22 20 22 CB B9 22 20 22 CB BC 22 0D 0A 20 20 20 20 20 20 " +
961aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 CB C9 22 20 22 CB D5 22 20 22 CB F7 22 20 22 CB F9 22 20 22 CB FE 22 20 22 " +
962aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CC A9 22 0D 0A 20 20 20 20 20 20 22 CC B9 22 20 22 CC C0 22 20 22 CC C6 22 20 " +
963aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 CC D5 22 20 22 CC D8 22 20 22 CC FA 22 0D 0A 20 20 20 20 20 20 22 CD A2 22 " +
964aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 CD A8 22 20 22 CD BC 22 20 22 CD CF 22 20 22 CD D0 22 20 22 CD DF 22 0D " +
965aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0A 20 20 20 20 20 20 22 CD F2 22 20 22 CD FA 22 20 22 CD FE 22 20 22 CE A4 22 " +
966aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 CE AC 22 20 22 CE BA 22 0D 0A 20 20 20 20 20 20 22 CE C2 22 20 22 CE C4 " +
967aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 CE CC 22 20 22 CE D6 22 20 22 CE DA 22 20 22 CE E4 22 0D 0A 20 20 20 " +
968aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 22 CE E9 22 20 22 CE F7 22 20 22 CE FD 22 20 22 CF A3 22 20 22 CF A4 " +
969aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 CF AF 22 0D 0A 20 20 20 20 20 20 22 CF C4 22 20 22 CF E3 22 20 22 D0 " +
970aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "A4 22 20 22 D0 AA 22 20 22 D0 BB 22 20 22 D0 C0 22 0D 0A 20 20 20 20 20 20 22 " +
971aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D0 C1 22 20 22 D0 DD 22 20 22 D0 DE 22 20 22 D0 ED 22 20 22 D0 F0 22 20 22 D1 " +
972aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "A6 22 0D 0A 20 20 20 20 20 20 22 D1 A9 22 20 22 D1 C5 22 20 22 D1 C7 22 20 22 " +
973aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D1 D3 22 20 22 D1 EF 22 20 22 D2 AB 22 0D 0A 20 20 20 20 20 20 22 D2 AE 22 20 " +
974aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 D2 B6 22 20 22 D2 C1 22 20 22 D2 D7 22 20 22 D3 A1 22 20 22 D3 A2 22 0D 0A " +
975aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 22 D3 C8 22 20 22 D3 DA 22 20 22 D3 EA 22 20 22 D4 BC 22 20 " +
976aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 D4 DE 22 20 22 D4 F3 22 0D 0A 20 20 20 20 20 20 22 D4 F8 22 20 22 D5 A7 22 " +
977aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 D4 FA 22 20 22 D5 B2 22 20 22 D5 C5 22 20 22 D5 E4 22 0D 0A 20 20 20 20 " +
978aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 22 D6 A5 22 20 22 D6 EC 22 20 22 D7 C8 22 20 22 D7 DA 22 20 22 D7 F4 22 " +
979aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 E7 EA 22 0D 0A 20 20 20 20 20 20 22 E8 A7 22 20 22 EB F8 22 20 22 F7 EC " +
980aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 29 29 0D 0A 0D 0A 28 64 65 66 76 61 72 20 2A 7A 68 " +
981aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "2D 6E 61 6D 65 2D 6D 65 64 69 61 6C 2D 63 68 61 72 73 2A 0D 0A 20 20 20 20 27 " +
982aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "28 22 A1 A4 22 20 22 A3 AE 22 20 22 B0 A2 22 20 22 B0 A3 22 20 22 B0 AC 22 20 " +
983aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B0 AE 22 0D 0A 20 20 20 20 20 20 22 B0 B2 22 20 22 B0 BA 22 20 22 B0 C2 22 " +
984aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B0 C4 22 20 22 B0 CD 22 20 22 B0 D7 22 0D 0A 20 20 20 20 20 20 22 B0 DD " +
985aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B0 E0 22 20 22 B0 EE 22 20 22 B1 AB 22 20 22 B1 B1 22 20 22 B1 B4 22 " +
986aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 B1 B6 22 20 22 B1 BE 22 20 22 B1 C8 22 20 22 B1 CB " +
987aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B1 D9 22 20 22 B1 F0 22 0D 0A 20 20 20 20 20 20 22 B1 F6 22 20 22 B2 " +
988aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "A8 22 20 22 B2 AA 22 20 22 B2 A9 22 20 22 B2 AE 22 20 22 B2 B7 22 0D 0A 20 20 " +
989aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 B2 BC 22 20 22 B2 DF 22 20 22 B2 E9 22 20 22 B2 F1 22 20 22 B3 " +
990aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B9 22 20 22 B3 C2 22 0D 0A 20 20 20 20 20 20 22 B4 C4 22 20 22 B4 CE 22 20 22 " +
991aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B4 EF 22 20 22 B4 F3 22 20 22 B4 F7 22 20 22 B4 FA 22 0D 0A 20 20 20 20 20 20 " +
992aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B5 A4 22 20 22 B5 B1 22 20 22 B5 C0 22 20 22 B5 C2 22 20 22 B5 C3 22 20 22 " +
993aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B5 C7 22 0D 0A 20 20 20 20 20 20 22 B5 CB 22 20 22 B5 CF 22 20 22 B5 D2 22 20 " +
994aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 B5 D8 22 20 22 B5 DA 22 20 22 B5 D9 22 0D 0A 20 20 20 20 20 20 22 B6 A1 22 " +
995aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B6 AB 22 20 22 B6 C5 22 20 22 B6 D9 22 20 22 B6 E0 22 20 22 B6 F2 22 0D " +
996aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0A 20 20 20 20 20 20 22 B6 ED 22 20 22 B6 F7 22 20 22 B6 FB 22 20 22 B7 A8 22 " +
997aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 B7 B6 22 20 22 B7 BD 22 0D 0A 20 20 20 20 20 20 22 B7 C6 22 20 22 B7 C7 " +
998aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B7 D1 22 20 22 B7 D2 22 20 22 B7 E1 22 20 22 B7 EB 22 0D 0A 20 20 20 " +
999aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 22 B7 F0 22 20 22 B7 F2 22 20 22 B8 A3 22 20 22 B8 A5 22 20 22 B8 B5 " +
1000aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 B8 BB 22 0D 0A 20 20 20 20 20 20 22 B8 C7 22 20 22 B8 CA 22 20 22 B8 " +
1001aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "DF 22 20 22 B8 E7 22 20 22 B8 EA 22 20 22 B8 EF 22 0D 0A 20 20 20 20 20 20 22 " +
1002aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B8 F0 22 20 22 B8 F1 22 20 22 B8 F7 22 20 22 B8 F9 22 20 22 B8 FC 22 20 22 B9 " +
1003aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B1 22 0D 0A 20 20 20 20 20 20 22 B9 C3 22 20 22 B9 C5 22 20 22 B9 CF 22 20 22 " +
1004aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B9 E7 22 20 22 B9 FA 22 20 22 B9 FE 22 0D 0A 20 20 20 20 20 20 22 BA A3 22 20 " +
1005aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 BA B1 22 20 22 BA B2 22 20 22 BA BA 22 20 22 BA C0 22 20 22 BA C1 22 0D 0A " +
1006aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 22 BA D5 22 20 22 BA DA 22 20 22 BA E0 22 20 22 BA E3 22 20 " +
1007aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 BA E9 22 20 22 BA EE 22 0D 0A 20 20 20 20 20 20 22 BA FA 22 20 22 BB AA 22 " +
1008aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 BB B3 22 20 22 BB DD 22 20 22 BB F4 22 20 22 BB F9 22 0D 0A 20 20 20 20 " +
1009aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 22 BC AA 22 20 22 BC BE 22 20 22 BC CE 22 20 22 BC D3 22 20 22 BC D6 22 " +
1010aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 BD DC 22 0D 0A 20 20 20 20 20 20 22 BD F0 22 20 22 BD F2 22 20 22 BF A8 " +
1011aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 BF AA 22 20 22 BF AD 22 20 22 BF B2 22 0D 0A 20 20 20 20 20 20 22 BF " +
1012aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "B5 22 20 22 BF BC 22 20 22 BF C2 22 20 22 BF C6 22 20 22 BF CB 22 20 22 BF A6 " +
1013aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 22 BF CF 22 20 22 BF D7 22 20 22 BF DB 22 20 22 BF " +
1014aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "E2 22 20 22 BF E4 22 20 22 BF FC 22 0D 0A 20 20 20 20 20 20 22 C0 A5 22 20 22 " +
1015aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C0 AA 22 20 22 C0 AD 22 20 22 C0 B0 22 20 22 C0 B3 22 20 22 C0 B4 22 0D 0A 20 " +
1016aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 22 C0 B5 22 20 22 C0 BC 22 20 22 C0 CA 22 20 22 C0 CD 22 20 22 " +
1017aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C0 D5 22 20 22 C0 D7 22 0D 0A 20 20 20 20 20 20 22 C0 D9 22 20 22 C0 E8 22 20 " +
1018aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C0 ED 22 20 22 C0 EE 22 20 22 C0 EF 22 20 22 C0 F1 22 0D 0A 20 20 20 20 20 " +
1019aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C0 F2 22 20 22 C0 F6 22 20 22 C0 FA 22 20 22 C0 FB 22 20 22 C1 A2 22 20 " +
1020aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C1 AC 22 0D 0A 20 20 20 20 20 20 22 C1 AB 22 20 22 C1 AA 22 20 22 C1 AE 22 " +
1021aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C1 BF 22 20 22 C1 D0 22 20 22 C1 D2 22 0D 0A 20 20 20 20 20 20 22 C1 D5 " +
1022aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C1 D6 22 20 22 C1 F4 22 20 22 C1 F8 22 20 22 C1 FA 22 20 22 C2 A1 22 " +
1023aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 C2 AC 22 20 22 C2 B3 22 20 22 C2 B6 22 20 22 C2 B7 " +
1024aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C2 C0 22 20 22 C2 D4 22 0D 0A 20 20 20 20 20 20 22 C2 D7 22 20 22 C2 " +
1025aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D8 22 20 22 C2 DC 22 20 22 C2 DE 22 20 22 C2 E5 22 20 22 C2 EA 22 0D 0A 20 20 " +
1026aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 C2 ED 22 20 22 C2 F3 22 20 22 C2 F5 22 20 22 C2 FA 22 20 22 C2 " +
1027aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "FC 22 20 22 C3 A2 22 0D 0A 20 20 20 20 20 20 22 C3 A9 22 20 22 C3 B7 22 20 22 " +
1028aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C3 C0 22 20 22 C3 C5 22 20 22 C3 C9 22 20 22 C3 D7 22 0D 0A 20 20 20 20 20 20 " +
1029aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C3 DC 22 20 22 C3 F4 22 20 22 C3 F7 22 20 22 C4 A6 22 20 22 C4 AA 22 20 22 " +
1030aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C4 AC 22 0D 0A 20 20 20 20 20 20 22 C4 AD 22 20 22 C4 B7 22 20 22 C4 BE 22 20 " +
1031aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C4 C2 22 20 22 C4 C3 22 20 22 C4 C7 22 0D 0A 20 20 20 20 20 20 22 C4 C8 22 " +
1032aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C4 C9 22 20 22 C4 CE 22 20 22 C4 CF 22 20 22 C4 DA 22 20 22 C4 DD 22 0D " +
1033aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0A 20 20 20 20 20 20 22 C4 E1 22 20 22 C4 EA 22 20 22 C4 EE 22 20 22 C4 F9 22 " +
1034aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C4 FE 22 20 22 C5 A6 22 0D 0A 20 20 20 20 20 20 22 C5 A9 22 20 22 C5 AC " +
1035aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C5 B5 22 20 22 C5 B7 22 20 22 C5 C1 22 20 22 C5 C9 22 0D 0A 20 20 20 " +
1036aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 22 C5 CB 22 20 22 C5 D3 22 20 22 C5 E0 22 20 22 C5 E5 22 20 22 C5 ED " +
1037aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 C5 EE 22 0D 0A 20 20 20 20 20 20 22 C6 A4 22 20 22 C6 BD 22 20 22 C6 " +
1038aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C3 22 20 22 C6 D5 22 20 22 C6 E1 22 20 22 C6 E6 22 0D 0A 20 20 20 20 20 20 22 " +
1039aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C6 EB 22 20 22 C6 E4 22 20 22 C6 F5 22 20 22 C7 A1 22 20 22 C7 AE 22 20 22 C7 " +
1040aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "BF 22 0D 0A 20 20 20 20 20 20 22 C7 C7 22 20 22 C7 D0 22 20 22 C7 D5 22 20 22 " +
1041aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C7 D9 22 20 22 C7 ED 22 20 22 C7 F0 22 0D 0A 20 20 20 20 20 20 22 C7 F3 22 20 " +
1042aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C8 B4 22 20 22 C8 C8 22 20 22 C8 E5 22 20 22 C8 F4 22 20 22 C8 F6 22 0D 0A " +
1043aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 20 22 C8 F8 22 20 22 C8 FB 22 20 22 C8 FC 22 20 22 C9 A3 22 20 " +
1044aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 C9 AA 22 20 22 C9 AD 22 0D 0A 20 20 20 20 20 20 22 C9 AF 22 20 22 C9 B3 22 " +
1045aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 C9 BA 22 20 22 C9 BD 22 20 22 C9 DC 22 20 22 C9 E1 22 0D 0A 20 20 20 20 " +
1046aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 22 C9 EA 22 20 22 CA A2 22 20 22 CA A9 22 20 22 CA B2 22 20 22 CA B7 22 " +
1047aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 CA BF 22 0D 0A 20 20 20 20 20 20 22 CA E6 22 20 22 CB B9 22 20 22 CB BC " +
1048aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 CB BE 22 20 22 CB BF 22 20 22 CB C9 22 0D 0A 20 20 20 20 20 20 22 CB " +
1049aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D5 22 20 22 CB F7 22 20 22 CB FE 22 20 22 CC A9 22 20 22 CC AB 22 20 22 CC B9 " +
1050aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 0D 0A 20 20 20 20 20 20 22 CC C0 22 20 22 CC C6 22 20 22 CC D5 22 20 22 CC " +
1051aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D1 22 20 22 CC D8 22 20 22 CC E8 22 0D 0A 20 20 20 20 20 20 22 CC FA 22 20 22 " +
1052aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CD A1 22 20 22 CD A2 22 20 22 CD A8 22 20 22 CD BC 22 20 22 CD BD 22 0D 0A 20 " +
1053aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 20 22 CD C2 22 20 22 CD CB 22 20 22 CD D0 22 20 22 CD DF 22 20 22 " +
1054aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "CD F2 22 20 22 CD FA 22 0D 0A 20 20 20 20 20 20 22 CD FE 22 20 22 CE A4 22 20 " +
1055aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 CE AC 22 20 22 CE B0 22 20 22 CE BA 22 20 22 CE C0 22 0D 0A 20 20 20 20 20 " +
1056aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 CE C2 22 20 22 CE C4 22 20 22 CE CC 22 20 22 CE D6 22 20 22 CE DA 22 20 " +
1057aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 CE E4 22 0D 0A 20 20 20 20 20 20 22 CE E9 22 20 22 CE EE 22 20 22 CE F7 22 " +
1058aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 CE FD 22 20 22 CF A3 22 20 22 CF AF 22 0D 0A 20 20 20 20 20 20 22 CF C4 " +
1059aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 CF E3 22 20 22 CF FE 22 20 22 D0 A4 22 20 22 D0 AA 22 20 22 D0 BB 22 " +
1060aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 20 20 20 20 20 20 22 D0 C0 22 20 22 D0 C1 22 20 22 D0 C2 22 20 22 D0 CB " +
1061aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 D0 D2 22 20 22 D0 DD 22 0D 0A 20 20 20 20 20 20 22 D0 DE 22 20 22 D0 " +
1062aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "F5 22 20 22 D1 A9 22 20 22 D1 C7 22 20 22 E6 AB 22 20 22 D1 EF 22 0D 0A 20 20 " +
1063aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 20 22 D1 F4 22 20 22 D2 AE 22 20 22 D2 B6 22 20 22 D2 C0 22 20 22 D2 " +
1064aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "C1 22 20 22 D2 D4 22 0D 0A 20 20 20 20 20 20 22 D2 D7 22 20 22 D2 F2 22 20 22 " +
1065aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D3 A2 22 20 22 D3 C0 22 20 22 D3 C8 22 20 22 D3 D0 22 0D 0A 20 20 20 20 20 20 " +
1066aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 D3 D1 22 20 22 D3 D7 22 20 22 D3 F4 22 20 22 D4 BC 22 20 22 D4 DE 22 20 22 " +
1067aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "D4 F3 22 0D 0A 20 20 20 20 20 20 22 D4 F6 22 20 22 D4 F8 22 20 22 D4 FA 22 20 " +
1068aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 D5 B2 22 20 22 D5 E4 22 20 22 D5 FD 22 0D 0A 20 20 20 20 20 20 22 D6 CE 22 " +
1069aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 D6 DC 22 20 22 D6 EC 22 20 22 D7 BF 22 20 22 D7 C8 22 20 22 D7 CC 22 0D " +
1070aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0A 20 20 20 20 20 20 22 D7 D3 22 20 22 D7 E6 22 20 22 D7 F4 22 20 22 DA F7 22 " +
1071aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 22 E1 AF 22 20 22 E7 D1 22 0D 0A 20 20 20 20 20 20 22 E7 EA 22 20 22 E8 A7 " +
1072aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "22 20 22 E9 A6 22 20 22 EB F8 22 20 22 EC B3 22 20 22 F1 E3 22 0D 0A 20 20 20 " +
1073aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 20 22 F7 EB 22 20 22 F7 EC 22 0D 0A 20 20 20 20 20 20 29 29 0D 0A 0D 0A " +
1074aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "0D 0A 28 64 65 66 75 6E 20 7A 68 2D 6E 61 6D 65 2D 73 75 66 66 69 78 3F 20 28 " +
1075aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "73 74 72 69 6E 67 29 0D 0A 20 20 28 6D 65 6D 62 65 72 20 73 74 72 69 6E 67 20 " +
1076aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "2A 7A 68 2D 6E 61 6D 65 2D 66 69 6E 61 6C 2D 63 68 61 72 73 2A 20 3A 74 65 73 " +
1077aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "74 20 23 27 6D 61 74 63 68 69 6E 67 2D 73 75 66 66 69 78 3F 29 29 0D 0A 0D 0A " +
1078aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "28 64 65 66 75 6E 20 7A 68 2D 6E 61 6D 65 2D 70 72 65 66 69 78 3F 20 28 73 74 " +
1079aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "72 69 6E 67 29 0D 0A 20 20 28 6D 65 6D 62 65 72 20 73 74 72 69 6E 67 20 2A 7A " +
1080aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "68 2D 6E 61 6D 65 2D 69 6E 69 74 69 61 6C 2D 63 68 61 72 73 2A 20 3A 74 65 73 " +
1081aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "74 20 23 27 6D 61 74 63 68 69 6E 67 2D 70 72 65 66 69 78 3F 29 29 0D 0A 0D 0A " +
1082aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "28 64 65 66 75 6E 20 7A 68 2D 6E 61 6D 65 2D 69 6E 66 69 78 3F 20 28 73 74 72 " +
1083aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "69 6E 67 29 0D 0A 20 20 28 6D 65 6D 62 65 72 20 73 74 72 69 6E 67 20 2A 7A 68 " +
1084aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "2D 6E 61 6D 65 2D 6D 65 64 69 61 6C 2D 63 68 61 72 73 2A 20 3A 74 65 73 74 20 " +
1085aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "23 27 6D 61 74 63 68 69 6E 67 2D 73 75 62 73 74 72 69 6E 67 3F 29 29 0D 0A 09 " +
1086aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                "20 20 0D 0A");
1087aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      }
1088aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1089aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      private static byte[] createData2()
1090aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      {
1091aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          return bytesFromString("0A D0 A1 CA B1 20 3B 3B 20 48 6F 75 72 28 73 29 0A D0 C7 C6 DA 20 3B 3B 20 57 " +
1092aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                 "65 65 6B 28 73 29 0A B5 B1 B5 D8 20 CA B1 BC E4 20 3B 3B 20 6C 6F 63 61 6C 20 " +
1093aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                 "74 69 6D 65 0A");
1094aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      }
1095aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1096aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1097aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      /**
1098aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin       * Creates a byte array by decoding the hex string passed in.
1099aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin       *
1100aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin       * @param data hex string data.
1101aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin       * @return binary data in a byte array.
1102aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin       */
1103aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      private static byte[] bytesFromString(String data)
1104aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      {
1105aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          ByteArrayOutputStream out = new ByteArrayOutputStream();
1106aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          int index = 0;
1107aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          while (index < data.length())
1108aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          {
1109aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin           char[] number = new char[2];
1110aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin              number[0] = data.charAt(index++);
1111aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin              if (Character.isLetterOrDigit(number[0]))
1112aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin              {
1113aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                  number[1] = data.charAt(index++);
1114aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                  if (!Character.isLetterOrDigit(number[1]))
1115aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                  {
1116aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                      throw new IllegalArgumentException("Invalid input: " + data);
1117aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                  }
1118aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                  out.write(Integer.parseInt(new String(number), 16));
1119aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin              }
1120aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          }
1121aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1122aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          return out.toByteArray();
1123aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      }
1124aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      //
1125aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      // End of Bug #8309 Test Case
1126aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin      //
1127aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1128aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1129f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1130aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestBug9267() {
1131aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Test a long input of Lam Alef characters for CharsetRecog_IBM420_ar.
1132aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Bug 9267 was an array out of bounds problem in the unshaping code for these.
1133aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte [] input = new byte [7700];
1134aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int i;
1135aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (i=0; i<input.length; i++) {
1136aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin          input[i] = (byte)0xb2;
1137aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1138aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
1139aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(input);
1140aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.detect();
1141aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1142aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1143f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1144aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestBug6954 () throws Exception {
1145aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Ticket 6954 - trouble with the haveC1Bytes flag that is used to distinguish between
1146aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //  similar Windows and non-Windows SBCS encodings. State was kept in the shared
1147aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //  Charset Recognizer objects, and could be overwritten.
1148aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String sISO = "This is a small sample of some English text. Just enough to be sure that it detects correctly.";
1149aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String sWindows = "This is another small sample of some English text. Just enough to be sure that it detects correctly."
1150aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        + "It also includes some \u201CC1\u201D bytes.";
1151aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1152aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] bISO     = sISO.getBytes("ISO-8859-1");
1153aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] bWindows = sWindows.getBytes("windows-1252");
1154aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1155aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // First do a plain vanilla detect of 1252 text
1156aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1157aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector csd1 = new CharsetDetector();
1158aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        csd1.setText(bWindows);
1159aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch match1 = csd1.detect();
1160aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String name1 = match1.getName();
1161aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("Initial detection of charset", "windows-1252", name1);
1162aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1163aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Next, using a completely separate detector, detect some 8859-1 text
1164aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1165aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector csd2 = new CharsetDetector();
1166aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        csd2.setText(bISO);
1167aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch match2 = csd2.detect();
1168aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String name2 = match2.getName();
1169aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("Initial use of second detector", "ISO-8859-1", name2);
1170aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1171aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Recheck the 1252 results from the first detector, which should not have been
1172aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        //  altered by the use of a different detector.
1173aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1174aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        name1 = match1.getName();
1175aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        assertEquals("Wrong charset name after running a second charset detector", "windows-1252", name1);
1176aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1177aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1178f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1179aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestBug6889() {
1180aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Verify that CharsetDetector.detectAll() does not return the same encoding multiple times.
1181aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String text =
1182aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            "This is a small sample of some English text. Just enough to be sure that it detects correctly.";
1183aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        byte[] textBytes;
1184aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
1185aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            textBytes = text.getBytes("ISO-8859-1");
1186aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1187aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        catch (Exception e) {
1188aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            fail("Unexpected exception " + e.toString());
1189aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return;
1190aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1191aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1192aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetDetector det = new CharsetDetector();
1193aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        det.setText(textBytes);
1194aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        CharsetMatch matches[] = det.detectAll();
1195aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1196aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        HashSet<String> detectedEncodings = new HashSet<String>();
1197aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (CharsetMatch m: matches) {
1198aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            assertTrue("Charset " + m.getName() + " encountered before",
1199aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        detectedEncodings.add(m.getName()));
1200aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1201aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1202aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1203f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Test
1204aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    public void TestMultithreaded() {
1205aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String  s = "This is some random plain text to run charset detection on.";
1206aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        final byte [] bytes;
1207aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        try {
1208aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            bytes = s.getBytes("ISO-8859-1");
1209aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1210aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        catch (Exception e) {
1211aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            fail("Unexpected exception " + e.toString());
1212aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return;
1213aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1214aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1215aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        class WorkerThread extends Thread {
1216aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            WorkerThread(int num) {
1217aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                n = num;
1218aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
1219aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            private int n;
1220aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            public void run() {
1221aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // System.out.println("Thread " + n + " is running.");
1222aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                CharsetDetector det = new CharsetDetector();
1223aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                det.setText(bytes);
1224aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                for (int i=0; i<10000; i++) {
1225aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    CharsetMatch matches[] = det.detectAll();
1226aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    for (CharsetMatch m: matches) {
1227aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        assertNotNull("Failure in thread " + n, m);
1228aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
1229aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
1230aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // System.out.println("Thread " + n + " is finished.");
1231aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
1232aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1233aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1234aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        Thread threads[] = new Thread[10];
1235aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i=0; i<10; i++) {
1236aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            threads[i] = new WorkerThread(i);
1237aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            threads[i].start();
1238aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1239aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (Thread thread: threads) {
1240aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            try {
1241aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                thread.join();
1242aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } catch(Exception e) {
1243aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                fail("Unexpected exception " +  e.toString());
1244aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                return;
1245aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
1246aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
1247aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
1248aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1249aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
1250aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin}
1251