diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /xpcom/tests/unit | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xpcom/tests/unit')
103 files changed, 3936 insertions, 0 deletions
diff --git a/xpcom/tests/unit/data/SmallApp.app/Contents/Info.plist b/xpcom/tests/unit/data/SmallApp.app/Contents/Info.plist new file mode 100644 index 0000000000..8388fa2a55 --- /dev/null +++ b/xpcom/tests/unit/data/SmallApp.app/Contents/Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>SmallApp</string> + <key>CFBundleIdentifier</key> + <string>com.yourcompany.SmallApp</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>SmallApp</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/xpcom/tests/unit/data/SmallApp.app/Contents/MacOS/SmallApp b/xpcom/tests/unit/data/SmallApp.app/Contents/MacOS/SmallApp Binary files differnew file mode 100755 index 0000000000..c821003d34 --- /dev/null +++ b/xpcom/tests/unit/data/SmallApp.app/Contents/MacOS/SmallApp diff --git a/xpcom/tests/unit/data/SmallApp.app/Contents/PkgInfo b/xpcom/tests/unit/data/SmallApp.app/Contents/PkgInfo new file mode 100644 index 0000000000..bd04210fb4 --- /dev/null +++ b/xpcom/tests/unit/data/SmallApp.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPL????
\ No newline at end of file diff --git a/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/InfoPlist.strings b/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 0000000000..5e45963c38 --- /dev/null +++ b/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/InfoPlist.strings diff --git a/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/MainMenu.nib/designable.nib b/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/MainMenu.nib/designable.nib new file mode 100644 index 0000000000..59f8803c5d --- /dev/null +++ b/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/MainMenu.nib/designable.nib @@ -0,0 +1,343 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02"> + <data> + <int key="IBDocument.SystemTarget">0</int> + <string key="IBDocument.SystemVersion">9E17</string> + <string key="IBDocument.InterfaceBuilderVersion">644</string> + <string key="IBDocument.AppKitVersion">949.33</string> + <string key="IBDocument.HIToolboxVersion">352.00</string> + <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="29"/> + </object> + <object class="NSArray" key="IBDocument.PluginDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilderKit</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1048"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSCustomObject" id="1021"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSCustomObject" id="1014"> + <string key="NSClassName">FirstResponder</string> + </object> + <object class="NSCustomObject" id="1050"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSMenu" id="649796088"> + <string key="NSTitle">AMainMenu</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="694149608"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">NewApplication</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <object class="NSCustomResource" key="NSOnImage" id="35465992"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuCheckmark</string> + </object> + <object class="NSCustomResource" key="NSMixedImage" id="591987212"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuMixedState</string> + </object> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="110575045"> + <string key="NSTitle">NewApplication</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="632727374"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">Quit NewApplication</string> + <string key="NSKeyEquiv">q</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="591987212"/> + </object> + </object> + <string key="NSName">_NSAppleMenu</string> + </object> + </object> + <object class="NSMenuItem" id="379814623"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">File</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="591987212"/> + </object> + <object class="NSMenuItem" id="952259628"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Edit</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="591987212"/> + </object> + <object class="NSMenuItem" id="626404410"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Format</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="591987212"/> + </object> + <object class="NSMenuItem" id="586577488"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">View</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="591987212"/> + </object> + <object class="NSMenuItem" id="713487014"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Window</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="591987212"/> + </object> + <object class="NSMenuItem" id="391199113"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Help</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="591987212"/> + </object> + </object> + <string key="NSName">_NSMainMenu</string> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">terminate:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="632727374"/> + </object> + <int key="connectionID">369</int> + </object> + </object> + <object class="IBMutableOrderedSet" key="objectRecords"> + <object class="NSArray" key="orderedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <object class="NSArray" key="object" id="1049"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="children" ref="1048"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-2</int> + <reference key="object" ref="1021"/> + <reference key="parent" ref="1049"/> + <string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-1</int> + <reference key="object" ref="1014"/> + <reference key="parent" ref="1049"/> + <string key="objectName">First Responder</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-3</int> + <reference key="object" ref="1050"/> + <reference key="parent" ref="1049"/> + <string key="objectName">Application</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">29</int> + <reference key="object" ref="649796088"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="713487014"/> + <reference ref="694149608"/> + <reference ref="391199113"/> + <reference ref="952259628"/> + <reference ref="379814623"/> + <reference ref="586577488"/> + <reference ref="626404410"/> + </object> + <reference key="parent" ref="1049"/> + <string key="objectName">MainMenu</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">19</int> + <reference key="object" ref="713487014"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">56</int> + <reference key="object" ref="694149608"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="110575045"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">103</int> + <reference key="object" ref="391199113"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="parent" ref="649796088"/> + <string key="objectName">1</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">217</int> + <reference key="object" ref="952259628"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">83</int> + <reference key="object" ref="379814623"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">57</int> + <reference key="object" ref="110575045"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="632727374"/> + </object> + <reference key="parent" ref="694149608"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">136</int> + <reference key="object" ref="632727374"/> + <reference key="parent" ref="110575045"/> + <string key="objectName">1111</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">295</int> + <reference key="object" ref="586577488"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">299</int> + <reference key="object" ref="626404410"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="parent" ref="649796088"/> + </object> + </object> + </object> + <object class="NSMutableDictionary" key="flattenedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMutableArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>-1.IBPluginDependency</string> + <string>-2.IBPluginDependency</string> + <string>-3.IBPluginDependency</string> + <string>103.IBPluginDependency</string> + <string>103.ImportedFromIB2</string> + <string>136.IBPluginDependency</string> + <string>136.ImportedFromIB2</string> + <string>19.IBPluginDependency</string> + <string>19.ImportedFromIB2</string> + <string>217.IBPluginDependency</string> + <string>217.ImportedFromIB2</string> + <string>29.IBEditorWindowLastContentRect</string> + <string>29.IBPluginDependency</string> + <string>29.ImportedFromIB2</string> + <string>29.WindowOrigin</string> + <string>29.editorWindowContentRectSynchronizationRect</string> + <string>295.IBPluginDependency</string> + <string>299.IBPluginDependency</string> + <string>56.IBPluginDependency</string> + <string>56.ImportedFromIB2</string> + <string>57.IBEditorWindowLastContentRect</string> + <string>57.IBPluginDependency</string> + <string>57.ImportedFromIB2</string> + <string>57.editorWindowContentRectSynchronizationRect</string> + <string>83.IBPluginDependency</string> + <string>83.ImportedFromIB2</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilderKit</string> + <string>com.apple.InterfaceBuilderKit</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1" id="9"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <reference ref="9"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <reference ref="9"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <reference ref="9"/> + <string>{{0, 975}, {478, 20}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <reference ref="9"/> + <string>{74, 862}</string> + <string>{{6, 978}, {478, 20}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <reference ref="9"/> + <string>{{12, 952}, {218, 23}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <reference ref="9"/> + <string>{{23, 794}, {245, 183}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <reference ref="9"/> + </object> + </object> + <object class="NSMutableDictionary" key="unlocalizedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="activeLocalization"/> + <object class="NSMutableDictionary" key="localizations"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="sourceID"/> + <int key="maxID">374</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"/> + <int key="IBDocument.localizationMode">0</int> + <string key="IBDocument.LastKnownRelativeProjectPath">../SmallApp.xcodeproj</string> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + </data> +</archive> diff --git a/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib b/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib Binary files differnew file mode 100644 index 0000000000..bb27d4a5d6 --- /dev/null +++ b/xpcom/tests/unit/data/SmallApp.app/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib diff --git a/xpcom/tests/unit/data/bug121341-2.properties b/xpcom/tests/unit/data/bug121341-2.properties new file mode 100644 index 0000000000..f7885e4fca --- /dev/null +++ b/xpcom/tests/unit/data/bug121341-2.properties @@ -0,0 +1,9 @@ +# this file contains invalid UTF-8 sequence +# no property should be loaded + +1 = test + +# property with invalid UTF-8 sequence (0xa0) +2 = a b + +3 = test2 diff --git a/xpcom/tests/unit/data/bug121341.properties b/xpcom/tests/unit/data/bug121341.properties new file mode 100644 index 0000000000..b45fc9698c --- /dev/null +++ b/xpcom/tests/unit/data/bug121341.properties @@ -0,0 +1,68 @@ +# simple check +1=abc +# test whitespace trimming in key and value + 2 = xy +# test parsing of escaped values +3 = \u1234\t\r\n\uAB\ +\u1\n +# test multiline properties +4 = this is \ +multiline property +5 = this is \ + another multiline property +# property with DOS EOL
+6 = test\u0036
+# test multiline property with with DOS EOL +7 = yet another multi\
+ line propery
+# trimming should not trim escaped whitespaces +8 = \ttest5\u0020 +# another variant of #8 +9 = \ test6\t +# test UTF-8 encoded property/value +10aሴb = cì·¯d +# next property should test unicode escaping at the boundary of parsing buffer +# buffer size is expected to be 4096 so add comments to get to this offset +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +################################################################################ +############################################################################### +11 = \uABCD diff --git a/xpcom/tests/unit/data/iniparser01-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser01-utf16leBOM.ini new file mode 100644 index 0000000000..46b134b197 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser01-utf16leBOM.ini @@ -0,0 +1 @@ +ÿþ
\ No newline at end of file diff --git a/xpcom/tests/unit/data/iniparser01-utf8BOM.ini b/xpcom/tests/unit/data/iniparser01-utf8BOM.ini new file mode 100644 index 0000000000..5f282702bb --- /dev/null +++ b/xpcom/tests/unit/data/iniparser01-utf8BOM.ini @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/xpcom/tests/unit/data/iniparser01.ini b/xpcom/tests/unit/data/iniparser01.ini new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser01.ini diff --git a/xpcom/tests/unit/data/iniparser02-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser02-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..49cc8ef0e1 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser02-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser02-utf8BOM.ini b/xpcom/tests/unit/data/iniparser02-utf8BOM.ini new file mode 100644 index 0000000000..e02abfc9b0 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser02-utf8BOM.ini @@ -0,0 +1 @@ + diff --git a/xpcom/tests/unit/data/iniparser02.ini b/xpcom/tests/unit/data/iniparser02.ini new file mode 100644 index 0000000000..d3f5a12faa --- /dev/null +++ b/xpcom/tests/unit/data/iniparser02.ini @@ -0,0 +1 @@ +
diff --git a/xpcom/tests/unit/data/iniparser03-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser03-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..05255100a2 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser03-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser03-utf8BOM.ini b/xpcom/tests/unit/data/iniparser03-utf8BOM.ini new file mode 100644 index 0000000000..b76e44e194 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser03-utf8BOM.ini @@ -0,0 +1 @@ +[] diff --git a/xpcom/tests/unit/data/iniparser03.ini b/xpcom/tests/unit/data/iniparser03.ini new file mode 100644 index 0000000000..60b0742537 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser03.ini @@ -0,0 +1 @@ +[]
diff --git a/xpcom/tests/unit/data/iniparser04-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser04-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..e95d971134 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser04-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser04-utf8BOM.ini b/xpcom/tests/unit/data/iniparser04-utf8BOM.ini new file mode 100644 index 0000000000..47ef32c0a9 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser04-utf8BOM.ini @@ -0,0 +1 @@ +[section1] diff --git a/xpcom/tests/unit/data/iniparser04.ini b/xpcom/tests/unit/data/iniparser04.ini new file mode 100644 index 0000000000..23a50d155f --- /dev/null +++ b/xpcom/tests/unit/data/iniparser04.ini @@ -0,0 +1 @@ +[section1]
diff --git a/xpcom/tests/unit/data/iniparser05-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser05-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..a49491816c --- /dev/null +++ b/xpcom/tests/unit/data/iniparser05-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser05-utf8BOM.ini b/xpcom/tests/unit/data/iniparser05-utf8BOM.ini new file mode 100644 index 0000000000..eb33b5ccf1 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser05-utf8BOM.ini @@ -0,0 +1 @@ +[section1]junk diff --git a/xpcom/tests/unit/data/iniparser05.ini b/xpcom/tests/unit/data/iniparser05.ini new file mode 100644 index 0000000000..ade1373377 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser05.ini @@ -0,0 +1 @@ +[section1]junk
diff --git a/xpcom/tests/unit/data/iniparser06-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser06-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..e9023ac7c9 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser06-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser06-utf8BOM.ini b/xpcom/tests/unit/data/iniparser06-utf8BOM.ini new file mode 100644 index 0000000000..073d841cf3 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser06-utf8BOM.ini @@ -0,0 +1,2 @@ +[section1] + diff --git a/xpcom/tests/unit/data/iniparser06.ini b/xpcom/tests/unit/data/iniparser06.ini new file mode 100644 index 0000000000..c24821e6ed --- /dev/null +++ b/xpcom/tests/unit/data/iniparser06.ini @@ -0,0 +1,2 @@ +[section1]
+
diff --git a/xpcom/tests/unit/data/iniparser07-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser07-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..d1c167e6e3 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser07-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser07-utf8BOM.ini b/xpcom/tests/unit/data/iniparser07-utf8BOM.ini new file mode 100644 index 0000000000..38176d9444 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser07-utf8BOM.ini @@ -0,0 +1,2 @@ +[section1] +name1 diff --git a/xpcom/tests/unit/data/iniparser07.ini b/xpcom/tests/unit/data/iniparser07.ini new file mode 100644 index 0000000000..49816873b2 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser07.ini @@ -0,0 +1,2 @@ +[section1]
+name1
diff --git a/xpcom/tests/unit/data/iniparser08-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser08-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..e450566a0f --- /dev/null +++ b/xpcom/tests/unit/data/iniparser08-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser08-utf8BOM.ini b/xpcom/tests/unit/data/iniparser08-utf8BOM.ini new file mode 100644 index 0000000000..5fa7d2495c --- /dev/null +++ b/xpcom/tests/unit/data/iniparser08-utf8BOM.ini @@ -0,0 +1,2 @@ +[section1] +name1= diff --git a/xpcom/tests/unit/data/iniparser08.ini b/xpcom/tests/unit/data/iniparser08.ini new file mode 100644 index 0000000000..cfa15c9ffe --- /dev/null +++ b/xpcom/tests/unit/data/iniparser08.ini @@ -0,0 +1,2 @@ +[section1]
+name1=
diff --git a/xpcom/tests/unit/data/iniparser09-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser09-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..ef1da39e27 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser09-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser09-utf8BOM.ini b/xpcom/tests/unit/data/iniparser09-utf8BOM.ini new file mode 100644 index 0000000000..e3edce4d49 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser09-utf8BOM.ini @@ -0,0 +1,2 @@ +[section1] +name1=value1 diff --git a/xpcom/tests/unit/data/iniparser09.ini b/xpcom/tests/unit/data/iniparser09.ini new file mode 100644 index 0000000000..1c87762ba4 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser09.ini @@ -0,0 +1,2 @@ +[section1]
+name1=value1
diff --git a/xpcom/tests/unit/data/iniparser10-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser10-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..e5e70b6612 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser10-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser10-utf8BOM.ini b/xpcom/tests/unit/data/iniparser10-utf8BOM.ini new file mode 100644 index 0000000000..bda15fcc7b --- /dev/null +++ b/xpcom/tests/unit/data/iniparser10-utf8BOM.ini @@ -0,0 +1,3 @@ + +[section1] +name1=value1 diff --git a/xpcom/tests/unit/data/iniparser10.ini b/xpcom/tests/unit/data/iniparser10.ini new file mode 100644 index 0000000000..037fd79303 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser10.ini @@ -0,0 +1,3 @@ +
+[section1]
+name1=value1
diff --git a/xpcom/tests/unit/data/iniparser11-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser11-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..932d4004bc --- /dev/null +++ b/xpcom/tests/unit/data/iniparser11-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser11-utf8BOM.ini b/xpcom/tests/unit/data/iniparser11-utf8BOM.ini new file mode 100644 index 0000000000..78caafaba5 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser11-utf8BOM.ini @@ -0,0 +1,3 @@ +# comment +[section1] +name1=value1 diff --git a/xpcom/tests/unit/data/iniparser11.ini b/xpcom/tests/unit/data/iniparser11.ini new file mode 100644 index 0000000000..f8d573a284 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser11.ini @@ -0,0 +1,3 @@ +# comment
+[section1]
+name1=value1
diff --git a/xpcom/tests/unit/data/iniparser12-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser12-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..8a29127222 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser12-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser12-utf8BOM.ini b/xpcom/tests/unit/data/iniparser12-utf8BOM.ini new file mode 100644 index 0000000000..09ca62779d --- /dev/null +++ b/xpcom/tests/unit/data/iniparser12-utf8BOM.ini @@ -0,0 +1,3 @@ +[section1] +# [sectionBAD] +name1=value1 diff --git a/xpcom/tests/unit/data/iniparser12.ini b/xpcom/tests/unit/data/iniparser12.ini new file mode 100644 index 0000000000..2727940c09 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser12.ini @@ -0,0 +1,3 @@ +[section1]
+# [sectionBAD]
+name1=value1
diff --git a/xpcom/tests/unit/data/iniparser13-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser13-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..ebd9a51d3e --- /dev/null +++ b/xpcom/tests/unit/data/iniparser13-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser13-utf8BOM.ini b/xpcom/tests/unit/data/iniparser13-utf8BOM.ini new file mode 100644 index 0000000000..8c9499b669 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser13-utf8BOM.ini @@ -0,0 +1,3 @@ +[section1] +name1=value1 +# nameBAD=valueBAD diff --git a/xpcom/tests/unit/data/iniparser13.ini b/xpcom/tests/unit/data/iniparser13.ini new file mode 100644 index 0000000000..21d40b140c --- /dev/null +++ b/xpcom/tests/unit/data/iniparser13.ini @@ -0,0 +1,3 @@ +[section1]
+name1=value1
+# nameBAD=valueBAD
diff --git a/xpcom/tests/unit/data/iniparser14-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser14-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..bbc3413aa1 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser14-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser14-utf8BOM.ini b/xpcom/tests/unit/data/iniparser14-utf8BOM.ini new file mode 100644 index 0000000000..d109052c8d --- /dev/null +++ b/xpcom/tests/unit/data/iniparser14-utf8BOM.ini @@ -0,0 +1,6 @@ +[section1] +name1=value1 +name2=value2 +[section2] +name1=value1 +name2=foopy diff --git a/xpcom/tests/unit/data/iniparser14.ini b/xpcom/tests/unit/data/iniparser14.ini new file mode 100644 index 0000000000..744af4cb65 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser14.ini @@ -0,0 +1,6 @@ +[section1]
+name1=value1
+name2=value2
+[section2]
+name1=value1
+name2=foopy
diff --git a/xpcom/tests/unit/data/iniparser15-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser15-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..e60525dec6 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser15-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser15-utf8BOM.ini b/xpcom/tests/unit/data/iniparser15-utf8BOM.ini new file mode 100644 index 0000000000..172803f90b --- /dev/null +++ b/xpcom/tests/unit/data/iniparser15-utf8BOM.ini @@ -0,0 +1,6 @@ +[section1] +name1=value1 +[section2] +name1=foopy +[section1] +name1=newValue1 diff --git a/xpcom/tests/unit/data/iniparser15.ini b/xpcom/tests/unit/data/iniparser15.ini new file mode 100644 index 0000000000..608a27d8fb --- /dev/null +++ b/xpcom/tests/unit/data/iniparser15.ini @@ -0,0 +1,6 @@ +[section1]
+name1=value1
+[section2]
+name1=foopy
+[section1]
+name1=newValue1
diff --git a/xpcom/tests/unit/data/iniparser16-utf16leBOM.ini b/xpcom/tests/unit/data/iniparser16-utf16leBOM.ini Binary files differnew file mode 100644 index 0000000000..142b175902 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser16-utf16leBOM.ini diff --git a/xpcom/tests/unit/data/iniparser16-utf8BOM.ini b/xpcom/tests/unit/data/iniparser16-utf8BOM.ini new file mode 100644 index 0000000000..bba1018dab --- /dev/null +++ b/xpcom/tests/unit/data/iniparser16-utf8BOM.ini @@ -0,0 +1,13 @@ +#á¿»á¹Ò³Ï–·Ì˄ȡǨŅ©& +[☺♫] +#ѼΏá¹Ò³Ï– +♫=☻ +#·Ì˄ȡǨŅ© +♪=♥ +#‽ἧᵿΏá¹Ò³ +#ϖ·Ì˄ȡǨŅ©& +[☼] +♣=â™ +♦=♥ +#‽ἧᵿΏá¹Ò³ +#·Ì˄ȡǨŅ© diff --git a/xpcom/tests/unit/data/iniparser16.ini b/xpcom/tests/unit/data/iniparser16.ini new file mode 100644 index 0000000000..b94607d15d --- /dev/null +++ b/xpcom/tests/unit/data/iniparser16.ini @@ -0,0 +1,13 @@ +#á¿»á¹Ò³Ï–·Ì˄ȡǨŅ©& +[☺♫] +#ѼΏá¹Ò³Ï– +♫=☻ +#·Ì˄ȡǨŅ© +♪=♥ +#‽ἧᵿΏá¹Ò³ +#ϖ·Ì˄ȡǨŅ©& +[☼] +♣=â™ +♦=♥ +#‽ἧᵿΏá¹Ò³ +#·Ì˄ȡǨŅ© diff --git a/xpcom/tests/unit/data/iniparser17.ini b/xpcom/tests/unit/data/iniparser17.ini new file mode 100644 index 0000000000..bc4815b8c7 --- /dev/null +++ b/xpcom/tests/unit/data/iniparser17.ini @@ -0,0 +1,7 @@ +[section] +key= + +[] + +[empty] +=foo diff --git a/xpcom/tests/unit/data/presentation.key/.typeAttributes.dict b/xpcom/tests/unit/data/presentation.key/.typeAttributes.dict new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xpcom/tests/unit/data/presentation.key/.typeAttributes.dict diff --git a/xpcom/tests/unit/data/presentation.key/Contents/PkgInfo b/xpcom/tests/unit/data/presentation.key/Contents/PkgInfo new file mode 100644 index 0000000000..b0bc8e0761 --- /dev/null +++ b/xpcom/tests/unit/data/presentation.key/Contents/PkgInfo @@ -0,0 +1 @@ +????????
\ No newline at end of file diff --git a/xpcom/tests/unit/data/presentation.key/index.apxl.gz b/xpcom/tests/unit/data/presentation.key/index.apxl.gz Binary files differnew file mode 100644 index 0000000000..26178d809e --- /dev/null +++ b/xpcom/tests/unit/data/presentation.key/index.apxl.gz diff --git a/xpcom/tests/unit/data/presentation.key/thumbs/st0.tiff b/xpcom/tests/unit/data/presentation.key/thumbs/st0.tiff Binary files differnew file mode 100644 index 0000000000..8b49316b4d --- /dev/null +++ b/xpcom/tests/unit/data/presentation.key/thumbs/st0.tiff diff --git a/xpcom/tests/unit/data/process_directive.manifest b/xpcom/tests/unit/data/process_directive.manifest new file mode 100644 index 0000000000..3deb2ec444 --- /dev/null +++ b/xpcom/tests/unit/data/process_directive.manifest @@ -0,0 +1,2 @@ +category directives-test main-process @mozilla.org/supports-cstring;1 process=main +category directives-test content-process @mozilla.org/supports-cstring;1 process=content diff --git a/xpcom/tests/unit/head_xpcom.js b/xpcom/tests/unit/head_xpcom.js new file mode 100644 index 0000000000..e2ae79cb12 --- /dev/null +++ b/xpcom/tests/unit/head_xpcom.js @@ -0,0 +1,21 @@ +let CC = Components.Constructor; + +function get_test_program(prog) { + var progPath = do_get_cwd(); + progPath.append(prog); + progPath.leafName = progPath.leafName + mozinfo.bin_suffix; + return progPath; +} + +function set_process_running_environment() { + // Importing Services here messes up appInfo for some of the tests. + // eslint-disable-next-line mozilla/use-services + var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService( + Ci.nsIProperties + ); + var greBinDir = dirSvc.get("GreBinD", Ci.nsIFile); + Services.env.set("DYLD_LIBRARY_PATH", greBinDir.path); + // For Linux + Services.env.set("LD_LIBRARY_PATH", greBinDir.path); + // XXX: handle windows +} diff --git a/xpcom/tests/unit/test_bug121341.js b/xpcom/tests/unit/test_bug121341.js new file mode 100644 index 0000000000..2e66970092 --- /dev/null +++ b/xpcom/tests/unit/test_bug121341.js @@ -0,0 +1,64 @@ +const { NetUtil } = ChromeUtils.importESModule( + "resource://gre/modules/NetUtil.sys.mjs" +); + +function run_test() { + var dataFile = do_get_file("data/bug121341.properties"); + var channel = NetUtil.newChannel({ + uri: Services.io.newFileURI(dataFile, null, null), + loadUsingSystemPrincipal: true, + }); + var inp = channel.open(); + + var properties = Cu.createPersistentProperties(); + properties.load(inp); + + var value; + + value = properties.getStringProperty("1"); + Assert.equal(value, "abc"); + + value = properties.getStringProperty("2"); + Assert.equal(value, "xy"); + + value = properties.getStringProperty("3"); + Assert.equal(value, "\u1234\t\r\n\u00AB\u0001\n"); + + value = properties.getStringProperty("4"); + Assert.equal(value, "this is multiline property"); + + value = properties.getStringProperty("5"); + Assert.equal(value, "this is another multiline property"); + + value = properties.getStringProperty("6"); + Assert.equal(value, "test\u0036"); + + value = properties.getStringProperty("7"); + Assert.equal(value, "yet another multiline propery"); + + value = properties.getStringProperty("8"); + Assert.equal(value, "\ttest5\u0020"); + + value = properties.getStringProperty("9"); + Assert.equal(value, " test6\t"); + + value = properties.getStringProperty("10a\u1234b"); + Assert.equal(value, "c\uCDEFd"); + + value = properties.getStringProperty("11"); + Assert.equal(value, "\uABCD"); + + dataFile = do_get_file("data/bug121341-2.properties"); + + var channel2 = NetUtil.newChannel({ + uri: Services.io.newFileURI(dataFile, null, null), + loadUsingSystemPrincipal: true, + }); + inp = channel2.open(); + + var properties2 = Cu.createPersistentProperties(); + try { + properties2.load(inp); + do_throw("load() didn't fail"); + } catch (e) {} +} diff --git a/xpcom/tests/unit/test_bug1434856.js b/xpcom/tests/unit/test_bug1434856.js new file mode 100644 index 0000000000..a8dfa08079 --- /dev/null +++ b/xpcom/tests/unit/test_bug1434856.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +function run_test() { + let complete = false; + + let runnable = { + internalQI: ChromeUtils.generateQI(["nsIRunnable"]), + // eslint-disable-next-line mozilla/use-chromeutils-generateqi + QueryInterface(iid) { + // Attempt to schedule another runnable. This simulates a GC/CC + // being scheduled while executing the JS QI. + Services.tm.dispatchToMainThread(() => false); + return this.internalQI(iid); + }, + + run() { + complete = true; + }, + }; + + Services.tm.dispatchToMainThread(runnable); + Services.tm.spinEventLoopUntil( + "Test(test_bug1434856.js:run_test)", + () => complete + ); +} diff --git a/xpcom/tests/unit/test_bug325418.js b/xpcom/tests/unit/test_bug325418.js new file mode 100644 index 0000000000..5840aacf74 --- /dev/null +++ b/xpcom/tests/unit/test_bug325418.js @@ -0,0 +1,72 @@ +// 5 seconds. +const kExpectedDelay1 = 5; +// 1 second. +const kExpectedDelay2 = 1; + +var gStartTime1; +var gStartTime2; +var timer; + +var observer1 = { + observe: function observeTC1(subject, topic, data) { + if (topic == "timer-callback") { + // Stop timer, so it doesn't repeat (if test runs slowly). + timer.cancel(); + + // Actual delay may not be exact, so convert to seconds and round. + Assert.equal( + Math.round((Date.now() - gStartTime1) / 1000), + kExpectedDelay1 + ); + + timer = null; + + info( + "1st timer triggered (before being cancelled). Should not have happened!" + ); + Assert.ok(false); + } + }, +}; + +var observer2 = { + observe: function observeTC2(subject, topic, data) { + if (topic == "timer-callback") { + // Stop timer, so it doesn't repeat (if test runs slowly). + timer.cancel(); + + // Actual delay may not be exact, so convert to seconds and round. + Assert.equal( + Math.round((Date.now() - gStartTime2) / 1000), + kExpectedDelay2 + ); + + timer = null; + + do_test_finished(); + } + }, +}; + +function run_test() { + do_test_pending(); + + timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + + // Initialize the timer (with some delay), then cancel it. + gStartTime1 = Date.now(); + timer.init( + observer1, + kExpectedDelay1 * 1000, + timer.TYPE_REPEATING_PRECISE_CAN_SKIP + ); + timer.cancel(); + + // Re-initialize the timer (with a different delay). + gStartTime2 = Date.now(); + timer.init( + observer2, + kExpectedDelay2 * 1000, + timer.TYPE_REPEATING_PRECISE_CAN_SKIP + ); +} diff --git a/xpcom/tests/unit/test_bug332389.js b/xpcom/tests/unit/test_bug332389.js new file mode 100644 index 0000000000..605772f12a --- /dev/null +++ b/xpcom/tests/unit/test_bug332389.js @@ -0,0 +1,14 @@ +function run_test() { + var f = Services.dirsvc.get("CurProcD", Ci.nsIFile); + + var terminated = false; + for (var i = 0; i < 100; i++) { + if (f == null) { + terminated = true; + break; + } + f = f.parent; + } + + Assert.ok(terminated); +} diff --git a/xpcom/tests/unit/test_bug333505.js b/xpcom/tests/unit/test_bug333505.js new file mode 100644 index 0000000000..97016519da --- /dev/null +++ b/xpcom/tests/unit/test_bug333505.js @@ -0,0 +1,10 @@ +function run_test() { + var dirEntries = do_get_cwd().directoryEntries; + + while (dirEntries.hasMoreElements()) { + dirEntries.getNext(); + } + + // We ensure there is no crash + dirEntries.hasMoreElements(); +} diff --git a/xpcom/tests/unit/test_bug364285-1.js b/xpcom/tests/unit/test_bug364285-1.js new file mode 100644 index 0000000000..167e94e852 --- /dev/null +++ b/xpcom/tests/unit/test_bug364285-1.js @@ -0,0 +1,43 @@ +var nameArray = [ + "ascii", // ASCII + "fran\u00E7ais", // Latin-1 + "\u0420\u0443\u0441\u0441\u043A\u0438\u0439", // Cyrillic + "\u65E5\u672C\u8A9E", // Japanese + "\u4E2D\u6587", // Chinese + "\uD55C\uAD6D\uC5B4", // Korean + "\uD801\uDC0F\uD801\uDC2D\uD801\uDC3B\uD801\uDC2B", // Deseret +]; + +function getTempDir() { + return Services.dirsvc.get("TmpD", Ci.nsIFile); +} + +function create_file(fileName) { + var outFile = getTempDir(); + outFile.append(fileName); + outFile.createUnique(outFile.NORMAL_FILE_TYPE, 0o600); + + var stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance( + Ci.nsIFileOutputStream + ); + stream.init(outFile, 0x02 | 0x08 | 0x20, 0o600, 0); + stream.write("foo", 3); + stream.close(); + + Assert.equal(outFile.leafName.substr(0, fileName.length), fileName); + + return outFile; +} + +function test_create(fileName) { + var file1 = create_file(fileName); + var file2 = create_file(fileName); + file1.remove(false); + file2.remove(false); +} + +function run_test() { + for (var i = 0; i < nameArray.length; ++i) { + test_create(nameArray[i]); + } +} diff --git a/xpcom/tests/unit/test_bug374754.js b/xpcom/tests/unit/test_bug374754.js new file mode 100644 index 0000000000..0d20d90b2c --- /dev/null +++ b/xpcom/tests/unit/test_bug374754.js @@ -0,0 +1,65 @@ +var addedTopic = "xpcom-category-entry-added"; +var removedTopic = "xpcom-category-entry-removed"; +var testCategory = "bug-test-category"; +var testEntry = "@mozilla.org/bug-test-entry;1"; + +var testValue = "check validity"; +var result = ""; +var expected = "add remove add remove "; +var timer; + +var observer = { + QueryInterface: ChromeUtils.generateQI(["nsIObserver"]), + + observe(subject, topic, data) { + if (topic == "timer-callback") { + Assert.equal(result, expected); + + Services.obs.removeObserver(this, addedTopic); + Services.obs.removeObserver(this, removedTopic); + + do_test_finished(); + + timer = null; + } + + if ( + subject.QueryInterface(Ci.nsISupportsCString).data != testEntry || + data != testCategory + ) { + return; + } + + if (topic == addedTopic) { + result += "add "; + } else if (topic == removedTopic) { + result += "remove "; + } + }, +}; + +function run_test() { + do_test_pending(); + + Services.obs.addObserver(observer, addedTopic); + Services.obs.addObserver(observer, removedTopic); + + Services.catMan.addCategoryEntry( + testCategory, + testEntry, + testValue, + false, + true + ); + Services.catMan.addCategoryEntry( + testCategory, + testEntry, + testValue, + false, + true + ); + Services.catMan.deleteCategoryEntry(testCategory, testEntry, false); + + timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.init(observer, 0, timer.TYPE_ONE_SHOT); +} diff --git a/xpcom/tests/unit/test_bug476919.js b/xpcom/tests/unit/test_bug476919.js new file mode 100644 index 0000000000..5ba64758c7 --- /dev/null +++ b/xpcom/tests/unit/test_bug476919.js @@ -0,0 +1,25 @@ +/* global __LOCATION__ */ + +function run_test() { + var testDir = __LOCATION__.parent; + // create a test file, then symlink it, then check that we think it's a symlink + var targetFile = testDir.clone(); + targetFile.append("target.txt"); + if (!targetFile.exists()) { + targetFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + } + + var link = testDir.clone(); + link.append("link"); + if (link.exists()) { + link.remove(false); + } + + var ln = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + ln.initWithPath("/bin/ln"); + var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(ln); + var args = ["-s", targetFile.path, link.path]; + process.run(true, args, args.length); + Assert.ok(link.isSymlink()); +} diff --git a/xpcom/tests/unit/test_bug478086.js b/xpcom/tests/unit/test_bug478086.js new file mode 100644 index 0000000000..6debb58fbc --- /dev/null +++ b/xpcom/tests/unit/test_bug478086.js @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +function run_test() { + var nsIFile = Ci.nsIFile; + var root = Cc["@mozilla.org/file/local;1"].createInstance(nsIFile); + + // copied from http://mxr.mozilla.org/mozilla-central/source/image/test/unit/test_imgtools.js#135 + // nsIXULRuntime.OS doesn't seem to be available in xpcshell, so we'll use + // this as a kludgy way to figure out if we're running on Windows. + if (mozinfo.os == "win") { + root.initWithPath("\\\\."); + } else { + return; // XXX disabled, since this causes intermittent failures on Mac (bug 481369). + // root.initWithPath("/"); + } + var drives = root.directoryEntries; + Assert.ok(drives.hasMoreElements()); + while (drives.hasMoreElements()) { + var newPath = drives.nextFile.path; + Assert.equal(newPath.indexOf("\0"), -1); + } +} diff --git a/xpcom/tests/unit/test_bug745466.js b/xpcom/tests/unit/test_bug745466.js new file mode 100644 index 0000000000..a655bf45b4 --- /dev/null +++ b/xpcom/tests/unit/test_bug745466.js @@ -0,0 +1,7 @@ +const { FileUtils } = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs" +); + +function run_test() { + Assert.ok(FileUtils.File("~").equals(FileUtils.getDir("Home", []))); +} diff --git a/xpcom/tests/unit/test_console_service_callFunctionAndLogException.js b/xpcom/tests/unit/test_console_service_callFunctionAndLogException.js new file mode 100644 index 0000000000..1ca97ed6ec --- /dev/null +++ b/xpcom/tests/unit/test_console_service_callFunctionAndLogException.js @@ -0,0 +1,265 @@ +let lastMessage; +const consoleListener = { + observe(message) { + dump(" >> new message: " + message.errorMessage + "\n"); + lastMessage = message; + }, +}; +Services.console.registerListener(consoleListener); + +// The Console Service notifies its listener after one event loop cycle. +// So wait for one tick after each action dispatching a message/error to the service. +function waitForATick() { + return new Promise(resolve => Services.tm.dispatchToMainThread(resolve)); +} + +add_task(async function customScriptError() { + const scriptError = Cc["@mozilla.org/scripterror;1"].createInstance( + Ci.nsIScriptError + ); + scriptError.init( + "foo", + "file.js", + null, + 1, + 2, + Ci.nsIScriptError.warningFlag, + "some javascript" + ); + Services.console.logMessage(scriptError); + + await waitForATick(); + + Assert.equal( + lastMessage, + scriptError, + "We receive the exact same nsIScriptError object" + ); + + Assert.equal(lastMessage.errorMessage, "foo"); + Assert.equal(lastMessage.sourceName, "file.js"); + Assert.equal(lastMessage.lineNumber, 1); + Assert.equal(lastMessage.columnNumber, 2); + Assert.equal(lastMessage.flags, Ci.nsIScriptError.warningFlag); + Assert.equal(lastMessage.category, "some javascript"); + + Assert.equal( + lastMessage.stack, + undefined, + "Custom nsIScriptError object created from JS can't convey any stack" + ); +}); + +add_task(async function callFunctionAndLogExceptionWithChromeGlobal() { + try { + Services.console.callFunctionAndLogException(globalThis, function () { + throw new Error("custom exception"); + }); + Assert.fail("callFunctionAndLogException should throw"); + } catch (e) { + Assert.equal( + e.name, + "NS_ERROR_XPC_JAVASCRIPT_ERROR", + "callFunctionAndLogException thrown" + ); + } + + await waitForATick(); + + Assert.ok(!!lastMessage, "Got the message"); + Assert.ok( + lastMessage instanceof Ci.nsIScriptError, + "This is a nsIScriptError" + ); + + Assert.equal(lastMessage.errorMessage, "Error: custom exception"); + Assert.equal(lastMessage.sourceName, _TEST_FILE); + Assert.equal(lastMessage.lineNumber, 56); + Assert.equal(lastMessage.columnNumber, 13); + Assert.equal(lastMessage.flags, Ci.nsIScriptError.errorFlag); + Assert.equal(lastMessage.category, "chrome javascript"); + Assert.ok(lastMessage.stack, "It has a stack"); + Assert.equal(lastMessage.stack.source, _TEST_FILE); + Assert.equal(lastMessage.stack.line, 56); + Assert.equal(lastMessage.stack.column, 13); + Assert.ok(!!lastMessage.stack.parent, "stack has a parent frame"); + Assert.equal( + lastMessage.innerWindowID, + 0, + "The message isn't bound to any WindowGlobal" + ); +}); + +add_task(async function callFunctionAndLogExceptionWithContentGlobal() { + const window = createContentWindow(); + try { + Services.console.callFunctionAndLogException(window, function () { + throw new Error("another custom exception"); + }); + Assert.fail("callFunctionAndLogException should throw"); + } catch (e) { + Assert.equal( + e.name, + "NS_ERROR_XPC_JAVASCRIPT_ERROR", + "callFunctionAndLogException thrown" + ); + } + + await waitForATick(); + + Assert.ok(!!lastMessage, "Got the message"); + Assert.ok( + lastMessage instanceof Ci.nsIScriptError, + "This is a nsIScriptError" + ); + + Assert.equal(lastMessage.errorMessage, "Error: another custom exception"); + Assert.equal(lastMessage.sourceName, _TEST_FILE); + Assert.equal(lastMessage.lineNumber, 97); + Assert.equal(lastMessage.columnNumber, 13); + Assert.equal(lastMessage.flags, Ci.nsIScriptError.errorFlag); + Assert.equal(lastMessage.category, "content javascript"); + Assert.ok(lastMessage.stack, "It has a stack"); + Assert.equal(lastMessage.stack.source, _TEST_FILE); + Assert.equal(lastMessage.stack.line, 97); + Assert.equal(lastMessage.stack.column, 13); + Assert.ok(!!lastMessage.stack.parent, "stack has a parent frame"); + Assert.ok( + !!window.windowGlobalChild.innerWindowId, + "The window has a innerWindowId" + ); + Assert.equal( + lastMessage.innerWindowID, + window.windowGlobalChild.innerWindowId, + "The message is bound to the content window" + ); +}); + +add_task(async function callFunctionAndLogExceptionForContentScriptSandboxes() { + const { sandbox, window } = createContentScriptSandbox(); + Cu.evalInSandbox( + `function foo() { throw new Error("sandbox exception"); }`, + sandbox, + null, + "sandbox-file.js", + 1, + 0 + ); + try { + Services.console.callFunctionAndLogException(window, sandbox.foo); + Assert.fail("callFunctionAndLogException should throw"); + } catch (e) { + Assert.equal( + e.name, + "NS_ERROR_XPC_JAVASCRIPT_ERROR", + "callFunctionAndLogException thrown" + ); + } + + await waitForATick(); + + Assert.ok(!!lastMessage, "Got the message"); + // Note that it is important to "instanceof" in order to expose the nsIScriptError attributes. + Assert.ok( + lastMessage instanceof Ci.nsIScriptError, + "This is a nsIScriptError" + ); + + Assert.equal(lastMessage.errorMessage, "Error: sandbox exception"); + Assert.equal(lastMessage.sourceName, "sandbox-file.js"); + Assert.equal(lastMessage.lineNumber, 1); + Assert.equal(lastMessage.columnNumber, 24); + Assert.equal(lastMessage.flags, Ci.nsIScriptError.errorFlag); + Assert.equal(lastMessage.category, "content javascript"); + Assert.ok(lastMessage.stack, "It has a stack"); + Assert.equal(lastMessage.stack.source, "sandbox-file.js"); + Assert.equal(lastMessage.stack.line, 1); + Assert.equal(lastMessage.stack.column, 24); + Assert.ok(!!lastMessage.stack.parent, "stack has a parent frame"); + Assert.ok( + !!window.windowGlobalChild.innerWindowId, + "The sandbox's prototype is a window and has a innerWindowId" + ); + Assert.equal( + lastMessage.innerWindowID, + window.windowGlobalChild.innerWindowId, + "The message is bound to the sandbox's prototype WindowGlobal" + ); +}); + +add_task( + async function callFunctionAndLogExceptionForContentScriptSandboxesWrappedInChrome() { + const { sandbox, window } = createContentScriptSandbox(); + Cu.evalInSandbox( + `function foo() { throw new Error("sandbox exception"); }`, + sandbox, + null, + "sandbox-file.js", + 1, + 0 + ); + try { + Services.console.callFunctionAndLogException(window, function () { + sandbox.foo(); + }); + Assert.fail("callFunctionAndLogException should throw"); + } catch (e) { + Assert.equal( + e.name, + "NS_ERROR_XPC_JAVASCRIPT_ERROR", + "callFunctionAndLogException thrown" + ); + } + + await waitForATick(); + + Assert.ok(!!lastMessage, "Got the message"); + // Note that it is important to "instanceof" in order to expose the nsIScriptError attributes. + Assert.ok( + lastMessage instanceof Ci.nsIScriptError, + "This is a nsIScriptError" + ); + + Assert.ok( + !!window.windowGlobalChild.innerWindowId, + "The sandbox's prototype is a window and has a innerWindowId" + ); + Assert.equal( + lastMessage.innerWindowID, + window.windowGlobalChild.innerWindowId, + "The message is bound to the sandbox's prototype WindowGlobal" + ); + } +); + +add_task(function teardown() { + Services.console.unregisterListener(consoleListener); +}); + +// We are in xpcshell, so we can't have a real DOM Window as in Firefox +// but let's try to have a fake one. +function createContentWindow() { + const principal = + Services.scriptSecurityManager.createContentPrincipalFromOrigin( + "http://example.com/" + ); + + const webnav = Services.appShell.createWindowlessBrowser(false); + + webnav.docShell.createAboutBlankDocumentViewer(principal, principal); + + return webnav.document.defaultView; +} + +// Create a Sandbox as in WebExtension content scripts +function createContentScriptSandbox() { + const window = createContentWindow(); + // The sandboxPrototype is the key here in order to + // make xpc::SandboxWindowOrNull ignore the sandbox + // and instead retrieve its prototype and link the error message + // to the window instead of the sandbox. + return { + sandbox: Cu.Sandbox(window, { sandboxPrototype: window }), + window, + }; +} diff --git a/xpcom/tests/unit/test_debugger_malloc_size_of.js b/xpcom/tests/unit/test_debugger_malloc_size_of.js new file mode 100644 index 0000000000..3141d8c2c3 --- /dev/null +++ b/xpcom/tests/unit/test_debugger_malloc_size_of.js @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This is just a sanity test that Gecko is giving SpiderMonkey a MallocSizeOf +// function for new JSRuntimes. There is more extensive testing around the +// expected byte sizes within SpiderMonkey's jit-tests, we just want to make +// sure that Gecko is providing SpiderMonkey with the callback it needs. + +const { byteSize } = Cu.getJSTestingFunctions(); + +function run_test() { + const objects = [ + {}, + { w: 1, x: 2, y: 3, z: 4, a: 5 }, + [], + Array(10).fill(null), + new RegExp("(2|two) problems", "g"), + new Date(), + new Uint8Array(64), + Promise.resolve(1), + function f() {}, + Object, + ]; + + for (let obj of objects) { + info(uneval(obj)); + ok(byteSize(obj), "We should get some (non-zero) byte size"); + } +} diff --git a/xpcom/tests/unit/test_file_createUnique.js b/xpcom/tests/unit/test_file_createUnique.js new file mode 100644 index 0000000000..510002bda2 --- /dev/null +++ b/xpcom/tests/unit/test_file_createUnique.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function run_test() { + // Generate a leaf name that is 255 characters long. + var longLeafName = new Array(256).join("T"); + + // Generate the path for a file located in a directory with a long name. + var tempFile = Services.dirsvc.get("TmpD", Ci.nsIFile); + tempFile.append(longLeafName); + tempFile.append("test.txt"); + + try { + tempFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600); + do_throw("Creating an item in a folder with a very long name should throw"); + } catch (e) { + if ( + !( + e instanceof Ci.nsIException && + e.result == Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH + ) + ) { + throw e; + } + // We expect the function not to crash but to raise this exception. + } +} diff --git a/xpcom/tests/unit/test_file_equality.js b/xpcom/tests/unit/test_file_equality.js new file mode 100644 index 0000000000..74ea8046d8 --- /dev/null +++ b/xpcom/tests/unit/test_file_equality.js @@ -0,0 +1,37 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var LocalFile = CC("@mozilla.org/file/local;1", "nsIFile", "initWithPath"); + +function run_test() { + test_normalized_vs_non_normalized(); +} + +function test_normalized_vs_non_normalized() { + // get a directory that exists on all platforms + var tmp1 = Services.dirsvc.get("TmpD", Ci.nsIFile); + var exists = tmp1.exists(); + Assert.ok(exists); + if (!exists) { + return; + } + + // the test logic below assumes we're starting with a normalized path, but the + // default location on macos is a symbolic link, so resolve it before starting + tmp1.normalize(); + + // this has the same exact path as tmp1, it should equal tmp1 + var tmp2 = new LocalFile(tmp1.path); + Assert.ok(tmp1.equals(tmp2)); + + // this is a non-normalized version of tmp1, it should not equal tmp1 + tmp2.appendRelativePath("."); + Assert.ok(!tmp1.equals(tmp2)); + + // normalize and make sure they are equivalent again + tmp2.normalize(); + Assert.ok(tmp1.equals(tmp2)); +} diff --git a/xpcom/tests/unit/test_file_renameTo.js b/xpcom/tests/unit/test_file_renameTo.js new file mode 100644 index 0000000000..a6e8633773 --- /dev/null +++ b/xpcom/tests/unit/test_file_renameTo.js @@ -0,0 +1,55 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function run_test() { + // Create the base directory. + let base = Services.dirsvc.get("TmpD", Ci.nsIFile); + base.append("renameTesting"); + if (base.exists()) { + base.remove(true); + } + base.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8)); + + // Create a sub directory under the base. + let subdir = base.clone(); + subdir.append("subdir"); + subdir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0777", 8)); + + // Create a file under the sub directory. + let tempFile = subdir.clone(); + tempFile.append("file0.txt"); + tempFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0777", 8)); + + // Test renameTo in the base directory + tempFile.renameTo(null, "file1.txt"); + Assert.ok(exists(subdir, "file1.txt")); + + // Test moving across directories + tempFile = subdir.clone(); + tempFile.append("file1.txt"); + tempFile.renameTo(base, ""); + Assert.ok(exists(base, "file1.txt")); + + // Test moving across directories and renaming at the same time + tempFile = base.clone(); + tempFile.append("file1.txt"); + tempFile.renameTo(subdir, "file2.txt"); + Assert.ok(exists(subdir, "file2.txt")); + + // Test moving a directory + subdir.renameTo(base, "renamed"); + Assert.ok(exists(base, "renamed")); + let renamed = base.clone(); + renamed.append("renamed"); + Assert.ok(exists(renamed, "file2.txt")); + + base.remove(true); +} + +function exists(parent, filename) { + let file = parent.clone(); + file.append(filename); + return file.exists(); +} diff --git a/xpcom/tests/unit/test_getTimers.js b/xpcom/tests/unit/test_getTimers.js new file mode 100644 index 0000000000..58a048a4bc --- /dev/null +++ b/xpcom/tests/unit/test_getTimers.js @@ -0,0 +1,90 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +const timerManager = Cc["@mozilla.org/timer-manager;1"].getService( + Ci.nsITimerManager +); + +function newTimer(name, delay, type) { + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + timer.initWithCallback( + { + QueryInterface: ChromeUtils.generateQI(["nsITimerCallback", "nsINamed"]), + name, + notify: () => {}, + }, + delay, + type + ); + return timer; +} + +function getTimers() { + return timerManager.getTimers().filter(t => { + if (t.name == "BackgroundHangThread_timer") { + // BHR is Nightly-only, so just ignore it. + return false; + } + + if (AppConstants.platform == "win" && t.name == "nsAnonTempFileRemover") { + // On Windows there's a 3min timer added at startup to then add an + // idle observer that finally triggers removing leftover temp files. + // Ignore that too. + return false; + } + + return true; + }); +} + +function run_test() { + { + let timers = getTimers(); + for (let timer of timers) { + // Print info about unexpected startup timers to help debugging. + info(`${timer.name}: ${timer.delay}ms, ${timer.type}`); + } + Assert.equal( + timers.length, + 0, + "there should be no timer at xpcshell startup" + ); + } + + let timerData = [ + ["t1", 500, Ci.nsITimer.TYPE_ONE_SHOT], + ["t2", 1500, Ci.nsITimer.TYPE_REPEATING_SLACK], + ["t3", 2500, Ci.nsITimer.TYPE_REPEATING_PRECISE], + ["t4", 3500, Ci.nsITimer.TYPE_REPEATING_PRECISE_CAN_SKIP], + ["t5", 5500, Ci.nsITimer.TYPE_REPEATING_SLACK_LOW_PRIORITY], + ["t6", 7500, Ci.nsITimer.TYPE_ONE_SHOT_LOW_PRIORITY], + ]; + + info("Add timers one at a time."); + for (let [name, delay, type] of timerData) { + let timer = newTimer(name, delay, type); + let timers = getTimers(); + Assert.equal(timers.length, 1, "there should be only one timer"); + Assert.equal(name, timers[0].name, "the name is correct"); + Assert.equal(delay, timers[0].delay, "the delay is correct"); + Assert.equal(type, timers[0].type, "the type is correct"); + + timer.cancel(); + Assert.equal(getTimers().length, 0, "no timer left after cancelling"); + } + + info("Add all timers at once."); + let timers = []; + for (let [name, delay, type] of timerData) { + timers.push(newTimer(name, delay, type)); + } + while (timers.length) { + Assert.equal(getTimers().length, timers.length, "correct timer count"); + timers.pop().cancel(); + } + Assert.equal(getTimers().length, 0, "no timer left after cancelling"); +} diff --git a/xpcom/tests/unit/test_hidden_files.js b/xpcom/tests/unit/test_hidden_files.js new file mode 100644 index 0000000000..27d87e6f54 --- /dev/null +++ b/xpcom/tests/unit/test_hidden_files.js @@ -0,0 +1,24 @@ +const NS_OS_TEMP_DIR = "TmpD"; + +var hiddenUnixFile; +function createUNIXHiddenFile() { + var tmpDir = Services.dirsvc.get(NS_OS_TEMP_DIR, Ci.nsIFile); + hiddenUnixFile = tmpDir.clone(); + hiddenUnixFile.append(".foo"); + // we don't care if this already exists because we don't care + // about the file's contents (just the name) + if (!hiddenUnixFile.exists()) { + hiddenUnixFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666); + } + return hiddenUnixFile.exists(); +} + +function run_test() { + // Skip this test on Windows + if (mozinfo.os == "win") { + return; + } + + Assert.ok(createUNIXHiddenFile()); + Assert.ok(hiddenUnixFile.isHidden()); +} diff --git a/xpcom/tests/unit/test_home.js b/xpcom/tests/unit/test_home.js new file mode 100644 index 0000000000..e3a4af9796 --- /dev/null +++ b/xpcom/tests/unit/test_home.js @@ -0,0 +1,18 @@ +const CWD = do_get_cwd(); +function checkOS(os) { + const nsILocalFile_ = "nsILocalFile" + os; + return nsILocalFile_ in Ci && CWD instanceof Ci[nsILocalFile_]; +} + +const isWin = checkOS("Win"); + +function run_test() { + var envVar = isWin ? "USERPROFILE" : "HOME"; + + var homeDir = Services.dirsvc.get("Home", Ci.nsIFile); + + var expected = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + expected.initWithPath(Services.env.get(envVar)); + + Assert.equal(homeDir.path, expected.path); +} diff --git a/xpcom/tests/unit/test_iniParser.js b/xpcom/tests/unit/test_iniParser.js new file mode 100644 index 0000000000..a586c4c060 --- /dev/null +++ b/xpcom/tests/unit/test_iniParser.js @@ -0,0 +1,476 @@ +var testnum = 0; +var factory; + +function parserForFile(filename) { + let parser = null; + try { + let file = do_get_file(filename); + Assert.ok(!!file); + parser = factory.createINIParser(file); + Assert.ok(!!parser); + } catch (e) { + dump("INFO | caught error: " + e); + // checkParserOutput will handle a null parser when it's expected. + } + return parser; +} + +function checkParserOutput(parser, expected) { + // If the expected output is null, we expect the parser to have + // failed (and vice-versa). + if (!parser || !expected) { + Assert.equal(parser, null); + Assert.equal(expected, null); + return; + } + + let output = getParserOutput(parser); + for (let section in expected) { + Assert.ok(section in output); + for (let key in expected[section]) { + Assert.ok(key in output[section]); + Assert.equal(output[section][key], expected[section][key]); + delete output[section][key]; + } + for (let key in output[section]) { + Assert.equal(key, "wasn't expecting this key!"); + } + delete output[section]; + } + for (let section in output) { + Assert.equal(section, "wasn't expecting this section!"); + } +} + +function getParserOutput(parser) { + let output = {}; + + for (let section of parser.getSections()) { + Assert.equal(false, section in output); // catch dupes + output[section] = {}; + + for (let key of parser.getKeys(section)) { + Assert.equal(false, key in output[section]); // catch dupes + let value = parser.getString(section, key); + output[section][key] = value; + } + } + return output; +} + +function run_test() { + try { + var testdata = [ + { filename: "data/iniparser01.ini", reference: {} }, + { filename: "data/iniparser02.ini", reference: {} }, + { filename: "data/iniparser03.ini", reference: {} }, + { filename: "data/iniparser04.ini", reference: {} }, + { filename: "data/iniparser05.ini", reference: {} }, + { filename: "data/iniparser06.ini", reference: {} }, + { filename: "data/iniparser07.ini", reference: {} }, + { + filename: "data/iniparser08.ini", + reference: { section1: { name1: "" } }, + }, + { + filename: "data/iniparser09.ini", + reference: { section1: { name1: "value1" } }, + }, + { + filename: "data/iniparser10.ini", + reference: { section1: { name1: "value1" } }, + }, + { + filename: "data/iniparser11.ini", + reference: { section1: { name1: "value1" } }, + }, + { + filename: "data/iniparser12.ini", + reference: { section1: { name1: "value1" } }, + }, + { + filename: "data/iniparser13.ini", + reference: { section1: { name1: "value1" } }, + }, + { + filename: "data/iniparser14.ini", + reference: { + section1: { name1: "value1", name2: "value2" }, + section2: { name1: "value1", name2: "foopy" }, + }, + }, + { + filename: "data/iniparser15.ini", + reference: { + section1: { name1: "newValue1" }, + section2: { name1: "foopy" }, + }, + }, + { + filename: "data/iniparser16.ini", + reference: { + "☺♫": { "♫": "☻", "♪": "♥" }, + "☼": { "♣": "♠", "♦": "♥" }, + }, + }, + { filename: "data/iniparser17.ini", reference: { section: { key: "" } } }, + ]; + + testdata.push({ + filename: "data/iniparser01-utf8BOM.ini", + reference: testdata[0].reference, + }); + testdata.push({ + filename: "data/iniparser02-utf8BOM.ini", + reference: testdata[1].reference, + }); + testdata.push({ + filename: "data/iniparser03-utf8BOM.ini", + reference: testdata[2].reference, + }); + testdata.push({ + filename: "data/iniparser04-utf8BOM.ini", + reference: testdata[3].reference, + }); + testdata.push({ + filename: "data/iniparser05-utf8BOM.ini", + reference: testdata[4].reference, + }); + testdata.push({ + filename: "data/iniparser06-utf8BOM.ini", + reference: testdata[5].reference, + }); + testdata.push({ + filename: "data/iniparser07-utf8BOM.ini", + reference: testdata[6].reference, + }); + testdata.push({ + filename: "data/iniparser08-utf8BOM.ini", + reference: testdata[7].reference, + }); + testdata.push({ + filename: "data/iniparser09-utf8BOM.ini", + reference: testdata[8].reference, + }); + testdata.push({ + filename: "data/iniparser10-utf8BOM.ini", + reference: testdata[9].reference, + }); + testdata.push({ + filename: "data/iniparser11-utf8BOM.ini", + reference: testdata[10].reference, + }); + testdata.push({ + filename: "data/iniparser12-utf8BOM.ini", + reference: testdata[11].reference, + }); + testdata.push({ + filename: "data/iniparser13-utf8BOM.ini", + reference: testdata[12].reference, + }); + testdata.push({ + filename: "data/iniparser14-utf8BOM.ini", + reference: testdata[13].reference, + }); + testdata.push({ + filename: "data/iniparser15-utf8BOM.ini", + reference: testdata[14].reference, + }); + testdata.push({ + filename: "data/iniparser16-utf8BOM.ini", + reference: testdata[15].reference, + }); + + // Intentional test for appInfo that can't be preloaded. + // eslint-disable-next-line mozilla/use-services + let os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; + if ("WINNT" === os) { + testdata.push({ + filename: "data/iniparser01-utf16leBOM.ini", + reference: testdata[0].reference, + }); + testdata.push({ + filename: "data/iniparser02-utf16leBOM.ini", + reference: testdata[1].reference, + }); + testdata.push({ + filename: "data/iniparser03-utf16leBOM.ini", + reference: testdata[2].reference, + }); + testdata.push({ + filename: "data/iniparser04-utf16leBOM.ini", + reference: testdata[3].reference, + }); + testdata.push({ + filename: "data/iniparser05-utf16leBOM.ini", + reference: testdata[4].reference, + }); + testdata.push({ + filename: "data/iniparser06-utf16leBOM.ini", + reference: testdata[5].reference, + }); + testdata.push({ + filename: "data/iniparser07-utf16leBOM.ini", + reference: testdata[6].reference, + }); + testdata.push({ + filename: "data/iniparser08-utf16leBOM.ini", + reference: testdata[7].reference, + }); + testdata.push({ + filename: "data/iniparser09-utf16leBOM.ini", + reference: testdata[8].reference, + }); + testdata.push({ + filename: "data/iniparser10-utf16leBOM.ini", + reference: testdata[9].reference, + }); + testdata.push({ + filename: "data/iniparser11-utf16leBOM.ini", + reference: testdata[10].reference, + }); + testdata.push({ + filename: "data/iniparser12-utf16leBOM.ini", + reference: testdata[11].reference, + }); + testdata.push({ + filename: "data/iniparser13-utf16leBOM.ini", + reference: testdata[12].reference, + }); + testdata.push({ + filename: "data/iniparser14-utf16leBOM.ini", + reference: testdata[13].reference, + }); + testdata.push({ + filename: "data/iniparser15-utf16leBOM.ini", + reference: testdata[14].reference, + }); + testdata.push({ + filename: "data/iniparser16-utf16leBOM.ini", + reference: testdata[15].reference, + }); + } + + /* ========== 0 ========== */ + factory = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].getService( + Ci.nsIINIParserFactory + ); + Assert.ok(!!factory); + + // Test reading from a variety of files and strings. While we're at it, + // write out each one and read it back to ensure that nothing changed. + while (testnum < testdata.length) { + dump("\nINFO | test #" + ++testnum); + let filename = testdata[testnum - 1].filename; + dump(", filename " + filename + "\n"); + let parser = parserForFile(filename); + checkParserOutput(parser, testdata[testnum - 1].reference); + if (!parser) { + continue; + } + Assert.ok(parser instanceof Ci.nsIINIParserWriter); + // write contents out to a new file + let newfilename = filename + ".new"; + let newfile = do_get_file(filename); + newfile.leafName += ".new"; + parser.writeFile(newfile); + // read new file and make sure the contents are the same. + parser = parserForFile(newfilename); + checkParserOutput(parser, testdata[testnum - 1].reference); + // cleanup after the test + newfile.remove(false); + + // ensure that `writeString` works correctly + Assert.ok(parser instanceof Ci.nsIINIParserWriter); + let formatted = parser.writeToString(); + parser = factory.createINIParser(null); + // re-parsing the formatted string is the easiest + // way to verify correctness... + parser.initFromString(formatted); + checkParserOutput(parser, testdata[testnum - 1].reference); + } + + dump("INFO | test #" + ++testnum + "\n"); + + // test writing to a new file. + var newfile = do_get_file("data/"); + newfile.append("nonexistent-file.ini"); + if (newfile.exists()) { + newfile.remove(false); + } + Assert.ok(!newfile.exists()); + + try { + var parser = factory.createINIParser(newfile); + Assert.ok(false, "Should have thrown an exception"); + } catch (e) { + Assert.equal( + e.result, + Cr.NS_ERROR_FILE_NOT_FOUND, + "Caught a file not found exception" + ); + } + parser = factory.createINIParser(); + Assert.ok(!!parser); + Assert.ok(parser instanceof Ci.nsIINIParserWriter); + checkParserOutput(parser, {}); + parser.writeFile(newfile); + Assert.ok(newfile.exists()); + + // test adding a new section and new key + parser.setString("section", "key", "value"); + parser.setString("section", "key2", ""); + parser.writeFile(newfile); + Assert.ok(newfile.exists()); + checkParserOutput(parser, { section: { key: "value", key2: "" } }); + // read it in again, check for same data. + parser = parserForFile("data/nonexistent-file.ini"); + checkParserOutput(parser, { section: { key: "value", key2: "" } }); + // cleanup after the test + newfile.remove(false); + + dump("INFO | test #" + ++testnum + "\n"); + + // test modifying a existing key's value (in an existing section) + parser = parserForFile("data/iniparser09.ini"); + checkParserOutput(parser, { section1: { name1: "value1" } }); + + Assert.ok(parser instanceof Ci.nsIINIParserWriter); + parser.setString("section1", "name1", "value2"); + checkParserOutput(parser, { section1: { name1: "value2" } }); + + dump("INFO | test #" + ++testnum + "\n"); + + // test trying to set illegal characters + var caughtError; + caughtError = null; + checkParserOutput(parser, { section1: { name1: "value2" } }); + + // Bad characters in section name + try { + parser.setString("bad\0", "ok", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("bad\r", "ok", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("bad\n", "ok", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("bad[", "ok", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("bad]", "ok", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("", "ok", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + + // Bad characters in key name + caughtError = null; + try { + parser.setString("ok", "bad\0", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("ok", "bad\r", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("ok", "bad\n", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("ok", "bad=", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("ok", "", "ok"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + + // Bad characters in value + caughtError = null; + try { + parser.setString("ok", "ok", "bad\0"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("ok", "ok", "bad\r"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("ok", "ok", "bad\n"); + } catch (e) { + caughtError = e; + } + Assert.ok(caughtError); + Assert.equal(caughtError.result, Cr.NS_ERROR_INVALID_ARG); + caughtError = null; + try { + parser.setString("ok", "ok", "good="); + } catch (e) { + caughtError = e; + } + Assert.ok(!caughtError); + caughtError = null; + } catch (e) { + throw new Error(`FAILED in test #${testnum} -- ${e}`); + } +} diff --git a/xpcom/tests/unit/test_ioutil.js b/xpcom/tests/unit/test_ioutil.js new file mode 100644 index 0000000000..e269b424a2 --- /dev/null +++ b/xpcom/tests/unit/test_ioutil.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const util = Cc["@mozilla.org/io-util;1"].getService(Ci.nsIIOUtil); + +function run_test() { + try { + util.inputStreamIsBuffered(null); + do_throw("inputStreamIsBuffered should have thrown"); + } catch (e) { + Assert.equal(e.result, Cr.NS_ERROR_INVALID_POINTER); + } + + try { + util.outputStreamIsBuffered(null); + do_throw("outputStreamIsBuffered should have thrown"); + } catch (e) { + Assert.equal(e.result, Cr.NS_ERROR_INVALID_POINTER); + } + + var s = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( + Ci.nsIStringInputStream + ); + var body = "This is a test"; + s.setData(body, body.length); + Assert.equal(util.inputStreamIsBuffered(s), true); +} diff --git a/xpcom/tests/unit/test_localfile.js b/xpcom/tests/unit/test_localfile.js new file mode 100644 index 0000000000..c90d91b278 --- /dev/null +++ b/xpcom/tests/unit/test_localfile.js @@ -0,0 +1,288 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); +const { setTimeout } = ChromeUtils.importESModule( + "resource://gre/modules/Timer.sys.mjs" +); + +const MAX_TIME_DIFFERENCE = 2500; +const MILLIS_PER_DAY = 1000 * 60 * 60 * 24; + +var LocalFile = CC("@mozilla.org/file/local;1", "nsIFile", "initWithPath"); + +function sleep(ms) { + // We are measuring timestamps, which are slightly fuzzed, and just need to + // measure that they are increasing. + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + return new Promise(resolve => setTimeout(() => resolve(), ms)); +} + +add_task(function test_toplevel_parent_is_null() { + try { + var lf = new LocalFile("C:\\"); + + // not required by API, but a property on which the implementation of + // parent == null relies for correctness + Assert.ok(lf.path.length == 2); + + Assert.ok(lf.parent === null); + } catch (e) { + // not Windows + Assert.equal(e.result, Cr.NS_ERROR_FILE_UNRECOGNIZED_PATH); + } +}); + +add_task(function test_normalize_crash_if_media_missing() { + const a = "a".charCodeAt(0); + const z = "z".charCodeAt(0); + for (var i = a; i <= z; ++i) { + try { + LocalFile(String.fromCharCode(i) + ":.\\test").normalize(); + } catch (e) {} + } +}); + +// Tests that changing a file's modification time is possible +add_task(async function test_file_modification_time() { + let file = do_get_profile(); + file.append("testfile"); + + // Should never happen but get rid of it anyway + if (file.exists()) { + file.remove(true); + } + + const now = Date.now(); + file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + Assert.ok(file.exists()); + + const atime = file.lastAccessedTime; + + // Modification time may be out by up to 2 seconds on FAT filesystems. Test + // with a bit of leeway, close enough probably means it is correct. + let diff = Math.abs(file.lastModifiedTime - now); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + const yesterday = now - MILLIS_PER_DAY; + file.lastModifiedTime = yesterday; + + diff = Math.abs(file.lastModifiedTime - yesterday); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + Assert.equal( + file.lastAccessedTime, + atime, + "Setting lastModifiedTime should not set lastAccessedTime" + ); + + const tomorrow = now + MILLIS_PER_DAY; + file.lastModifiedTime = tomorrow; + + diff = Math.abs(file.lastModifiedTime - tomorrow); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + const bug377307 = 1172950238000; + file.lastModifiedTime = bug377307; + + diff = Math.abs(file.lastModifiedTime - bug377307); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + await sleep(1000); + + file.lastModifiedTime = 0; + Assert.greater( + file.lastModifiedTime, + now, + "Setting lastModifiedTime to 0 should set it to current date and time" + ); + + file.remove(true); +}); + +add_task(async function test_lastAccessedTime() { + const file = do_get_profile(); + + file.append("test-atime"); + if (file.exists()) { + file.remove(true); + } + + const now = Date.now(); + file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + Assert.ok(file.exists()); + + const mtime = file.lastModifiedTime; + + // Modification time may be out by up to 2 seconds on FAT filesystems. Test + // with a bit of leeway, close enough probably means it is correct. + let diff = Math.abs(file.lastModifiedTime - now); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + const yesterday = now - MILLIS_PER_DAY; + file.lastAccessedTime = yesterday; + + diff = Math.abs(file.lastAccessedTime - yesterday); + Assert.ok(diff < MAX_TIME_DIFFERENCE, `${diff} < ${MAX_TIME_DIFFERENCE}`); + Assert.equal( + file.lastModifiedTime, + mtime, + "Setting lastAccessedTime should not set lastModifiedTime" + ); + + const tomorrow = now + MILLIS_PER_DAY; + file.lastAccessedTime = tomorrow; + + diff = Math.abs(file.lastAccessedTime - tomorrow); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + const bug377307 = 1172950238000; + file.lastAccessedTime = bug377307; + + diff = Math.abs(file.lastAccessedTime - bug377307); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + await sleep(1000); + + file.lastAccessedTime = 0; + Assert.greater( + file.lastAccessedTime, + now, + "Setting lastAccessedTime to 0 should set it to the current date and time" + ); +}); + +// Tests that changing a directory's modification time is possible +add_task(function test_directory_modification_time() { + var dir = do_get_profile(); + dir.append("testdir"); + + // Should never happen but get rid of it anyway + if (dir.exists()) { + dir.remove(true); + } + + var now = Date.now(); + dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755); + Assert.ok(dir.exists()); + + // Modification time may be out by up to 2 seconds on FAT filesystems. Test + // with a bit of leeway, close enough probably means it is correct. + var diff = Math.abs(dir.lastModifiedTime - now); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + var yesterday = now - MILLIS_PER_DAY; + dir.lastModifiedTime = yesterday; + + diff = Math.abs(dir.lastModifiedTime - yesterday); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + var tomorrow = now - MILLIS_PER_DAY; + dir.lastModifiedTime = tomorrow; + + diff = Math.abs(dir.lastModifiedTime - tomorrow); + Assert.ok(diff < MAX_TIME_DIFFERENCE); + + dir.remove(true); +}); + +add_task(function test_diskSpaceAvailable() { + let file = do_get_profile(); + file.QueryInterface(Ci.nsIFile); + + let bytes = file.diskSpaceAvailable; + Assert.ok(bytes > 0); + + file.append("testfile"); + if (file.exists()) { + file.remove(true); + } + file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + + bytes = file.diskSpaceAvailable; + Assert.ok(bytes > 0); + + file.remove(true); +}); + +add_task(function test_diskCapacity() { + let file = do_get_profile(); + file.QueryInterface(Ci.nsIFile); + + const startBytes = file.diskCapacity; + Assert.ok(!!startBytes); // Not 0, undefined etc. + + file.append("testfile"); + if (file.exists()) { + file.remove(true); + } + file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + + const endBytes = file.diskCapacity; + Assert.ok(!!endBytes); // Not 0, undefined etc. + Assert.ok(startBytes === endBytes); + + file.remove(true); +}); + +add_task( + { + // nsIFile::CreationTime is only supported on macOS and Windows. + skip_if: () => !["macosx", "win"].includes(AppConstants.platform), + }, + function test_file_creation_time() { + const file = do_get_profile(); + // If we re-use the same file name from the other tests, even if the + // file.exists() check fails at 165, this test will likely fail due to the + // creation time being copied over from the previous instance of the file on + // Windows. + file.append("testfile-creation-time"); + + if (file.exists()) { + file.remove(true); + } + + const now = Date.now(); + + file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + Assert.ok(file.exists()); + + const creationTime = file.creationTime; + Assert.ok(creationTime === file.lastModifiedTime); + + file.lastModifiedTime = now + MILLIS_PER_DAY; + + Assert.ok(creationTime !== file.lastModifiedTime); + Assert.ok(creationTime === file.creationTime); + + file.remove(true); + } +); + +add_task(function test_file_append_parent() { + const SEPARATOR = AppConstants.platform === "win" ? "\\" : "/"; + + const file = do_get_profile(); + + Assert.throws( + () => file.append(".."), + /NS_ERROR_FILE_UNRECOGNIZED_PATH/, + `nsLocalFile::Append("..") throws` + ); + + Assert.throws( + () => file.appendRelativePath(".."), + /NS_ERROR_FILE_UNRECOGNIZED_PATH/, + `nsLocalFile::AppendRelativePath("..") throws` + ); + + Assert.throws( + () => file.appendRelativePath(`foo${SEPARATOR}..${SEPARATOR}baz`), + /NS_ERROR_FILE_UNRECOGNIZED_PATH/, + `nsLocalFile::AppendRelativePath(path) fails when path contains ".."` + ); +}); diff --git a/xpcom/tests/unit/test_mac_bundle.js b/xpcom/tests/unit/test_mac_bundle.js new file mode 100644 index 0000000000..6703e8a2b8 --- /dev/null +++ b/xpcom/tests/unit/test_mac_bundle.js @@ -0,0 +1,18 @@ +function run_test() { + // this is a hack to skip the rest of the code on non-Mac platforms, + // since #ifdef is not available to xpcshell tests... + if (mozinfo.os != "mac") { + return; + } + + // OK, here's the real part of the test: + // make sure these two test bundles are recognized as bundles (or "packages") + var keynoteBundle = do_get_file("data/presentation.key"); + var appBundle = do_get_file("data/SmallApp.app"); + + Assert.ok(keynoteBundle instanceof Ci.nsILocalFileMac); + Assert.ok(appBundle instanceof Ci.nsILocalFileMac); + + Assert.ok(keynoteBundle.isPackage()); + Assert.ok(appBundle.isPackage()); +} diff --git a/xpcom/tests/unit/test_mac_xattrs.js b/xpcom/tests/unit/test_mac_xattrs.js new file mode 100644 index 0000000000..b387358d74 --- /dev/null +++ b/xpcom/tests/unit/test_mac_xattrs.js @@ -0,0 +1,98 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { FileUtils } = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs" +); + +const ATTR = "bogus.attr"; +const VALUE = new TextEncoder().encode("bogus"); + +async function run_test() { + const path = PathUtils.join( + Services.dirsvc.get("TmpD", Ci.nsIFile).path, + "macos-xattrs.tmp.d" + ); + await IOUtils.makeDirectory(path); + + try { + await test_macos_xattr(path); + } finally { + await IOUtils.remove(path, { recursive: true }); + } +} + +async function test_macos_xattr(tmpDir) { + const path = PathUtils.join(tmpDir, "file.tmp"); + + await IOUtils.writeUTF8(path, ""); + + const file = new FileUtils.File(path); + file.queryInterface(Cc.nsILocalFileMac); + + Assert.ok(!file.exists(), "File should not exist"); + + info("Testing reading an attribute on a file that does not exist"); + Assert.throws( + () => file.hasXAttr(ATTR), + /NS_ERROR_FILE_NOT_FOUND/, + "Non-existant files can't have attributes checked" + ); + Assert.throws( + () => file.getXAttr(ATTR), + /NS_ERROR_FILE_NOT_FOUND/, + "Non-existant files can't have attributes read" + ); + + file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + Assert.ok(file.exists(), "File exists after creation"); + + info("Testing reading an attribute that does not exist"); + Assert.ok( + !file.hasXAttr(ATTR), + "File should not have attribute before being set." + ); + Assert.throws( + () => file.getXAttr(ATTR), + /NS_ERROR_NOT_AVAILABLE/, + "Attempting to get an attribute that does not exist throws" + ); + + { + info("Testing setting and reading an attribute"); + file.setXAttr(ATTR, VALUE); + Assert.ok( + file.hasXAttr(ATTR), + "File should have attribute after being set" + ); + const result = file.getXAttr(ATTR); + + Assert.deepEqual( + Array.from(result), + Array.from(VALUE), + "File should have attribute value matching what was set" + ); + } + + info("Testing removing an attribute"); + file.delXAttr(ATTR); + Assert.ok( + !file.hasXAttr(ATTR), + "File should no longer have the attribute after removal" + ); + Assert.throws( + () => file.getXAttr(ATTR), + /NS_ERROR_NOT_AVAILABLE/, + "Attempting to get an attribute after removal results in an error" + ); + + info("Testing removing an attribute that does not exist"); + Assert.throws( + () => file.delXAttr(ATTR), + /NS_ERROR_NOT_AVAILABLE/, + "Attempting to remove an attribute that does not exist throws" + ); +} diff --git a/xpcom/tests/unit/test_notxpcom_scriptable.js b/xpcom/tests/unit/test_notxpcom_scriptable.js new file mode 100644 index 0000000000..5362894b70 --- /dev/null +++ b/xpcom/tests/unit/test_notxpcom_scriptable.js @@ -0,0 +1,67 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const kCID = Components.ID("{1f9f7181-e6c5-4f4c-8f71-08005cec8468}"); +const kContract = "@testing/notxpcomtest"; + +function run_test() { + let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); + + ok(Ci.nsIScriptableWithNotXPCOM); + + let method1Called = false; + + let testObject = { + QueryInterface: ChromeUtils.generateQI([ + "nsIScriptableOK", + "nsIScriptableWithNotXPCOM", + ]), + + method1() { + method1Called = true; + }, + + method2() { + ok(false, "method2 should not have been called!"); + }, + + method3() { + ok(false, "mehod3 should not have been called!"); + }, + + jsonly: true, + }; + + let factory = { + QueryInterface: ChromeUtils.generateQI(["nsIFactory"]), + + createInstance(iid) { + return testObject.QueryInterface(iid); + }, + }; + + registrar.registerFactory(kCID, null, kContract, factory); + + let xpcomObject = Cc[kContract].createInstance(); + ok(xpcomObject); + strictEqual(xpcomObject.jsonly, undefined); + + xpcomObject.QueryInterface(Ci.nsIScriptableOK); + + xpcomObject.method1(); + ok(method1Called); + + try { + xpcomObject.QueryInterface(Ci.nsIScriptableWithNotXPCOM); + ok(false, "Should not have implemented nsIScriptableWithNotXPCOM"); + } catch (e) { + ok( + true, + "Should not have implemented nsIScriptableWithNotXPCOM. Correctly threw error: " + + e + ); + } + strictEqual(xpcomObject.method2, undefined); +} diff --git a/xpcom/tests/unit/test_nsIMutableArray.js b/xpcom/tests/unit/test_nsIMutableArray.js new file mode 100644 index 0000000000..525196a48f --- /dev/null +++ b/xpcom/tests/unit/test_nsIMutableArray.js @@ -0,0 +1,131 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var MutableArray = CC("@mozilla.org/array;1", "nsIMutableArray"); +var SupportsString = CC("@mozilla.org/supports-string;1", "nsISupportsString"); + +function create_n_element_array(n) { + var arr = new MutableArray(); + for (let i = 0; i < n; i++) { + let str = new SupportsString(); + str.data = "element " + i; + arr.appendElement(str); + } + return arr; +} + +function test_appending_null_actually_inserts() { + var arr = new MutableArray(); + Assert.equal(0, arr.length); + arr.appendElement(null); + Assert.equal(1, arr.length); +} + +function test_object_gets_appended() { + var arr = new MutableArray(); + var str = new SupportsString(); + str.data = "hello"; + arr.appendElement(str); + Assert.equal(1, arr.length); + var obj = arr.queryElementAt(0, Ci.nsISupportsString); + Assert.equal(str, obj); +} + +function test_insert_at_beginning() { + var arr = create_n_element_array(5); + // just a sanity check + Assert.equal(5, arr.length); + var str = new SupportsString(); + str.data = "hello"; + arr.insertElementAt(str, 0); + Assert.equal(6, arr.length); + var obj = arr.queryElementAt(0, Ci.nsISupportsString); + Assert.equal(str, obj); + // check the data of all the other objects + for (let i = 1; i < arr.length; i++) { + let obj2 = arr.queryElementAt(i, Ci.nsISupportsString); + Assert.equal("element " + (i - 1), obj2.data); + } +} + +function test_replace_element() { + var arr = create_n_element_array(5); + // just a sanity check + Assert.equal(5, arr.length); + var str = new SupportsString(); + str.data = "hello"; + // replace first element + arr.replaceElementAt(str, 0); + Assert.equal(5, arr.length); + var obj = arr.queryElementAt(0, Ci.nsISupportsString); + Assert.equal(str, obj); + // replace last element + arr.replaceElementAt(str, arr.length - 1); + Assert.equal(5, arr.length); + obj = arr.queryElementAt(arr.length - 1, Ci.nsISupportsString); + Assert.equal(str, obj); + // replace after last element, should insert empty elements + arr.replaceElementAt(str, 9); + Assert.equal(10, arr.length); + obj = arr.queryElementAt(9, Ci.nsISupportsString); + Assert.equal(str, obj); + // AFAIK there's no way to check the empty elements, since you can't QI them. +} + +function test_clear() { + var arr = create_n_element_array(5); + // just a sanity check + Assert.equal(5, arr.length); + arr.clear(); + Assert.equal(0, arr.length); +} + +function test_enumerate() { + var arr = create_n_element_array(5); + Assert.equal(5, arr.length); + var i = 0; + for (let str of arr.enumerate()) { + Assert.ok(str instanceof Ci.nsISupportsString); + Assert.equal(str.data, "element " + i); + i++; + } + Assert.equal(arr.length, i); +} + +function test_nsiarrayextensions() { + // Tests to check that the extensions that make an nsArray act like an + // nsISupportsArray for iteration purposes works. + // Note: we do not want to QI here, just want to make sure the magic glue + // works as a drop-in replacement. + + let fake_nsisupports_array = create_n_element_array(5); + + // Check that |Count| works. + Assert.equal(5, fake_nsisupports_array.Count()); + + for (let i = 0; i < fake_nsisupports_array.Count(); i++) { + // Check that the generic |GetElementAt| works. + let elm = fake_nsisupports_array.GetElementAt(i); + Assert.notEqual(elm, null); + let str = elm.QueryInterface(Ci.nsISupportsString); + Assert.notEqual(str, null); + Assert.equal(str.data, "element " + i); + } +} + +var tests = [ + test_appending_null_actually_inserts, + test_object_gets_appended, + test_insert_at_beginning, + test_replace_element, + test_clear, + test_enumerate, + test_nsiarrayextensions, +]; + +function run_test() { + for (var i = 0; i < tests.length; i++) { + tests[i](); + } +} diff --git a/xpcom/tests/unit/test_nsIProcess.js b/xpcom/tests/unit/test_nsIProcess.js new file mode 100644 index 0000000000..582d10440c --- /dev/null +++ b/xpcom/tests/unit/test_nsIProcess.js @@ -0,0 +1,184 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// nsIProcess unit test +const TEST_ARGS = [ + "mozilla", + "firefox", + "thunderbird", + "seamonkey", + "foo", + "bar", + "argument with spaces", + '"argument with quotes"', +]; + +const TEST_UNICODE_ARGS = [ + "M\u00F8z\u00EEll\u00E5", + "\u041C\u043E\u0437\u0438\u043B\u043B\u0430", + "\u09AE\u09CB\u099C\u09BF\u09B2\u09BE", + "\uD808\uDE2C\uD808\uDF63\uD808\uDDB7", +]; + +// test if a process can be started, polled for its running status +// and then killed +function test_kill() { + var file = get_test_program("TestBlockingProcess"); + + var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(file); + + Assert.ok(!process.isRunning); + + try { + process.kill(); + do_throw("Attempting to kill a not-running process should throw"); + } catch (e) {} + + process.run(false, [], 0); + + Assert.ok(process.isRunning); + + process.kill(); + + Assert.ok(!process.isRunning); + + try { + process.kill(); + do_throw("Attempting to kill a not-running process should throw"); + } catch (e) {} +} + +// test if we can get an exit value from an application that is +// guaranteed to return an exit value of 42 +function test_quick() { + var file = get_test_program("TestQuickReturn"); + + var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(file); + + // to get an exit value it must be a blocking process + process.run(true, [], 0); + + Assert.equal(process.exitValue, 42); +} + +function test_args(file, args, argsAreASCII) { + var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(file); + + if (argsAreASCII) { + process.run(true, args, args.length); + } else { + process.runw(true, args, args.length); + } + + Assert.equal(process.exitValue, 0); +} + +// test if an argument can be successfully passed to an application +// that will return 0 if "mozilla" is the only argument +function test_arguments() { + test_args(get_test_program("TestArguments"), TEST_ARGS, true); +} + +// test if Unicode arguments can be successfully passed to an application +function test_unicode_arguments() { + test_args(get_test_program("TestUnicodeArguments"), TEST_UNICODE_ARGS, false); +} + +function rename_and_test(asciiName, unicodeName, args, argsAreASCII) { + var asciiFile = get_test_program(asciiName); + var asciiLeaf = asciiFile.leafName; + var unicodeLeaf = asciiLeaf.replace(asciiName, unicodeName); + + asciiFile.moveTo(null, unicodeLeaf); + + var unicodeFile = get_test_program(unicodeName); + + test_args(unicodeFile, args, argsAreASCII); + + unicodeFile.moveTo(null, asciiLeaf); +} + +// test passing ASCII and Unicode arguments to an application with a Unicode name +function test_unicode_app() { + rename_and_test( + "TestArguments", + // "Unicode" in Tamil + "\u0BAF\u0BC1\u0BA9\u0BBF\u0B95\u0BCB\u0B9F\u0BCD", + TEST_ARGS, + true + ); + + rename_and_test( + "TestUnicodeArguments", + // "Unicode" in Thai + "\u0E22\u0E39\u0E19\u0E34\u0E42\u0E04\u0E14", + TEST_UNICODE_ARGS, + false + ); +} + +// test if we get notified about a blocking process +function test_notify_blocking() { + var file = get_test_program("TestQuickReturn"); + + var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(file); + + process.runAsync([], 0, { + observe(subject, topic, data) { + process = subject.QueryInterface(Ci.nsIProcess); + Assert.equal(topic, "process-failed"); + Assert.equal(process.exitValue, 42); + test_notify_nonblocking(); + }, + }); +} + +// test if we get notified about a non-blocking process +function test_notify_nonblocking() { + var file = get_test_program("TestArguments"); + + var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(file); + + process.runAsync(TEST_ARGS, TEST_ARGS.length, { + observe(subject, topic, data) { + process = subject.QueryInterface(Ci.nsIProcess); + Assert.equal(topic, "process-finished"); + Assert.equal(process.exitValue, 0); + test_notify_killed(); + }, + }); +} + +// test if we get notified about a killed process +function test_notify_killed() { + var file = get_test_program("TestBlockingProcess"); + + var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(file); + + process.runAsync([], 0, { + observe(subject, topic, data) { + process = subject.QueryInterface(Ci.nsIProcess); + Assert.equal(topic, "process-failed"); + do_test_finished(); + }, + }); + + process.kill(); +} + +function run_test() { + set_process_running_environment(); + test_kill(); + test_quick(); + test_arguments(); + test_unicode_arguments(); + test_unicode_app(); + do_test_pending(); + test_notify_blocking(); +} diff --git a/xpcom/tests/unit/test_nsIProcess_stress.js b/xpcom/tests/unit/test_nsIProcess_stress.js new file mode 100644 index 0000000000..802f9d70aa --- /dev/null +++ b/xpcom/tests/unit/test_nsIProcess_stress.js @@ -0,0 +1,24 @@ +function run_test() { + set_process_running_environment(); + + var file = get_test_program("TestQuickReturn"); + var tm = Cc["@mozilla.org/thread-manager;1"].getService(); + + for (var i = 0; i < 1000; i++) { + var process = Cc["@mozilla.org/process/util;1"].createInstance( + Ci.nsIProcess + ); + process.init(file); + + process.run(false, [], 0); + + try { + process.kill(); + } catch (e) {} + + // We need to ensure that we process any events on the main thread - + // this allow threads to clean up properly and avoid out of memory + // errors during the test. + tm.spinEventLoopUntilEmpty(); + } +} diff --git a/xpcom/tests/unit/test_pipe.js b/xpcom/tests/unit/test_pipe.js new file mode 100644 index 0000000000..e3ccc6ef3f --- /dev/null +++ b/xpcom/tests/unit/test_pipe.js @@ -0,0 +1,55 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var Pipe = CC("@mozilla.org/pipe;1", "nsIPipe", "init"); + +function run_test() { + test_not_initialized(); + test_ends_are_threadsafe(); +} + +function test_not_initialized() { + var p = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe); + try { + var dummy = p.outputStream; + dump("dummy: " + dummy + "\n"); + throw Components.Exception("", Cr.NS_ERROR_FAILURE); + } catch (e) { + if (e.result != Cr.NS_ERROR_NOT_INITIALIZED) { + do_throw( + "using a pipe before initializing it should throw NS_ERROR_NOT_INITIALIZED" + ); + } + } +} + +function test_ends_are_threadsafe() { + var p, is, os; + + p = new Pipe(true, true, 1024, 1, null); + is = p.inputStream.QueryInterface(Ci.nsIClassInfo); + os = p.outputStream.QueryInterface(Ci.nsIClassInfo); + Assert.ok(Boolean(is.flags & Ci.nsIClassInfo.THREADSAFE)); + Assert.ok(Boolean(os.flags & Ci.nsIClassInfo.THREADSAFE)); + + p = new Pipe(true, false, 1024, 1, null); + is = p.inputStream.QueryInterface(Ci.nsIClassInfo); + os = p.outputStream.QueryInterface(Ci.nsIClassInfo); + Assert.ok(Boolean(is.flags & Ci.nsIClassInfo.THREADSAFE)); + Assert.ok(Boolean(os.flags & Ci.nsIClassInfo.THREADSAFE)); + + p = new Pipe(false, true, 1024, 1, null); + is = p.inputStream.QueryInterface(Ci.nsIClassInfo); + os = p.outputStream.QueryInterface(Ci.nsIClassInfo); + Assert.ok(Boolean(is.flags & Ci.nsIClassInfo.THREADSAFE)); + Assert.ok(Boolean(os.flags & Ci.nsIClassInfo.THREADSAFE)); + + p = new Pipe(false, false, 1024, 1, null); + is = p.inputStream.QueryInterface(Ci.nsIClassInfo); + os = p.outputStream.QueryInterface(Ci.nsIClassInfo); + Assert.ok(Boolean(is.flags & Ci.nsIClassInfo.THREADSAFE)); + Assert.ok(Boolean(os.flags & Ci.nsIClassInfo.THREADSAFE)); +} diff --git a/xpcom/tests/unit/test_process_directives.js b/xpcom/tests/unit/test_process_directives.js new file mode 100644 index 0000000000..b1975a43da --- /dev/null +++ b/xpcom/tests/unit/test_process_directives.js @@ -0,0 +1,20 @@ +function categoryExists(category, entry) { + try { + Services.catMan.getCategoryEntry(category, entry); + return true; + } catch (e) { + return false; + } +} + +function run_test() { + Components.manager.autoRegister( + do_get_file("data/process_directive.manifest") + ); + + let isChild = + Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT; + + Assert.equal(categoryExists("directives-test", "main-process"), !isChild); + Assert.equal(categoryExists("directives-test", "content-process"), isChild); +} diff --git a/xpcom/tests/unit/test_process_directives_child.js b/xpcom/tests/unit/test_process_directives_child.js new file mode 100644 index 0000000000..dca63b3563 --- /dev/null +++ b/xpcom/tests/unit/test_process_directives_child.js @@ -0,0 +1,3 @@ +function run_test() { + run_test_in_child("test_process_directives.js"); +} diff --git a/xpcom/tests/unit/test_seek_multiplex.js b/xpcom/tests/unit/test_seek_multiplex.js new file mode 100644 index 0000000000..7a469d9f48 --- /dev/null +++ b/xpcom/tests/unit/test_seek_multiplex.js @@ -0,0 +1,164 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// The string we use as data. +const data = "0123456789"; +// Number of streams in the multiplex stream. +const count = 10; + +function test_multiplex_streams() { + var MultiplexStream = CC( + "@mozilla.org/io/multiplex-input-stream;1", + "nsIMultiplexInputStream" + ); + Assert.equal(1, 1); + + var multiplex = new MultiplexStream(); + for (var i = 0; i < count; ++i) { + let s = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( + Ci.nsIStringInputStream + ); + s.setData(data, data.length); + + multiplex.appendStream(s); + } + var seekable = multiplex.QueryInterface(Ci.nsISeekableStream); + var sis = Cc["@mozilla.org/scriptableinputstream;1"].createInstance( + Ci.nsIScriptableInputStream + ); + sis.init(seekable); + // Read some data. + var readData = sis.read(20); + Assert.equal(readData, data + data); + // -- Tests for NS_SEEK_SET + // Seek to a non-zero, non-stream-boundary offset. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 2); + Assert.equal(seekable.tell(), 2); + Assert.equal(seekable.available(), 98); + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 9); + Assert.equal(seekable.tell(), 9); + Assert.equal(seekable.available(), 91); + // Seek across stream boundary. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 35); + Assert.equal(seekable.tell(), 35); + Assert.equal(seekable.available(), 65); + readData = sis.read(5); + Assert.equal(readData, data.slice(5)); + Assert.equal(seekable.available(), 60); + // Seek at stream boundaries. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 40); + Assert.equal(seekable.tell(), 40); + Assert.equal(seekable.available(), 60); + readData = sis.read(10); + Assert.equal(readData, data); + Assert.equal(seekable.tell(), 50); + Assert.equal(seekable.available(), 50); + // Rewind and read across streams. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 39); + Assert.equal(seekable.tell(), 39); + Assert.equal(seekable.available(), 61); + readData = sis.read(11); + Assert.equal(readData, data.slice(9) + data); + Assert.equal(seekable.tell(), 50); + Assert.equal(seekable.available(), 50); + // Rewind to the beginning. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0); + Assert.equal(seekable.tell(), 0); + Assert.equal(seekable.available(), 100); + // Seek to some random location + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 50); + // -- Tests for NS_SEEK_CUR + // Positive seek. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_CUR, 15); + Assert.equal(seekable.tell(), 65); + Assert.equal(seekable.available(), 35); + readData = sis.read(10); + Assert.equal(readData, data.slice(5) + data.slice(0, 5)); + Assert.equal(seekable.tell(), 75); + Assert.equal(seekable.available(), 25); + // Negative seek. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_CUR, -15); + Assert.equal(seekable.tell(), 60); + Assert.equal(seekable.available(), 40); + readData = sis.read(10); + Assert.equal(readData, data); + Assert.equal(seekable.tell(), 70); + Assert.equal(seekable.available(), 30); + + // -- Tests for NS_SEEK_END + // Normal read. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_END, -5); + Assert.equal(seekable.tell(), data.length * count - 5); + readData = sis.read(5); + Assert.equal(readData, data.slice(5)); + Assert.equal(seekable.tell(), data.length * count); + // Read across streams. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_END, -15); + Assert.equal(seekable.tell(), data.length * count - 15); + readData = sis.read(15); + Assert.equal(readData, data.slice(5) + data); + Assert.equal(seekable.tell(), data.length * count); + + // -- Try to do various edge cases + // Forward seek from the end, should throw. + var caught = false; + try { + seekable.seek(Ci.nsISeekableStream.NS_SEEK_END, 15); + } catch (e) { + caught = true; + } + Assert.equal(caught, true); + Assert.equal(seekable.tell(), data.length * count); + // Backward seek from the beginning, should be clamped. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0); + Assert.equal(seekable.tell(), 0); + seekable.seek(Ci.nsISeekableStream.NS_SEEK_CUR, -15); + Assert.equal(seekable.tell(), 0); + // Seek too far: should be clamped. + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0); + Assert.equal(seekable.tell(), 0); + seekable.seek(Ci.nsISeekableStream.NS_SEEK_CUR, 3 * data.length * count); + Assert.equal(seekable.tell(), 100); + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, data.length * count); + Assert.equal(seekable.tell(), 100); + seekable.seek(Ci.nsISeekableStream.NS_SEEK_CUR, -2 * data.length * count); + Assert.equal(seekable.tell(), 0); +} + +function test_multiplex_bug797871() { + var data2 = "1234567890123456789012345678901234567890"; + + var MultiplexStream = CC( + "@mozilla.org/io/multiplex-input-stream;1", + "nsIMultiplexInputStream" + ); + Assert.equal(1, 1); + + var multiplex = new MultiplexStream(); + let s = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( + Ci.nsIStringInputStream + ); + s.setData(data2, data2.length); + + multiplex.appendStream(s); + + var seekable = multiplex.QueryInterface(Ci.nsISeekableStream); + var sis = Cc["@mozilla.org/scriptableinputstream;1"].createInstance( + Ci.nsIScriptableInputStream + ); + sis.init(seekable); + + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 8); + Assert.equal(seekable.tell(), 8); + sis.read(2); + Assert.equal(seekable.tell(), 10); + + seekable.seek(Ci.nsISeekableStream.NS_SEEK_SET, 20); + Assert.equal(seekable.tell(), 20); +} + +function run_test() { + test_multiplex_streams(); + test_multiplex_bug797871(); +} diff --git a/xpcom/tests/unit/test_storagestream.js b/xpcom/tests/unit/test_storagestream.js new file mode 100644 index 0000000000..2a0fb1b569 --- /dev/null +++ b/xpcom/tests/unit/test_storagestream.js @@ -0,0 +1,152 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "unusedVariable" }] */ + +function run_test() { + test1(); + test2(); + test3(); + test4(); +} + +/** + * Checks that getting an input stream from a storage stream which has never had + * anything written to it throws a not-initialized exception. + */ +function test1() { + var ss = Cc["@mozilla.org/storagestream;1"].createInstance( + Ci.nsIStorageStream + ); + ss.init(1024, 1024, null); + + var unusedVariable = ss.getOutputStream(0); + var inp2 = ss.newInputStream(0); + Assert.equal(inp2.available(), 0); + Assert.ok(inp2.isNonBlocking()); + + var sis = Cc["@mozilla.org/scriptableinputstream;1"].createInstance( + Ci.nsIScriptableInputStream + ); + sis.init(inp2); + + var threw = false; + try { + sis.read(1); + } catch (ex) { + if (ex.result == Cr.NS_BASE_STREAM_WOULD_BLOCK) { + threw = true; + } else { + throw ex; + } + } + Assert.ok(threw); +} + +/** + * Checks that getting an input stream from a storage stream to which 0 bytes of + * data have been explicitly written doesn't throw an exception. + */ +function test2() { + var ss = Cc["@mozilla.org/storagestream;1"].createInstance( + Ci.nsIStorageStream + ); + ss.init(1024, 1024, null); + + var out = ss.getOutputStream(0); + out.write("", 0); + try { + ss.newInputStream(0); + } catch (e) { + do_throw("shouldn't throw exception when new input stream created"); + } +} + +/** + * Checks that reading any non-zero amount of data from a storage stream + * which has had 0 bytes written to it explicitly works correctly. + */ +function test3() { + var ss = Cc["@mozilla.org/storagestream;1"].createInstance( + Ci.nsIStorageStream + ); + ss.init(1024, 1024, null); + + var out = ss.getOutputStream(0); + out.write("", 0); + try { + var inp = ss.newInputStream(0); + } catch (e) { + do_throw("newInputStream(0) shouldn't throw if write() is called: " + e); + } + + Assert.ok(inp.isNonBlocking(), "next test expects a non-blocking stream"); + + try { + var threw = false; + var bis = BIS(inp); + bis.readByteArray(5); + } catch (e) { + if (e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK) { + do_throw("wrong error thrown: " + e); + } + threw = true; + } + Assert.ok(threw, "should have thrown (nsStorageInputStream is nonblocking)"); +} + +/** + * Basic functionality test for storagestream: write data to it, get an input + * stream, and read the data back to see that it matches. + */ +function test4() { + var bytes = [65, 66, 67, 68, 69, 70, 71, 72, 73, 74]; + + var ss = Cc["@mozilla.org/storagestream;1"].createInstance( + Ci.nsIStorageStream + ); + ss.init(1024, 1024, null); + + var outStream = ss.getOutputStream(0); + + var bos = Cc["@mozilla.org/binaryoutputstream;1"].createInstance( + Ci.nsIBinaryOutputStream + ); + bos.setOutputStream(outStream); + + bos.writeByteArray(bytes); + bos.close(); + + var inp = ss.newInputStream(0); + var bis = BIS(inp); + + var count = 0; + while (count < bytes.length) { + var data = bis.read8(1); + Assert.equal(data, bytes[count++]); + } + + var threw = false; + try { + data = bis.read8(1); + } catch (e) { + if (e.result != Cr.NS_ERROR_FAILURE) { + do_throw("wrong error thrown: " + e); + } + threw = true; + } + if (!threw) { + do_throw("should have thrown but instead returned: '" + data + "'"); + } +} + +function BIS(input) { + var bis = Cc["@mozilla.org/binaryinputstream;1"].createInstance( + Ci.nsIBinaryInputStream + ); + bis.setInputStream(input); + return bis; +} diff --git a/xpcom/tests/unit/test_streams.js b/xpcom/tests/unit/test_streams.js new file mode 100644 index 0000000000..c0c644bf19 --- /dev/null +++ b/xpcom/tests/unit/test_streams.js @@ -0,0 +1,170 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var Pipe = CC("@mozilla.org/pipe;1", "nsIPipe", "init"); +var BinaryOutput = CC( + "@mozilla.org/binaryoutputstream;1", + "nsIBinaryOutputStream", + "setOutputStream" +); +var BinaryInput = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +/** + * Binary stream tests. + */ +function test_binary_streams() { + var p, is, os; + + p = new Pipe(false, false, 1024, 1, null); + is = new BinaryInput(p.inputStream); + os = new BinaryOutput(p.outputStream); + + const LargeNum = Math.pow(2, 18) + Math.pow(2, 12) + 1; + const HugeNum = Math.pow(2, 62); + const HelloStr = "Hello World"; + const HelloArray = Array.from(HelloStr, function (c) { + return c.charCodeAt(0); + }); + var countObj = {}; + var msg = {}; + var buffer = new ArrayBuffer(HelloArray.length); + + // Test reading immediately after writing. + os.writeBoolean(true); + Assert.equal(is.readBoolean(), true); + os.write8(4); + Assert.equal(is.read8(), 4); + os.write16(4); + Assert.equal(is.read16(), 4); + os.write16(1024); + Assert.equal(is.read16(), 1024); + os.write32(7); + Assert.equal(is.read32(), 7); + os.write32(LargeNum); + Assert.equal(is.read32(), LargeNum); + os.write64(LargeNum); + Assert.equal(is.read64(), LargeNum); + os.write64(1024); + Assert.equal(is.read64(), 1024); + os.write64(HugeNum); + Assert.equal(is.read64(), HugeNum); + os.writeFloat(2.5); + Assert.equal(is.readFloat(), 2.5); + // os.writeDouble(Math.SQRT2); + // do_check_eq(is.readDouble(), Math.SQRT2); + os.writeStringZ("Mozilla"); + Assert.equal(is.readCString(), "Mozilla"); + os.writeWStringZ("Gecko"); + Assert.equal(is.readString(), "Gecko"); + os.writeBytes(HelloStr, HelloStr.length); + Assert.equal(is.available(), HelloStr.length); + msg = is.readBytes(HelloStr.length); + Assert.equal(msg, HelloStr); + msg = null; + countObj.value = -1; + os.writeByteArray(HelloArray); + Assert.equal(is.available(), HelloStr.length); + msg = is.readByteArray(HelloStr.length); + Assert.equal(typeof msg, typeof HelloArray); + Assert.equal(msg.toSource(), HelloArray.toSource()); + Assert.equal(is.available(), 0); + os.writeByteArray(HelloArray); + Assert.equal( + is.readArrayBuffer(buffer.byteLength, buffer), + HelloArray.length + ); + Assert.equal([...new Uint8Array(buffer)].toSource(), HelloArray.toSource()); + Assert.equal(is.available(), 0); + + // Test writing in one big chunk. + os.writeBoolean(true); + os.write8(4); + os.write16(4); + os.write16(1024); + os.write32(7); + os.write32(LargeNum); + os.write64(LargeNum); + os.write64(1024); + os.write64(HugeNum); + os.writeFloat(2.5); + // os.writeDouble(Math.SQRT2); + os.writeStringZ("Mozilla"); + os.writeWStringZ("Gecko"); + os.writeBytes(HelloStr, HelloStr.length); + os.writeByteArray(HelloArray); + // Available should not be zero after a long write like this. + Assert.notEqual(is.available(), 0); + + // Test reading in one big chunk. + Assert.equal(is.readBoolean(), true); + Assert.equal(is.read8(), 4); + Assert.equal(is.read16(), 4); + Assert.equal(is.read16(), 1024); + Assert.equal(is.read32(), 7); + Assert.equal(is.read32(), LargeNum); + Assert.equal(is.read64(), LargeNum); + Assert.equal(is.read64(), 1024); + Assert.equal(is.read64(), HugeNum); + Assert.equal(is.readFloat(), 2.5); + // do_check_eq(is.readDouble(), Math.SQRT2); + Assert.equal(is.readCString(), "Mozilla"); + Assert.equal(is.readString(), "Gecko"); + // Remember, we wrote HelloStr twice - once as a string, and then as an array. + Assert.equal(is.available(), HelloStr.length * 2); + msg = is.readBytes(HelloStr.length); + Assert.equal(msg, HelloStr); + msg = null; + countObj.value = -1; + Assert.equal(is.available(), HelloStr.length); + msg = is.readByteArray(HelloStr.length); + Assert.equal(typeof msg, typeof HelloArray); + Assert.equal(msg.toSource(), HelloArray.toSource()); + Assert.equal(is.available(), 0); + + // Test for invalid actions. + os.close(); + is.close(); + + try { + os.writeBoolean(false); + do_throw("Not reached!"); + } catch (e) { + if ( + !(e instanceof Ci.nsIException && e.result == Cr.NS_BASE_STREAM_CLOSED) + ) { + throw e; + } + // do nothing + } + + try { + is.available(); + do_throw("Not reached!"); + } catch (e) { + if ( + !(e instanceof Ci.nsIException && e.result == Cr.NS_BASE_STREAM_CLOSED) + ) { + throw e; + } + // do nothing + } + + try { + is.readBoolean(); + do_throw("Not reached!"); + } catch (e) { + if (!(e instanceof Ci.nsIException && e.result == Cr.NS_ERROR_FAILURE)) { + throw e; + } + // do nothing + } +} + +function run_test() { + test_binary_streams(); +} diff --git a/xpcom/tests/unit/test_stringstream.js b/xpcom/tests/unit/test_stringstream.js new file mode 100644 index 0000000000..0b9dcf3c5e --- /dev/null +++ b/xpcom/tests/unit/test_stringstream.js @@ -0,0 +1,20 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function run_test() { + var s = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( + Ci.nsIStringInputStream + ); + var body = "This is a test"; + s.setData(body, body.length); + Assert.equal(s.available(), body.length); + + var sis = Cc["@mozilla.org/scriptableinputstream;1"].createInstance( + Ci.nsIScriptableInputStream + ); + sis.init(s); + + Assert.equal(sis.read(body.length), body); +} diff --git a/xpcom/tests/unit/test_symlinks.js b/xpcom/tests/unit/test_symlinks.js new file mode 100644 index 0000000000..8c0d25f792 --- /dev/null +++ b/xpcom/tests/unit/test_symlinks.js @@ -0,0 +1,139 @@ +const CWD = do_get_cwd(); + +const DIR_TARGET = "target"; +const DIR_LINK = "link"; +const DIR_LINK_LINK = "link_link"; +const FILE_TARGET = "target.txt"; +const FILE_LINK = "link.txt"; +const FILE_LINK_LINK = "link_link.txt"; + +const DOES_NOT_EXIST = "doesnotexist"; +const DANGLING_LINK = "dangling_link"; +const LOOP_LINK = "loop_link"; + +const nsIFile = Ci.nsIFile; + +var process; +function createSymLink(from, to) { + if (!process) { + var ln = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); + ln.initWithPath("/bin/ln"); + + process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + process.init(ln); + } + + const args = ["-s", from, to]; + process.run(true, args, args.length); + Assert.equal(process.exitValue, 0); +} + +function makeSymLink(from, toName, relative) { + var to = from.parent; + to.append(toName); + + if (relative) { + createSymLink(from.leafName, to.path); + } else { + createSymLink(from.path, to.path); + } + + Assert.ok(to.isSymlink()); + + print("---"); + print(from.path); + print(to.path); + print(to.target); + + if (from.leafName != DOES_NOT_EXIST && from.isSymlink()) { + // XXXjag wish I could set followLinks to false so we'd just get + // the symlink's direct target instead of the final target. + Assert.equal(from.target, to.target); + } else { + Assert.equal(from.path, to.target); + } + + return to; +} + +function setupTestDir(testDir, relative) { + var targetDir = testDir.clone(); + targetDir.append(DIR_TARGET); + + if (testDir.exists()) { + testDir.remove(true); + } + Assert.ok(!testDir.exists()); + + testDir.create(nsIFile.DIRECTORY_TYPE, 0o777); + + targetDir.create(nsIFile.DIRECTORY_TYPE, 0o777); + + var targetFile = testDir.clone(); + targetFile.append(FILE_TARGET); + targetFile.create(nsIFile.NORMAL_FILE_TYPE, 0o666); + + var imaginary = testDir.clone(); + imaginary.append(DOES_NOT_EXIST); + + var loop = testDir.clone(); + loop.append(LOOP_LINK); + + var dirLink = makeSymLink(targetDir, DIR_LINK, relative); + var fileLink = makeSymLink(targetFile, FILE_LINK, relative); + + makeSymLink(dirLink, DIR_LINK_LINK, relative); + makeSymLink(fileLink, FILE_LINK_LINK, relative); + + makeSymLink(imaginary, DANGLING_LINK, relative); + + try { + makeSymLink(loop, LOOP_LINK, relative); + Assert.ok(false); + } catch (e) {} +} + +function createSpaces(dirs, files, links) { + function longest(a, b) { + return a.length > b.length ? a : b; + } + return dirs.concat(files, links).reduce(longest, "").replace(/./g, " "); +} + +function testSymLinks(testDir, relative) { + setupTestDir(testDir, relative); + + const dirLinks = [DIR_LINK, DIR_LINK_LINK]; + const fileLinks = [FILE_LINK, FILE_LINK_LINK]; + const otherLinks = [DANGLING_LINK, LOOP_LINK]; + const dirs = [DIR_TARGET].concat(dirLinks); + const files = [FILE_TARGET].concat(fileLinks); + const links = otherLinks.concat(dirLinks, fileLinks); + + const spaces = createSpaces(dirs, files, links); + const bools = { false: " false", true: " true " }; + print(spaces + " dir file symlink"); + var dirEntries = testDir.directoryEntries; + while (dirEntries.hasMoreElements()) { + const file = dirEntries.nextFile; + const name = file.leafName; + print( + name + + spaces.substring(name.length) + + bools[file.isDirectory()] + + bools[file.isFile()] + + bools[file.isSymlink()] + ); + Assert.equal(file.isDirectory(), dirs.includes(name)); + Assert.equal(file.isFile(), files.includes(name)); + Assert.equal(file.isSymlink(), links.includes(name)); + } +} + +function run_test() { + var testDir = CWD; + testDir.append("test_symlinks"); + + testSymLinks(testDir, false); + testSymLinks(testDir, true); +} diff --git a/xpcom/tests/unit/test_systemInfo.js b/xpcom/tests/unit/test_systemInfo.js new file mode 100644 index 0000000000..6ab67796c9 --- /dev/null +++ b/xpcom/tests/unit/test_systemInfo.js @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function run_test() { + const PROPERTIES = [ + "name", + "arch", + "version", + "pagesize", + "pageshift", + "memmapalign", + "memsize", + ]; + let sysInfo = Services.sysinfo; + + PROPERTIES.forEach(function (aPropertyName) { + print("Testing property: " + aPropertyName); + let value = sysInfo.getProperty(aPropertyName); + Assert.ok(!!value); + }); + + // This property must exist, but its value might be zero. + print("Testing property: umask"); + Assert.equal(typeof sysInfo.getProperty("umask"), "number"); +} diff --git a/xpcom/tests/unit/test_versioncomparator.js b/xpcom/tests/unit/test_versioncomparator.js new file mode 100644 index 0000000000..5744d62721 --- /dev/null +++ b/xpcom/tests/unit/test_versioncomparator.js @@ -0,0 +1,55 @@ +// Versions to test listed in ascending order, none can be equal +var comparisons = [ + "pre", + // A number that is too large to be supported should be normalized to 0. + String(0x1f0000000), + "0.9", + "0.9.1", + "1.0pre1", + "1.0pre2", + "1.0", + "1.1pre", + "1.1pre1a", + "1.1pre1", + "1.1pre10a", + "1.1pre10", + "1.1", + "1.1.0.1", + "1.1.1", + "1.1.*", + "1.*", + "2.0", + "2.1", + "3.0.-1", + "3.0", +]; + +// Every version in this list means the same version number +var equality = ["1.1pre", "1.1pre0", "1.0+"]; + +function run_test() { + for (var i = 0; i < comparisons.length; i++) { + for (var j = 0; j < comparisons.length; j++) { + var result = Services.vc.compare(comparisons[i], comparisons[j]); + if (i == j) { + if (result != 0) { + do_throw(comparisons[i] + " should be the same as itself"); + } + } else if (i < j) { + if (!(result < 0)) { + do_throw(comparisons[i] + " should be less than " + comparisons[j]); + } + } else if (!(result > 0)) { + do_throw(comparisons[i] + " should be greater than " + comparisons[j]); + } + } + } + + for (i = 0; i < equality.length; i++) { + for (j = 0; j < equality.length; j++) { + if (Services.vc.compare(equality[i], equality[j]) != 0) { + do_throw(equality[i] + " should equal " + equality[j]); + } + } + } +} diff --git a/xpcom/tests/unit/test_windows_cmdline_file.js b/xpcom/tests/unit/test_windows_cmdline_file.js new file mode 100644 index 0000000000..318f93ebec --- /dev/null +++ b/xpcom/tests/unit/test_windows_cmdline_file.js @@ -0,0 +1,22 @@ +let executableFile = Services.dirsvc.get("CurProcD", Ci.nsIFile); +executableFile.append("xpcshell.exe"); +function run_test() { + let quote = '"'; // Windows' cmd processor doesn't actually use single quotes. + for (let suffix of ["", " -osint", ` --blah "%PROGRAMFILES%"`]) { + let cmdline = quote + executableFile.path + quote + suffix; + info(`Testing with ${cmdline}`); + let f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFileWin); + f.initWithCommandLine(cmdline); + Assert.equal( + f.path, + executableFile.path, + "Should be able to recover executable path" + ); + } + + let f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFileWin); + f.initWithCommandLine("%ComSpec% -c echo 'hi'"); + let cmd = Services.dirsvc.get("SysD", Ci.nsIFile); + cmd.append("cmd.exe"); + Assert.equal(f.path, cmd.path, "Should be able to replace env vars."); +} diff --git a/xpcom/tests/unit/test_windows_registry.js b/xpcom/tests/unit/test_windows_registry.js new file mode 100644 index 0000000000..691c0461c3 --- /dev/null +++ b/xpcom/tests/unit/test_windows_registry.js @@ -0,0 +1,204 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const nsIWindowsRegKey = Ci.nsIWindowsRegKey; +let regKeyComponent = Cc["@mozilla.org/windows-registry-key;1"]; + +function run_test() { + //* create a key structure in a spot that's normally writable (somewhere under HKCU). + let testKey = regKeyComponent.createInstance(nsIWindowsRegKey); + + // If it's already present because a previous test crashed or didn't clean up properly, clean it up first. + let keyName = BASE_PATH + "\\" + TESTDATA_KEYNAME; + setup_test_run(testKey, keyName); + + //* test that the write* functions write stuff + test_writing_functions(testKey); + + //* check that the valueCount/getValueName functions work for the values we just wrote + test_value_functions(testKey); + + //* check that the get* functions work for the values we just wrote. + test_reading_functions(testKey); + + //* check that the get* functions fail with the right exception codes if we ask for the wrong type or if the value name doesn't exist at all + test_invalidread_functions(testKey); + + //* check that creating/enumerating/deleting child keys works + test_childkey_functions(testKey); + + //* clean up + cleanup_test_run(testKey, keyName); +} + +function setup_test_run(testKey, keyName) { + info("Setup test run"); + try { + testKey.open( + nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + keyName, + nsIWindowsRegKey.ACCESS_READ + ); + info("Test key exists. Needs cleanup."); + cleanup_test_run(testKey, keyName); + } catch (e) { + if (!(e instanceof Ci.nsIException && e.result == Cr.NS_ERROR_FAILURE)) { + throw e; + } + } + + testKey.create( + nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + keyName, + nsIWindowsRegKey.ACCESS_ALL + ); +} + +function test_writing_functions(testKey) { + strictEqual(testKey.valueCount, 0); + + strictEqual(testKey.hasValue(TESTDATA_STRNAME), false); + testKey.writeStringValue(TESTDATA_STRNAME, TESTDATA_STRVALUE); + strictEqual(testKey.hasValue(TESTDATA_STRNAME), true); + + strictEqual(testKey.hasValue(TESTDATA_INTNAME), false); + testKey.writeIntValue(TESTDATA_INTNAME, TESTDATA_INTVALUE); + + strictEqual(testKey.hasValue(TESTDATA_INT64NAME), false); + testKey.writeInt64Value(TESTDATA_INT64NAME, TESTDATA_INT64VALUE); + + strictEqual(testKey.hasValue(TESTDATA_BINARYNAME), false); + testKey.writeBinaryValue(TESTDATA_BINARYNAME, TESTDATA_BINARYVALUE); +} + +function test_value_functions(testKey) { + strictEqual(testKey.valueCount, 4); + strictEqual(testKey.getValueName(0), TESTDATA_STRNAME); + strictEqual(testKey.getValueName(1), TESTDATA_INTNAME); + strictEqual(testKey.getValueName(2), TESTDATA_INT64NAME); + strictEqual(testKey.getValueName(3), TESTDATA_BINARYNAME); +} + +function test_reading_functions(testKey) { + strictEqual( + testKey.getValueType(TESTDATA_STRNAME), + nsIWindowsRegKey.TYPE_STRING + ); + strictEqual(testKey.readStringValue(TESTDATA_STRNAME), TESTDATA_STRVALUE); + + strictEqual( + testKey.getValueType(TESTDATA_INTNAME), + nsIWindowsRegKey.TYPE_INT + ); + strictEqual(testKey.readIntValue(TESTDATA_INTNAME), TESTDATA_INTVALUE); + + strictEqual( + testKey.getValueType(TESTDATA_INT64NAME), + nsIWindowsRegKey.TYPE_INT64 + ); + strictEqual(testKey.readInt64Value(TESTDATA_INT64NAME), TESTDATA_INT64VALUE); + + strictEqual( + testKey.getValueType(TESTDATA_BINARYNAME), + nsIWindowsRegKey.TYPE_BINARY + ); + strictEqual( + testKey.readBinaryValue(TESTDATA_BINARYNAME), + TESTDATA_BINARYVALUE + ); +} + +function test_invalidread_functions(testKey) { + try { + testKey.readIntValue(TESTDATA_STRNAME); + do_throw("Reading an integer from a string registry value should throw."); + } catch (e) { + if (!(e instanceof Ci.nsIException && e.result == Cr.NS_ERROR_FAILURE)) { + throw e; + } + } + + try { + let val = testKey.readStringValue(TESTDATA_INTNAME); + do_throw( + "Reading an string from an Int registry value should throw." + val + ); + } catch (e) { + if (!(e instanceof Ci.nsIException && e.result == Cr.NS_ERROR_FAILURE)) { + throw e; + } + } + + try { + testKey.readStringValue(TESTDATA_INT64NAME); + do_throw("Reading an string from an Int64 registry value should throw."); + } catch (e) { + if (!(e instanceof Ci.nsIException && e.result == Cr.NS_ERROR_FAILURE)) { + throw e; + } + } + + try { + testKey.readStringValue(TESTDATA_BINARYNAME); + do_throw("Reading a string from an Binary registry value should throw."); + } catch (e) { + if (!(e instanceof Ci.nsIException && e.result == Cr.NS_ERROR_FAILURE)) { + throw e; + } + } +} + +function test_childkey_functions(testKey) { + strictEqual(testKey.childCount, 0); + strictEqual(testKey.hasChild(TESTDATA_CHILD_KEY), false); + + let childKey = testKey.createChild( + TESTDATA_CHILD_KEY, + nsIWindowsRegKey.ACCESS_ALL + ); + childKey.close(); + + strictEqual(testKey.childCount, 1); + strictEqual(testKey.hasChild(TESTDATA_CHILD_KEY), true); + strictEqual(testKey.getChildName(0), TESTDATA_CHILD_KEY); + + childKey = testKey.openChild(TESTDATA_CHILD_KEY, nsIWindowsRegKey.ACCESS_ALL); + testKey.removeChild(TESTDATA_CHILD_KEY); + strictEqual(testKey.childCount, 0); + strictEqual(testKey.hasChild(TESTDATA_CHILD_KEY), false); +} + +function cleanup_test_run(testKey, keyName) { + info("Cleaning up test."); + + for (var i = 0; i < testKey.childCount; i++) { + testKey.removeChild(testKey.getChildName(i)); + } + testKey.close(); + + let baseKey = regKeyComponent.createInstance(nsIWindowsRegKey); + baseKey.open( + nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + BASE_PATH, + nsIWindowsRegKey.ACCESS_ALL + ); + baseKey.removeChild(TESTDATA_KEYNAME); + baseKey.close(); +} + +// Test data used above. +const BASE_PATH = "SOFTWARE"; +const TESTDATA_KEYNAME = "TestRegXPC"; +const TESTDATA_STRNAME = "AString"; +const TESTDATA_STRVALUE = "The quick brown fox jumps over the lazy dog."; +const TESTDATA_INTNAME = "AnInteger"; +const TESTDATA_INTVALUE = 65536; +const TESTDATA_INT64NAME = "AnInt64"; +const TESTDATA_INT64VALUE = 9223372036854775000; +const TESTDATA_BINARYNAME = "ABinary"; +const TESTDATA_BINARYVALUE = "She sells seashells by the seashore"; +const TESTDATA_CHILD_KEY = "TestChildKey"; diff --git a/xpcom/tests/unit/xpcshell.toml b/xpcom/tests/unit/xpcshell.toml new file mode 100644 index 0000000000..a542804b64 --- /dev/null +++ b/xpcom/tests/unit/xpcshell.toml @@ -0,0 +1,113 @@ +[DEFAULT] +head = "head_xpcom.js" +support-files = [ + "data/**", + "xpcomtest.xpt", +] +generated-files = "xpcomtest.xpt" + +["test_bug121341.js"] + +["test_bug325418.js"] + +["test_bug332389.js"] + +["test_bug333505.js"] + +["test_bug364285-1.js"] + +["test_bug374754.js"] + +["test_bug476919.js"] +# Creating a symlink requires admin or developer mode on Windows. +skip-if = ["os == 'win'"] +# Bug 676998: test fails consistently on Android +fail-if = ["os == 'android'"] + +["test_bug478086.js"] + +["test_bug745466.js"] +skip-if = ["os == 'win'"] +# Bug 676998: test fails consistently on Android +fail-if = ["os == 'android'"] + +["test_bug1434856.js"] + +["test_console_service_callFunctionAndLogException.js"] + +["test_debugger_malloc_size_of.js"] + +["test_file_createUnique.js"] + +["test_file_equality.js"] + +["test_file_renameTo.js"] + +["test_getTimers.js"] +skip-if = ["os == 'android'"] + +["test_hidden_files.js"] + +["test_home.js"] +# Bug 676998: test fails consistently on Android +fail-if = ["os == 'android'"] + +["test_iniParser.js"] + +["test_ioutil.js"] + +["test_localfile.js"] + +["test_mac_bundle.js"] + +["test_mac_xattrs.js"] +run-if = ["os == 'mac'"] + +["test_notxpcom_scriptable.js"] + +["test_nsIMutableArray.js"] + +["test_nsIProcess.js"] +skip-if = [ + "os == 'win'", # Bug 1325609 + "os == 'linux'", # Bug 676998 + "os == 'android'", # Bug 1631671 +] + +["test_nsIProcess_stress.js"] +skip-if = [ + "os == 'win'", # bug 676412, test isn't needed on windows and runs really slowly + "ccov", # bug 1394989 +] + +["test_pipe.js"] + +["test_process_directives.js"] + +["test_process_directives_child.js"] +skip-if = ["os == 'android'"] + +["test_seek_multiplex.js"] + +["test_storagestream.js"] + +["test_streams.js"] + +["test_stringstream.js"] + +["test_symlinks.js"] +# Creating a symlink requires admin or developer mode on Windows. +skip-if = ["os == 'win'"] +# Bug 676998: test fails consistently on Android +fail-if = ["os == 'android'"] + +["test_systemInfo.js"] + +["test_versioncomparator.js"] +skip-if = ["os == 'win' && asan"] # Bug 1763002 + +["test_windows_cmdline_file.js"] +run-if = ["os == 'win'"] + +["test_windows_registry.js"] +run-if = ["os == 'win'"] |