Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 27 Oct 2012 17:29:15 -0400
changeset 111753 3c70c13dd261d44814cadcef33032ad0ceb454a1
parent 111752 eb63fc7d719deab06e883895248be80ecbe379aa (current diff)
parent 111747 c5428231b6f7b17a29ebd6ded683ed9b312c06b1 (diff)
child 111754 3621795c03e1cea38ed5a64d48d3eb331fcbbf4b
child 111755 19dc5eccbc0693f0740cf8baeb582f809fe5dfa9
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
Merge m-c to inbound.
--- a/dom/sms/tests/marionette/manifest.ini
+++ b/dom/sms/tests/marionette/manifest.ini
@@ -6,8 +6,9 @@ qemu = true
 ;[test_between_emulators.py]
 [test_incoming.js]
 [test_outgoing.js]
 [test_message_classes.js]
 [test_incoming_delete.js]
 [test_outgoing_delete.js]
 [test_getmessage.js]
 [test_getmessage_notfound.js]
+[test_timestamp.js]
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_timestamp.js
@@ -0,0 +1,187 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 15000;
+
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+SpecialPowers.addPermission("sms", true, document);
+
+let sms = window.navigator.mozSms;
+let inText;
+let remoteNumber = "5559997777";
+let outText;
+let gotSmsOnsent;
+let gotReqOnsuccess;
+let inSmsId = 0;
+let outSmsId = 0;
+let inSmsTime = 0;
+let outSmsTime = 0;
+let testCount = 10;
+
+function verifyInitialState() {
+  log("Verifying initial state.");
+  ok(sms, "mozSms");
+  simulateIncomingSms();  
+}
+
+function simulateIncomingSms() {
+  log("Simulating incoming SMS.");
+
+  sms.onreceived = function onreceived(event) {
+    log("Received 'onreceived' smsmanager event.");
+    let incomingSms = event.message;
+    ok(incomingSms, "incoming sms");
+    ok(incomingSms.id, "sms id");
+    inSmsId = incomingSms.id;
+    is(incomingSms.body, inText, "msg body");
+    is(incomingSms.delivery, "received", "delivery");
+    is(incomingSms.read, false, "read");
+    is(incomingSms.receiver, null, "receiver");
+    is(incomingSms.sender, remoteNumber, "sender");
+    ok(incomingSms.timestamp instanceof Date, "timestamp is instanceof date");
+    // The max resolution of the SCTS (SMS Centre TimeStamp) is one second
+    // therefore we want to compare in seconds not milliseconds. No need to
+    // round received sms timestamp, the value is in milliseconds but at
+    // seconds resolution already (always ends with 000) so just convert
+    inSmsTime = Math.floor(incomingSms.timestamp.getTime() / 1000);
+    log("Received SMS (id: " + inSmsId + ") timestamp: " + inSmsTime + ".");
+    if(outSmsTime) {
+      // Test is repeating; compare received SMS timestamp with last sent sms.
+      // Can be some time drift between the SCTS and host/emulator, but we are
+      // comparing seconds (not milliseconds) so should be ok. If this test
+      // goes random orange, then may need to add a 1 second lee-way here.
+      if(inSmsTime >= outSmsTime) {
+        log("Timestamp in sms " + inSmsId + " is >= timestamp in sms "
+            + outSmsId + ".");
+      } else {
+        log("* Timestamp in sms " + inSmsId + " is < timestamp in sms "
+            + outSmsId + ".");
+        ok(false, "sms timestamp is incorrect");
+      }
+    }
+    sendSms();
+  };
+  // Simulate incoming sms sent from remoteNumber to our emulator
+  inText = "Incoming SMS " + Date.now();
+  runEmulatorCmd("sms send " + remoteNumber + " " + inText, function(result) {
+    is(result[0], "OK", "emulator output");
+  });
+}
+
+function sendSms() {
+  log("Sending an SMS.");
+  let gotSmsOnsent = false;
+  let gotReqOnsuccess = false;  
+  sms.onsent = function(event) {
+    log("Received 'onsent' smsmanager event.");
+    gotSmsOnsent = true;
+    let sentSms = event.message;
+    ok(sentSms, "outgoing sms");
+    ok(sentSms.id, "sms id");
+    outSmsId = sentSms.id;
+    is(sentSms.body, outText, "msg body");
+    is(sentSms.delivery, "sent", "delivery");
+    is(sentSms.read, true, "read");
+    is(sentSms.receiver, remoteNumber, "receiver");
+    is(sentSms.sender, null, "sender");
+    ok(sentSms.timestamp instanceof Date, "timestamp is instanceof date");
+    // The max resolution of the SCTS (SMS Centre TimeStamp) is one second
+    // therefore we want to compare in seconds not milliseconds. Round the
+    // sent sms timestamp to nearest second.
+    outSmsTime = Math.round(sentSms.timestamp.getTime() / 1000);
+    log("Sent SMS (id: " + outSmsId + ") timestamp: " + outSmsTime + ".");
+
+    if (gotSmsOnsent && gotReqOnsuccess) { verifyTimeStamps(); }
+  };
+  outText = "Outgoing SMS " + Date.now();
+  let requestRet = sms.send(remoteNumber, outText);
+  ok(requestRet, "smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    gotReqOnsuccess = true;
+    if(event.target.result){
+      if (gotSmsOnsent && gotReqOnsuccess) { verifyTimeStamps(); }
+    } else {
+      log("smsrequest returned false for sms.send");
+      ok(false,"SMS send failed");
+      cleanUp();
+    }
+  };
+
+  requestRet.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.send request returned unexpected error: "
+        + event.target.error.name );
+    cleanUp();
+  };
+}
+
+function verifyTimeStamps() {
+  // Compare sent sms timestamp with that of the previously received sms.
+  // Can be some time drift between the SCTS and host/emulator, but we are
+  // comparing seconds (not milliseconds) so should be ok. If this test
+  // goes random orange, then may need to add a 1 second lee-way here.
+  if(outSmsTime >= inSmsTime) {
+    log("Timestamp in sms " + outSmsId + " is >= timestamp in sms "
+        + inSmsId + ".");
+  } else {
+    log("* Timestamp in sms " + outSmsId + " is < timestamp in sms "
+        + inSmsId + ".");
+    ok(false, "sms timestamp is incorrect");
+  }
+  deleteMsgs();
+}
+
+function deleteMsgs() {
+  log("Deleting SMS (id: " + inSmsId + ").");
+  let requestRet = sms.delete(inSmsId);
+  ok(requestRet,"smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if(event.target.result){
+      log("Deleting SMS (id: " + outSmsId + ").");
+      let nextReqRet = sms.delete(outSmsId);
+      ok(nextReqRet,"smsrequest obj returned");
+
+      nextReqRet.onsuccess = function(event) {
+        log("Received 'onsuccess' smsrequest event.");
+        if(event.target.result) {
+          if(--testCount) {
+            simulateIncomingSms();
+          } else {
+            cleanUp();
+          }
+        } else {
+          log("smsrequest returned false for sms.delete");
+          ok(false,"SMS delete failed");
+          cleanUp();
+        }
+      };
+    } else {
+      log("smsrequest returned false for sms.delete");
+      ok(false,"SMS delete failed");
+      cleanUp();
+    }
+  };
+
+  requestRet.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.delete request returned unexpected error: "
+        + event.target.error.name );
+    cleanUp();
+  };
+}
+
+function cleanUp() {
+  sms.onreceived = null;
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.setBoolPref("dom.sms.enabled", false);
+  finish();
+}
+
+// Start the test
+verifyInitialState();
--- a/testing/mochitest/runtestsb2g.py
+++ b/testing/mochitest/runtestsb2g.py
@@ -206,16 +206,17 @@ class B2GMochitest(Mochitest):
         self._dm = devmgr
         self.runSSLTunnel = False
         self.remoteProfile = options.remoteTestRoot + '/profile'
         self._automation.setRemoteProfile(self.remoteProfile)
         self.remoteLog = options.remoteLogFile
         self.localLog = None
         self.userJS = '/data/local/user.js'
         self.remoteMozillaPath = '/data/b2g/mozilla'
+        self.bundlesDir = '/system/b2g/distribution/bundles'
         self.remoteProfilesIniPath = os.path.join(self.remoteMozillaPath, 'profiles.ini')
         self.originalProfilesIni = None
 
     def copyRemoteFile(self, src, dest):
         if self._dm.useDDCopy:
             self._dm._checkCmdAs(['shell', 'dd', 'if=%s' % src,'of=%s' % dest])
         else:
             self._dm._checkCmdAs(['shell', 'cp', src, dest])
@@ -223,16 +224,26 @@ class B2GMochitest(Mochitest):
     def origUserJSExists(self):
         return self._dm.fileExists('/data/local/user.js.orig')
 
     def cleanup(self, manifest, options):
         if self.localLog:
             self._dm.getFile(self.remoteLog, self.localLog)
             self._dm.removeFile(self.remoteLog)
 
+        # Delete any bundled extensions
+        extensionDir = os.path.join(options.profilePath, 'extensions', 'staged')
+        if os.access(extensionDir, os.F_OK):
+            for filename in os.listdir(extensionDir):
+                try:
+                    self._dm._checkCmdAs(['shell', 'rm', '-rf',
+                                          os.path.join(self.bundlesDir, filename)])
+                except devicemanager.DMError:
+                    pass
+
         if not options.emulator:
             # Remove the test profile
             self._dm._checkCmdAs(['shell', 'rm', '-r', self.remoteProfile])
 
             if self.origUserJSExists():
                 # Restore the original user.js
                 self._dm.removeFile(self.userJS)
                 self.copyRemoteFile('%s.orig' % self.userJS, self.userJS)
@@ -390,16 +401,29 @@ user_pref("network.dns.localDomains","ap
         # Copy the profile to the device.
         self._dm._checkCmdAs(['shell', 'rm', '-r', self.remoteProfile])
         try:
             self._dm.pushDir(options.profilePath, self.remoteProfile)
         except devicemanager.DMError:
             print "Automation Error: Unable to copy profile to device."
             raise
 
+        # Copy the extensions to the B2G bundles dir.
+        extensionDir = os.path.join(options.profilePath, 'extensions', 'staged')
+        # need to write to read-only dir
+        self._dm._checkCmdAs(['remount'])
+        for filename in os.listdir(extensionDir):
+            self._dm._checkCmdAs(['shell', 'rm', '-rf',
+                                  os.path.join(self.bundlesDir, filename)])
+        try:
+            self._dm.pushDir(extensionDir, self.bundlesDir)
+        except devicemanager.DMError:
+            print "Automation Error: Unable to copy extensions to device."
+            raise
+
         # In B2G, user.js is always read from /data/local, not the profile
         # directory.  Backup the original user.js first so we can restore it.
         if not self._dm.fileExists('%s.orig' % self.userJS):
             self.copyRemoteFile(self.userJS, '%s.orig' % self.userJS)
         self._dm.pushFile(os.path.join(options.profilePath, "user.js"), self.userJS)
         self.updateProfilesIni(self.remoteProfile)
         options.profilePath = self.remoteProfile
         options.logFile = self.localLog
--- a/testing/tps/setup.py
+++ b/testing/tps/setup.py
@@ -2,19 +2,19 @@
 # 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/.
 
 import sys
 from setuptools import setup, find_packages
 
 version = '0.3'
 
-deps = ['mozinfo == 0.3.3', 'mozprofile == 0.4',
-        'mozprocess == 0.4', 'mozrunner == 5.8', 'mozregression == 0.6.3',
-        'mozautolog == 0.2.4', 'mozautoeslib == 0.1.1']
+deps = ['mozinfo >= 0.3.3', 'mozprofile >= 0.4',
+        'mozprocess >= 0.4', 'mozrunner >= 5.8', 'mozinstall >= 1.4',
+        'mozautolog >= 0.2.4', 'mozautoeslib >= 0.1.1', 'httplib2 >= 0.7.3']
 
 # we only support python 2.6+ right now
 assert sys.version_info[0] == 2
 assert sys.version_info[1] >= 6
 
 setup(name='tps',
       version=version,
       description='run automated multi-profile sync tests',
--- a/testing/tps/tps/firefoxrunner.py
+++ b/testing/tps/tps/firefoxrunner.py
@@ -1,21 +1,22 @@
 # 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/.
 
 import copy
+import httplib2
 import os
 import shutil
 import sys
 
+import mozinstall
+
 from mozprocess.pid import get_pids
 from mozprofile import Profile
-from mozregression.mozInstall import MozInstaller
-from mozregression.utils import download_url, get_platform
 from mozrunner import FirefoxRunner
 
 class TPSFirefoxRunner(object):
 
   PROCESS_TIMEOUT = 240
 
   def __init__(self, binary):
     if binary is not None and ('http://' in binary or 'ftp://' in binary):
@@ -26,51 +27,49 @@ class TPSFirefoxRunner(object):
       self.binary = binary
     self.runner = None
     self.installdir = None
 
   def __del__(self):
     if self.installdir:
       shutil.rmtree(self.installdir, True)
 
-  def download_build(self, installdir='downloadedbuild',
-                     appname='firefox', macAppName='Minefield.app'):
+  def download_url(self, url, dest=None):
+    h = httplib2.Http()
+    resp, content = h.request(url, "GET")
+    if dest == None:
+        dest = os.path.basename(url)
+
+    local = open(dest, 'wb')
+    local.write(content)
+    local.close()
+    return dest
+
+  def download_build(self, installdir='downloadedbuild', appname='firefox'):
     self.installdir = os.path.abspath(installdir)
     buildName = os.path.basename(self.url)
     pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                buildName)
 
     # delete the build if it already exists
     if os.access(pathToBuild, os.F_OK):
       os.remove(pathToBuild)
 
     # download the build
     print "downloading build"
-    download_url(self.url, pathToBuild)
+    self.download_url(self.url, pathToBuild)
 
     # install the build
     print "installing %s" % pathToBuild
     shutil.rmtree(self.installdir, True)
-    MozInstaller(src=pathToBuild, dest=self.installdir, dest_app=macAppName)
+    binary = mozinstall.install(src=pathToBuild, dest=self.installdir)
 
     # remove the downloaded archive
     os.remove(pathToBuild)
 
-    # calculate path to binary
-    platform = get_platform()
-    if platform['name'] == 'Mac':
-      binary = '%s/%s/Contents/MacOS/%s-bin' % (installdir,
-                                                macAppName,
-                                                appname)
-    else:
-      binary = '%s/%s/%s%s' % (installdir,
-                               appname,
-                               appname,
-                               '.exe' if platform['name'] == 'Windows' else '')
-
     return binary
 
   def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
     """Runs the given FirefoxRunner with the given Profile, waits
        for completion, then returns the process exit code
     """
     if profile is None:
       profile = Profile()