Error (don't just warn) on unknown architecture (#935)

Also, add tests for unknown architecture and wrong bitness and
add a mechanism (`EMSDK_ARCH`) to override the architecture assumed
by emsdk.
diff --git a/emsdk.py b/emsdk.py
index 067a89e..8c0dbd6 100644
--- a/emsdk.py
+++ b/emsdk.py
@@ -67,6 +67,11 @@
   print(msg, file=sys.stderr)
 
 
+def exit_with_error(msg):
+  errlog('error: %s' % msg)
+  sys.exit(1)
+
+
 MINGW = False
 MSYS = False
 if os.getenv('MSYSTEM'):
@@ -111,20 +116,18 @@
 else:
   ENVPATH_SEPARATOR = ':'
 
-ARCH = 'unknown'
 # platform.machine() may return AMD64 on windows, so standardize the case.
-machine = platform.machine().lower()
+machine = os.getenv('EMSDK_ARCH', platform.machine().lower())
 if machine.startswith('x64') or machine.startswith('amd64') or machine.startswith('x86_64'):
   ARCH = 'x86_64'
 elif machine.endswith('86'):
   ARCH = 'x86'
 elif machine.startswith('aarch64') or machine.lower().startswith('arm64'):
   ARCH = 'aarch64'
-elif platform.machine().startswith('arm'):
+elif machine.startswith('arm'):
   ARCH = 'arm'
 else:
-  errlog("Warning: unknown machine architecture " + machine)
-  errlog()
+  exit_with_error('unknown machine architecture: ' + machine)
 
 # Don't saturate all cores to not steal the whole system, but be aggressive.
 CPU_CORES = int(os.environ.get('EMSDK_NUM_CORES', max(multiprocessing.cpu_count() - 1, 1)))
@@ -2131,8 +2134,7 @@
 
 
 def is_os_64bit():
-  # http://stackoverflow.com/questions/2208828/detect-64bit-os-windows-in-python
-  return platform.machine().endswith('64')
+  return ARCH.endswith('64')
 
 
 def find_latest_version():
@@ -2269,11 +2271,6 @@
   return sorted(items, key=version_key)
 
 
-def exit_with_error(msg):
-  errlog('error: %s' % msg)
-  sys.exit(1)
-
-
 # Load the json info for emscripten-releases.
 def load_releases_info():
   if not hasattr(load_releases_info, 'cached_info'):
diff --git a/test/test.py b/test/test.py
index fac6a00..deb7240 100755
--- a/test/test.py
+++ b/test/test.py
@@ -52,14 +52,14 @@
 
   if expected:
     for x in listify(expected):
-      assert x in stdout, 'call had the right output: ' + stdout + '\n[[[' + x + ']]]'
+      assert x in stdout, 'expected output missing: ' + stdout + '\n[[[' + x + ']]]'
   if unexpected:
     for x in listify(unexpected):
-      assert x not in stdout, 'call had the wrong output: ' + stdout + '\n[[[' + x + ']]]'
+      assert x not in stdout, 'unexpected output present: ' + stdout + '\n[[[' + x + ']]]'
 
 
-def failing_call_with_output(cmd, expected):
-  proc = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+def failing_call_with_output(cmd, expected, env=None):
+  proc = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=env)
   stdout, stderr = proc.communicate()
   if WINDOWS:
     print('warning: skipping part of failing_call_with_output() due to error codes not being propagated (see #592)')
@@ -137,6 +137,20 @@
     run_emsdk('install latest')
     run_emsdk('activate latest')
 
+  def test_unknown_arch(self):
+    env = os.environ.copy()
+    env['EMSDK_ARCH'] = 'mips'
+    failing_call_with_output(emsdk + ' install latest',
+                             expected='unknown machine architecture: mips',
+                             env=env)
+
+  def test_wrong_bitness(self):
+    env = os.environ.copy()
+    env['EMSDK_ARCH'] = 'x86'
+    failing_call_with_output(emsdk + ' install sdk-latest-64bit',
+                             expected='is only provided for 64-bit OSe',
+                             env=env)
+
   def test_already_installed(self):
     # Test we don't re-download unnecessarily
     checked_call_with_output(emsdk + ' install latest', expected='already installed', unexpected='Downloading:')
@@ -251,11 +265,15 @@
       if not filename.startswith('.') and not os.path.isdir(filename):
         shutil.copy2(filename, os.path.join(temp_dir, filename))
 
-    os.chdir(temp_dir)
-    run_emsdk('update')
+    olddir = os.getcwd()
+    try:
+      os.chdir(temp_dir)
+      run_emsdk('update')
 
-    print('second time')
-    run_emsdk('update')
+      print('second time')
+      run_emsdk('update')
+    finally:
+      os.chdir(olddir)
 
   def test_install_arbitrary(self):
     # Test that its possible to install arbrary emscripten-releases SDKs
@@ -278,6 +296,7 @@
     # With EMSDK_KEEP_DOWNLOADS the downloading should happen on the first
     # install of 2.0.28, and again when we install 2.0.29, but not on the
     # second install of 2.0.28 because the zip should already be local.
+    shutil.rmtree('zips')
     checked_call_with_output(emsdk + ' install 2.0.28', expected='Downloading:', env=env)
     checked_call_with_output(emsdk + ' install 2.0.29', expected='Downloading:', env=env)
     checked_call_with_output(emsdk + ' install 2.0.28', expected='already downloaded, skipping', unexpected='Downloading:', env=env)