michael@0: const Ci = Components.interfaces; michael@0: const Cc = Components.classes; michael@0: const Cr = Components.results; michael@0: michael@0: let testnum = 0; michael@0: let factory; michael@0: michael@0: function parserForFile(filename) { michael@0: let parser = null; michael@0: try { michael@0: let file = do_get_file(filename); michael@0: do_check_true(!!file); michael@0: parser = factory.createINIParser(file); michael@0: do_check_true(!!parser); michael@0: } catch(e) { michael@0: dump("INFO | caught error: " + e); michael@0: // checkParserOutput will handle a null parser when it's expected. michael@0: } michael@0: return parser; michael@0: michael@0: } michael@0: michael@0: function checkParserOutput(parser, expected) { michael@0: // If the expected output is null, we expect the parser to have michael@0: // failed (and vice-versa). michael@0: if (!parser || !expected) { michael@0: do_check_eq(parser, null); michael@0: do_check_eq(expected, null); michael@0: return; michael@0: } michael@0: michael@0: let output = getParserOutput(parser); michael@0: for (let section in expected) { michael@0: do_check_true(section in output); michael@0: for (let key in expected[section]) { michael@0: do_check_true(key in output[section]); michael@0: do_check_eq(output[section][key], expected[section][key]); michael@0: delete output[section][key]; michael@0: } michael@0: for (let key in output[section]) michael@0: do_check_eq(key, "wasn't expecting this key!"); michael@0: delete output[section]; michael@0: } michael@0: for (let section in output) michael@0: do_check_eq(section, "wasn't expecting this section!"); michael@0: } michael@0: michael@0: function getParserOutput(parser) { michael@0: let output = {}; michael@0: michael@0: let sections = parser.getSections(); michael@0: do_check_true(!!sections); michael@0: while (sections.hasMore()) { michael@0: let section = sections.getNext(); michael@0: do_check_false(section in output); // catch dupes michael@0: output[section] = {}; michael@0: michael@0: let keys = parser.getKeys(section); michael@0: do_check_true(!!keys); michael@0: while (keys.hasMore()) { michael@0: let key = keys.getNext(); michael@0: do_check_false(key in output[section]); // catch dupes michael@0: let value = parser.getString(section, key); michael@0: output[section][key] = value; michael@0: } michael@0: } michael@0: return output; michael@0: } michael@0: michael@0: function run_test() { michael@0: try { michael@0: michael@0: let testdata = [ michael@0: { filename: "data/iniparser01.ini", reference: {} }, michael@0: { filename: "data/iniparser02.ini", reference: {} }, michael@0: { filename: "data/iniparser03.ini", reference: {} }, michael@0: { filename: "data/iniparser04.ini", reference: {} }, michael@0: { filename: "data/iniparser05.ini", reference: {} }, michael@0: { filename: "data/iniparser06.ini", reference: {} }, michael@0: { filename: "data/iniparser07.ini", reference: {} }, michael@0: { filename: "data/iniparser08.ini", reference: { section1: { name1: "" }} }, michael@0: { filename: "data/iniparser09.ini", reference: { section1: { name1: "value1" } } }, michael@0: { filename: "data/iniparser10.ini", reference: { section1: { name1: "value1" } } }, michael@0: { filename: "data/iniparser11.ini", reference: { section1: { name1: "value1" } } }, michael@0: { filename: "data/iniparser12.ini", reference: { section1: { name1: "value1" } } }, michael@0: { filename: "data/iniparser13.ini", reference: { section1: { name1: "value1" } } }, michael@0: { filename: "data/iniparser14.ini", reference: michael@0: { section1: { name1: "value1", name2: "value2" }, michael@0: section2: { name1: "value1", name2: "foopy" }} }, michael@0: { filename: "data/iniparser15.ini", reference: michael@0: { section1: { name1: "newValue1" }, michael@0: section2: { name1: "foopy" }} }, michael@0: { filename: "data/iniparser16.ini", reference: michael@0: { "☺♫": { "♫": "☻", "♪": "♥" }, michael@0: "☼": { "♣": "♠", "♦": "♥" }} }, michael@0: michael@0: ]; michael@0: michael@0: testdata.push( { filename: "data/iniparser01-utf8BOM.ini", michael@0: reference: testdata[0].reference } ); michael@0: testdata.push( { filename: "data/iniparser02-utf8BOM.ini", michael@0: reference: testdata[1].reference } ); michael@0: testdata.push( { filename: "data/iniparser03-utf8BOM.ini", michael@0: reference: testdata[2].reference } ); michael@0: testdata.push( { filename: "data/iniparser04-utf8BOM.ini", michael@0: reference: testdata[3].reference } ); michael@0: testdata.push( { filename: "data/iniparser05-utf8BOM.ini", michael@0: reference: testdata[4].reference } ); michael@0: testdata.push( { filename: "data/iniparser06-utf8BOM.ini", michael@0: reference: testdata[5].reference } ); michael@0: testdata.push( { filename: "data/iniparser07-utf8BOM.ini", michael@0: reference: testdata[6].reference } ); michael@0: testdata.push( { filename: "data/iniparser08-utf8BOM.ini", michael@0: reference: testdata[7].reference } ); michael@0: testdata.push( { filename: "data/iniparser09-utf8BOM.ini", michael@0: reference: testdata[8].reference } ); michael@0: testdata.push( { filename: "data/iniparser10-utf8BOM.ini", michael@0: reference: testdata[9].reference } ); michael@0: testdata.push( { filename: "data/iniparser11-utf8BOM.ini", michael@0: reference: testdata[10].reference } ); michael@0: testdata.push( { filename: "data/iniparser12-utf8BOM.ini", michael@0: reference: testdata[11].reference } ); michael@0: testdata.push( { filename: "data/iniparser13-utf8BOM.ini", michael@0: reference: testdata[12].reference } ); michael@0: testdata.push( { filename: "data/iniparser14-utf8BOM.ini", michael@0: reference: testdata[13].reference } ); michael@0: testdata.push( { filename: "data/iniparser15-utf8BOM.ini", michael@0: reference: testdata[14].reference } ); michael@0: testdata.push( { filename: "data/iniparser16-utf8BOM.ini", michael@0: reference: testdata[15].reference } ); michael@0: michael@0: let os = Cc["@mozilla.org/xre/app-info;1"] michael@0: .getService(Ci.nsIXULRuntime).OS; michael@0: if("WINNT" === os) { michael@0: testdata.push( { filename: "data/iniparser01-utf16leBOM.ini", michael@0: reference: testdata[0].reference } ); michael@0: testdata.push( { filename: "data/iniparser02-utf16leBOM.ini", michael@0: reference: testdata[1].reference } ); michael@0: testdata.push( { filename: "data/iniparser03-utf16leBOM.ini", michael@0: reference: testdata[2].reference } ); michael@0: testdata.push( { filename: "data/iniparser04-utf16leBOM.ini", michael@0: reference: testdata[3].reference } ); michael@0: testdata.push( { filename: "data/iniparser05-utf16leBOM.ini", michael@0: reference: testdata[4].reference } ); michael@0: testdata.push( { filename: "data/iniparser06-utf16leBOM.ini", michael@0: reference: testdata[5].reference } ); michael@0: testdata.push( { filename: "data/iniparser07-utf16leBOM.ini", michael@0: reference: testdata[6].reference } ); michael@0: testdata.push( { filename: "data/iniparser08-utf16leBOM.ini", michael@0: reference: testdata[7].reference } ); michael@0: testdata.push( { filename: "data/iniparser09-utf16leBOM.ini", michael@0: reference: testdata[8].reference } ); michael@0: testdata.push( { filename: "data/iniparser10-utf16leBOM.ini", michael@0: reference: testdata[9].reference } ); michael@0: testdata.push( { filename: "data/iniparser11-utf16leBOM.ini", michael@0: reference: testdata[10].reference } ); michael@0: testdata.push( { filename: "data/iniparser12-utf16leBOM.ini", michael@0: reference: testdata[11].reference } ); michael@0: testdata.push( { filename: "data/iniparser13-utf16leBOM.ini", michael@0: reference: testdata[12].reference } ); michael@0: testdata.push( { filename: "data/iniparser14-utf16leBOM.ini", michael@0: reference: testdata[13].reference } ); michael@0: testdata.push( { filename: "data/iniparser15-utf16leBOM.ini", michael@0: reference: testdata[14].reference } ); michael@0: testdata.push( { filename: "data/iniparser16-utf16leBOM.ini", michael@0: reference: testdata[15].reference } ); michael@0: } michael@0: michael@0: /* ========== 0 ========== */ michael@0: factory = Cc["@mozilla.org/xpcom/ini-processor-factory;1"]. michael@0: getService(Ci.nsIINIParserFactory); michael@0: do_check_true(!!factory); michael@0: michael@0: // Test reading from a variety of files. While we're at it, write out each one michael@0: // and read it back to ensure that nothing changed. michael@0: while (testnum < testdata.length) { michael@0: dump("\nINFO | test #" + ++testnum); michael@0: let filename = testdata[testnum -1].filename; michael@0: dump(", filename " + filename + "\n"); michael@0: let parser = parserForFile(filename); michael@0: checkParserOutput(parser, testdata[testnum - 1].reference); michael@0: if (!parser) michael@0: continue; michael@0: do_check_true(parser instanceof Ci.nsIINIParserWriter); michael@0: // write contents out to a new file michael@0: let newfilename = filename + ".new"; michael@0: let newfile = do_get_file(filename); michael@0: newfile.leafName += ".new"; michael@0: parser.writeFile(newfile); michael@0: // read new file and make sure the contents are the same. michael@0: parser = parserForFile(newfilename); michael@0: checkParserOutput(parser, testdata[testnum - 1].reference); michael@0: // cleanup after the test michael@0: newfile.remove(false); michael@0: } michael@0: michael@0: dump("INFO | test #" + ++testnum + "\n"); michael@0: michael@0: // test writing to a new file. michael@0: let newfile = do_get_file("data/"); michael@0: newfile.append("nonexistent-file.ini"); michael@0: if (newfile.exists()) michael@0: newfile.remove(false); michael@0: do_check_false(newfile.exists()); michael@0: michael@0: let parser = factory.createINIParser(newfile); michael@0: do_check_true(!!parser); michael@0: do_check_true(parser instanceof Ci.nsIINIParserWriter); michael@0: checkParserOutput(parser, {}); michael@0: parser.writeFile(); michael@0: do_check_true(newfile.exists()); michael@0: michael@0: // test adding a new section and new key michael@0: parser.setString("section", "key", "value"); michael@0: parser.writeFile(); michael@0: do_check_true(newfile.exists()); michael@0: checkParserOutput(parser, {section: {key: "value"} }); michael@0: // read it in again, check for same data. michael@0: parser = parserForFile("data/nonexistent-file.ini"); michael@0: checkParserOutput(parser, {section: {key: "value"} }); michael@0: // cleanup after the test michael@0: newfile.remove(false); michael@0: michael@0: dump("INFO | test #" + ++testnum + "\n"); michael@0: michael@0: // test modifying a existing key's value (in an existing section) michael@0: parser = parserForFile("data/iniparser09.ini"); michael@0: checkParserOutput(parser, {section1: {name1: "value1"} }); michael@0: michael@0: do_check_true(parser instanceof Ci.nsIINIParserWriter); michael@0: parser.setString("section1", "name1", "value2"); michael@0: checkParserOutput(parser, {section1: {name1: "value2"} }); michael@0: michael@0: dump("INFO | test #" + ++testnum + "\n"); michael@0: michael@0: // test trying to set illegal characters michael@0: let caughtError; michael@0: caughtError = false; michael@0: checkParserOutput(parser, {section1: {name1: "value2"} }); michael@0: michael@0: // Bad characters in section name michael@0: try { parser.SetString("bad\0", "ok", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("bad\r", "ok", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("bad\n", "ok", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("bad[", "ok", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("bad]", "ok", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: michael@0: // Bad characters in key name michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "bad\0", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "bad\r", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "bad\n", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "bad=", "ok"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: michael@0: // Bad characters in value michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "ok", "bad\0"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "ok", "bad\r"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "ok", "bad\n"); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: caughtError = false; michael@0: try { parser.SetString("ok", "ok", "bad="); } catch (e) { caughtError = true; } michael@0: do_check_true(caughtError); michael@0: michael@0: } catch(e) { michael@0: throw "FAILED in test #" + testnum + " -- " + e; michael@0: } michael@0: }