text: # coding: utf-8
  
  # Import Python libs
  from __future__ import absolute_import
  import os
  import shutil
  import tempfile
  
  # Import Salt Testing libs
  from salttesting import TestCase
  from salttesting.helpers import ensure_in_syspath, destructiveTest
  
  import salt.config
  import salt.spm
  
  ensure_in_syspath('../')
  
  
  _TMP_SPM = tempfile.mkdtemp()
  
  config = salt.config.minion_config(None)
  config['file_roots'] = {'base': [os.path.join(_TMP_SPM, 'salt')]}
  config['pillar_roots'] = {'base': [os.path.join(_TMP_SPM, 'pillar')]}
  
  __opts__ = {
      'spm_logfile': os.path.join(_TMP_SPM, 'log'),
      'spm_repos_config': os.path.join(_TMP_SPM, 'etc', 'spm.repos'),
      'spm_cache_dir': os.path.join(_TMP_SPM, 'cache'),
      'spm_build_dir': os.path.join(_TMP_SPM, 'build'),
      'spm_build_exclude': ['.git'],
      'spm_db_provider': 'sqlite3',
      'spm_files_provider': 'local',
      'spm_db': os.path.join(_TMP_SPM, 'packages.db'),
      'extension_modules': os.path.join(_TMP_SPM, 'modules'),
      'file_roots': {'base': [_TMP_SPM, ]},
      'formula_path': os.path.join(_TMP_SPM, 'spm'),
      'pillar_path': os.path.join(_TMP_SPM, 'pillar'),
      'reactor_path': os.path.join(_TMP_SPM, 'reactor'),
      'assume_yes': True,
      'force': False,
  }
  
  _F1 = {
      'definition': {
          'name': 'formula1',
          'version': '1.2',
          'release': '2',
          'summary': 'test',
          'description': 'testing, nothing to see here',
      }
  }
  
  _F1['contents'] = (
      ('FORMULA', ('name: {name}\n'
                   'version: {version}\n'
                   'release: {release}\n'
                   'summary: {summary}\n'
                   'description: {description}').format(**_F1['definition'])),
      ('modules/mod1.py', '# mod1.py'),
      ('modules/mod2.py', '# mod2.py'),
      ('states/state1.sls', '# state1.sls'),
      ('states/state2.sls', '# state2.sls'),
  )
  
  
  @destructiveTest
  class SPMTestUserInterface(salt.spm.SPMUserInterface):
      '''
      Unit test user interface to SPMClient
      '''
      def __init__(self):
          self._status = []
          self._confirm = []
          self._error = []
  
      def status(self, msg):
          self._status.append(msg)
  
      def confirm(self, action):
          self._confirm.append(action)
  
      def error(self, msg):
          self._error.append(msg)
  
  
  class SPMTest(TestCase):
      def setUp(self):
          shutil.rmtree(_TMP_SPM, ignore_errors=True)
          os.mkdir(_TMP_SPM)
          self.ui = SPMTestUserInterface()
          self.client = salt.spm.SPMClient(self.ui, __opts__)
  
      def tearDown(self):
          shutil.rmtree(_TMP_SPM, ignore_errors=True)
  
      def _create_formula_files(self, formula):
          fdir = os.path.join(_TMP_SPM, formula['definition']['name'])
          shutil.rmtree(fdir, ignore_errors=True)
          os.mkdir(fdir)
          for path, contents in formula['contents']:
              path = os.path.join(fdir, path)
              dirname, _ = os.path.split(path)
              if not os.path.exists(dirname):
                  os.makedirs(dirname)
              with open(path, 'w') as f:
                  f.write(contents)
          return fdir
  
      def test_build_install(self):
          # Build package
          fdir = self._create_formula_files(_F1)
          self.client.run(['build', fdir])
          pkgpath = self.ui._status[-1].split()[-1]
          assert os.path.exists(pkgpath)
          # Install package
          self.client.run(['local', 'install', pkgpath])
          # Check filesystem
          for path, contents in _F1['contents']:
              path = os.path.join(__opts__['file_roots']['base'][0], _F1['definition']['name'], path)
              assert os.path.exists(path)
              assert open(path, 'r').read() == contents
          # Check database
          self.client.run(['info', _F1['definition']['name']])
          lines = self.ui._status[-1].split('\n')
          for key, line in (
                  ('name', 'Name: {0}'),
                  ('version', 'Version: {0}'),
                  ('release', 'Release: {0}'),
                  ('summary', 'Summary: {0}')):
              assert line.format(_F1['definition'][key]) in lines
          # Reinstall with force=False, should fail
          self.ui._error.clear()
          self.client.run(['local', 'install', pkgpath])
          assert len(self.ui._error) > 0
          # Reinstall with force=True, should succeed
          __opts__['force'] = True
          self.ui._error.clear()
          self.client.run(['local', 'install', pkgpath])
          assert len(self.ui._error) == 0
          __opts__['force'] = False
  
      def test_failure_paths(self):
          fail_args = (
              ['bogus', 'command'],
              ['create_repo'],
              ['build'],
              ['build', '/nonexistent/path'],
              ['info'],
              ['info', 'not_installed'],
              ['files'],
              ['files', 'not_installed'],
              ['install'],
              ['install', 'nonexistent.spm'],
              ['remove'],
              ['remove', 'not_installed'],
              ['local', 'bogus', 'command'],
              ['local', 'info'],
              ['local', 'info', '/nonexistent/path/junk.spm'],
              ['local', 'files'],
              ['local', 'files', '/nonexistent/path/junk.spm'],
              ['local', 'install'],
              ['local', 'install', '/nonexistent/path/junk.spm'],
              ['local', 'list'],
              ['local', 'list', '/nonexistent/path/junk.spm'],
              # XXX install failure due to missing deps
              # XXX install failure due to missing field
          )
  
          for args in fail_args:
              self.ui._error.clear()
              self.client.run(args)
              assert len(self.ui._error) > 0
  
  
  if __name__ == '__main__':
      from integration import run_tests
      run_tests(SPMTest, needs_daemon=False)
  