Ejemplo n.º 1
0
    def testStore(self):
        project = launcher.Project('/tmp/hoover', 8000)
        flagsproj = launcher.Project('/tmp/markd-attack',
                                     8001,
                                     'run-for-your-life',
                                     flags=['--vehicular-assault'])

        # make some stuff, write it out, and re-load it
        parser = ConfigParser.ConfigParser()
        parser.add_section('greeble')
        parser.add_section('grooble')

        project.SaveToConfigParser(parser, 'greeble')
        flagsproj.SaveToConfigParser(parser, 'grooble')

        self.checkProject(
            launcher.Project.ProjectWithConfigParser(parser, 'greeble'),
            project.path, project.name, project.port)

        self.checkProject(launcher.Project.ProjectWithConfigParser(
            parser, 'grooble'),
                          flagsproj.path,
                          flagsproj.name,
                          flagsproj.port,
                          flags=flagsproj.flags)
Ejemplo n.º 2
0
    def testName(self):
        p = launcher.Project('/tmp/foo', 8000, 'my_name')
        self.assertEqual('my_name', p.name)

        # make sure we cannot set the name (hidden with @property)
        def setName():
            p.name = 'doh'

        self.assertRaises(AttributeError, setName)
        self.assertEqual('my_name', p.name)
        p = launcher.Project('/tmp/foo', 8000, name='bozo')
        self.assertEqual('bozo', p.name)
Ejemplo n.º 3
0
 def testVerifyAndValid(self):
     p = launcher.Project('/tmp/foo/smin/du7737g', 8000, 'name')
     self.assertFalse(p.valid)
     p.Verify()
     self.assertFalse(p.valid)
     self.createTempProject('turbo-monkey')
     p = launcher.Project(self._temp_project, 8000)
     self.assertTrue(p.valid)
     p.Verify()
     self.assertTrue(p.valid)
     self.deleteTempProject()
     p.Verify()
     self.assertFalse(p.valid)
Ejemplo n.º 4
0
  def testDeployServer(self):

    class MockPref(object):
      def __init__(self, pref=None):
        self.pref = pref
      def Get(self, name):
        if name == launcher.Preferences.PREF_DEPLOY_SERVER:
          return self.pref
        return None

    class MockText(object):
      def __init__(self):
        self.text = None
      def SetLabel(self, text):
        self.text = text

    project = launcher.Project('path', 8000, 'project_name')
    mockpref = MockPref()
    mocktext = MockText()
    d = launcher.DeployController(None, mockpref, [project])
    d._AddDeployServerToTextField(mocktext)
    self.assertFalse(mocktext.text)

    mockpref = MockPref('hi dave')
    d = launcher.DeployController(None, mockpref, [project])
    d._AddDeployServerToTextField(mocktext)
    self.assertTrue('dave' in mocktext.text)
 def doTestThreadRun(self, killit=False):
     """Run a command, watch for state change.
 Optionally kill it to speed up death.
 """
     controller = launcher.TaskController(FakeAppController())
     project = launcher.Project('himom', 8000)
     secs = 3
     if killit:
         # If in killit mode, make sure it'll last longer than us so we
         # don't confuse kill with runout
         secs = 20
     # Start a task ripe for the killing.
     command = [sys.executable, '-c', 'import time; time.sleep(%d)' % secs]
     tt = launcher.TaskThread(controller, project, command)
     tt.start()
     # TODO(jrg): is this a reasonable chance?
     for i in range(20):
         time.sleep(0.25)
         if tt.isAlive():
             break
     self.assertTrue(tt.isAlive())
     if killit:
         tt.stop()
     for i in range(20):
         time.sleep(0.25)
         if not tt.isAlive():
             break
     self.assertFalse(tt.isAlive())
     pass
Ejemplo n.º 6
0
 def testProperties(self):
     for plist in (('foo', '/tmp/foo', 8000), ('zzz', '/yo/momma/zzz',
                                               9000)):
         p = launcher.Project(plist[1], plist[2])
         self.assertEqual(p.name, plist[0])
         self.assertEqual(p.path, plist[1])
         self.assertEqual(p.port, plist[2])
Ejemplo n.º 7
0
    def testShowModal(self):
        project = launcher.Project('path', 9000)
        for (wx_rtn, updated_calls) in ((wx.ID_OK, 1), (wx.ID_CANCEL, 0)):
            sc = launcher.SettingsController(project)
            settings_dialog = project_dialogs.ProjectSettingsDialog
            dialog_mock = mox.MockObject(settings_dialog)
            dialog_mock.ShowModal().AndReturn(wx_rtn)
            mox.Replay(dialog_mock)
            sc.dialog = dialog_mock
            actual_updated = [0]

            def plusone():
                """Must use mutable to modify var in enclosing scope."""
                actual_updated[0] += 1

            sc._UpdateProject = plusone
            rtn = sc.ShowModal()
            self.assertEqual(wx_rtn, rtn)
            mox.Verify(dialog_mock)
            self.assertEqual(updated_calls, actual_updated[0])
            # SettingsController needs to Destroy() its dialog.
            # That is done in SettingsController's __del__.
            # But that's past the mox.Verify(), so we can't expect it.
            # We can, however, make sure it doesn't cause mox
            # to yell.
            sc.dialog = None
Ejemplo n.º 8
0
    def testUpdateProject(self):
        project = launcher.Project('path', 9001)
        sc = launcher.SettingsController(project)
        # Basic change:
        # First a port...
        sc.dialog.app_port_text_ctrl.SetValue(str(1008))
        sc._UpdateProject()
        self.assertEqual(1008, project.port)
        # Then a flag.
        sc.dialog.full_flag_list_text_ctrl.SetValue('--bozo-assault')
        sc._UpdateProject()
        self.assertTrue('--bozo-assault' in project.flags)
        # Deny a change if it's running
        failures = [0]

        def plusone(arg1, arg2):
            """Must use mutable to modify var in enclosing scope."""
            failures[0] += 1

        sc.FailureMessage = plusone
        # First change the port...
        oldport = project.port
        sc.dialog.app_port_text_ctrl.SetValue(str(5555))
        project.runstate = launcher.Project.STATE_RUN
        sc._UpdateProject()
        self.assertEqual(1, failures[0])
        failures[0] = 0
        # Restore, then change the flags
        sc.dialog.app_port_text_ctrl.SetValue(str(oldport))
        sc.dialog.full_flag_list_text_ctrl.SetValue('--anti-clown-spray')
        sc._UpdateProject()
        self.assertEqual(1, failures[0])
 def testInstallDemoByName(self):
     # Create a demo source
     sourcedir = tempfile.mkdtemp()
     demo = os.path.join(sourcedir, 'sooper-dooper-demo')
     os.mkdir(demo)
     yaml = os.path.join(demo, 'app.yaml')
     f = open(yaml, 'w')
     f.write('hi mom\n')
     f.close()
     # Create a demo dest dir
     destdir = tempfile.mkdtemp()
     # Now copy a demo.
     ac = NoAskController(self.app, launcher.Project('hi', 8000))
     ac.InstallDemoByName(demo, destdir, False)
     self.assertTrue(os.path.basename(demo) in os.listdir(destdir))
     for copied_demo in os.listdir(destdir):
         self.assertTrue(
             os.path.exists(os.path.join(destdir, copied_demo, 'app.yaml')))
     # Now copy another, trying to conflict.
     ac.InstallDemoByName(demo, destdir, False)
     self.assertEqual(2, len(os.listdir(destdir)))
     for copied_demo in os.listdir(destdir):
         self.assertTrue(
             os.path.exists(os.path.join(destdir, copied_demo, 'app.yaml')))
     # Now for a 3rd to test out counter.
     ac.InstallDemoByName(demo, destdir, False)
     self.assertEqual(3, len(os.listdir(destdir)))
     # Finally, clean up.
     shutil.rmtree(sourcedir)
     shutil.rmtree(destdir)
Ejemplo n.º 10
0
 def testUpdateNameOnVerify(self):
     name = 'starting_name'
     self.createTempProject(name)
     p = launcher.Project(self._temp_project, 9000)
     self.assertEqual(name, p.name)
     name = 'ending_name'
     self.createYaml(name, self._temp_project)
     p.Verify()
     self.assertEqual(name, p.name)  # the new name
Ejemplo n.º 11
0
 def testUniquePort(self):
     table = launcher.MainTable(self._temp_filename)
     self.assertTrue(table.UniquePort() > 1024)
     ports = range(8000, 8020) + range(8021, 8200, 17)
     for i in range(len(ports)):
         table.AddProject(launcher.Project('/tmp/himom' + str(i), ports[i]))
         unused = table.UniquePort()
         self.assertTrue(unused not in ports[:i + 1])
         self.assertTrue(unused > 1024)
Ejemplo n.º 12
0
 def testInvalidProject(self):
     projects = []
     for valid in (False, True, False):
         p = launcher.Project('/tmp/foo', 8000)
         p._valid = valid
         projects.append(p)
     self.frame._MarkRowValidity = self.frame._listctrl._MarkRowValidity
     self.frame.RefreshView(projects)
     self.assertEqual(1, self.frame._listctrl.valid)
     self.assertEqual(2, self.frame._listctrl.invalid)
 def testEndModalClosure(self):
     project = launcher.Project('path', 9000)
     sc = launcher.SettingsController(project)
     for code in (wx.ID_OK, wx.ID_CANCEL):
         dialog_mock = mox.MockObject(wx.Dialog)
         dialog_mock.EndModal(code)
         mox.Replay(dialog_mock)
         closure = sc.EndModalClosure(dialog_mock, code)
         closure(None)
         mox.Verify(dialog_mock)
Ejemplo n.º 14
0
    def testRunState(self):
        p1 = launcher.Project('/tmp/foo', 8000)
        for state in launcher.Project.ALL_STATES:
            p1.runstate = state
            self.assertEqual(state, p1.runstate)
        for state in ('hi mom', 1029333, None):

            def setRunState():
                p1.runstate = state

            self.assertRaises(launcher.ProjectException, setRunState)
    def Project(self):
        """Return a project created from interaction with this dialog.

    Returns:
      A launcher.Project, or None.
    """
        if self._dialog_return_value != wx.ID_OK:
            return None
        path = self.GetPath()
        port = self.GetPort()
        if not (self._SanityCheckPath(path) and self._SanityCheckPort(port)):
            return None
        return launcher.Project(path, port)
    def Projects(self, n):
        """Return a list of N unique Projects.

    Args:
      n: the number of unique Projects we will generate
    Returns:
      A list of unique Projects
    """
        projects = []
        for i in range(n):
            name = '/tmp/himom-%d' % i
            projects.append(launcher.Project(name, i + 8000))
        return projects
    def Projects(self, n):
        """Convenience routine for creating unique projects.

    Args:
      n: number of unique projects

    Returns:
      A list of N unique projects.
    """
        projects = []
        for i in range(n):
            name = '/tmp/himom-%d' % i
            projects.append(launcher.Project(name, 8000 + i))
        return projects
Ejemplo n.º 18
0
  def testDoDeploy(self):
    project = launcher.Project('path', 8000, 'project_name')
    d = launcher.DeployController(None, None, [project])
    d._password = '******'
    self.assertFalse(d._DoDeploy()) # no name
    d._password = None
    d._authname = 'joe'
    self.assertFalse(d._DoDeploy()) # no password

    projects = [launcher.Project('path', 8000+x, 'name') for x in range(3)]
    started = [0]
    for p in projects:
      def dummy_start():
        started[0] += 1
      p.start = dummy_start
    d = launcher.DeployController(None, None, projects)
    d._authname = 'fred'
    d._password = '******'
    d._TextFrameForProject = (lambda x: x)
    d._TaskThreadForProject = (lambda x: x)
    self.assertTrue(d._DoDeploy())
    self.assertEqual(3, len(d._text_frames))
    self.assertEqual(3, len(d._task_threads))
    for p in projects:
      self.assertEqual(3, started[0])

    # We're already setup for testing, so while we're here,
    # let's test _TaskDidStop and DisplayProjectOutput
    didit = [False]
    def append_text(line):
      didit[0] = True
    projects[0].AppendText = append_text
    d._TaskDidStop(projects[0])  # appends one last line of text
    self.assertTrue(didit[0])
    self.assertEqual(2, len(d._text_frames))
    self.assertEqual(2, len(d._task_threads))
Ejemplo n.º 19
0
 def testParseFlags(self):
     project = launcher.Project('path', 9000)
     sc = launcher.SettingsController(project)
     flagtests = {
         '': [],
         '\n\n\n\n\n\n--keyboard': ['--keyboard'],
         '-d': ['-d'],
         '--debug': ['--debug'],
         '-f --foo': ['-f', '--foo'],
         '--foo -f': ['--foo', '-f'],
         '  --zoo\n--path=hi mom  -d --fred=hi mom --zoo':
         ['--zoo', '--path=hi mom', '-d', '--fred=hi mom', '--zoo']
     }
     for key in flagtests:
         flaglist = sc._ParseFlags(key)
         self.assertEqual(flagtests[key], flaglist)
Ejemplo n.º 20
0
    def testPort(self):
        """Make sure we can't set the port while running."""
        p1 = launcher.Project('/tmp/foo', 8000)
        self.assertEqual(8000, p1.port)
        p1.port = 102
        self.assertEqual(102, p1.port)
        p1.runstate = launcher.Project.STATE_RUN

        def setPort():
            p1.port = 8000

        self.assertRaises(launcher.ProjectException, setPort)
        self.assertEqual(102, p1.port)
        p1.runstate = launcher.Project.STATE_STOP
        p1.port = 8001
        self.assertEqual(8001, p1.port)
Ejemplo n.º 21
0
 def testSetThenGet(self):
   platform = FakePlatform('pythoncmd', 'dir')
   pref = launcher.Preferences(self.filename, platform)
   runtime = RuntimeNoDialog(platform, pref)
   self.assertFalse(runtime.problem)
   project = launcher.Project('super-path', '123', False)
   das = runtime.DevAppServerCommand(project, verify=False)
   self.assertTrue('pythoncmd' in das)
   self.assertTrue('photojournalist' not in das)
   pref[launcher.Preferences.PREF_PYTHON] = 'photojournalist'
   das = runtime.DevAppServerCommand(project, verify=False)
   self.assertTrue('pythoncmd' not in das)
   self.assertTrue('photojournalist' in das)
   self.assertRaises(launcher.RuntimeException,
                     runtime.DevAppServerCommand,
                     project)
Ejemplo n.º 22
0
    def testEquality(self):
        p1 = launcher.Project('/tmp/foo', 8000)
        p2 = launcher.Project('/tmp/foo', 8001)
        p3 = launcher.Project('/windindicfnodsin', 8000)
        p4 = launcher.Project('/tmp/foo', 8000)

        self.assertEqual(p1, p4)  # same path and port
        self.assertNotEqual(p1, p2)  # differ by port
        self.assertNotEqual(p1, p3)  # differ by path
        self.assertNotEqual(p2, p3)  # differ by path and port
        # make sure both __eq__ and __ne__ hit; no guarantee with unittest
        self.assertTrue(p1 == p4)
        self.assertTrue(p1 != p3)
        # Make sure we test with "projects" that exist on disk
        for dir in ('/bin', 'c:\\'):
            self.assertEqual(launcher.Project(dir, 8010),
                             launcher.Project(dir, 8010))
            self.assertNotEqual(launcher.Project(dir, 8010),
                                launcher.Project(dir, 8011))
Ejemplo n.º 23
0
 def testProjects(self):
     table = launcher.MainTable(self._temp_filename)
     projects = []
     for i in range(20):
         projects.append(launcher.Project('/tmp/himom' + str(i), 8000 + i))
     # test Add/Remove
     for p in projects:
         table.AddProject(p)
         self.assertEqual(p, table.ProjectAtIndex(0))
         table.RemoveProject(p)
     # Test big table and extraction
     for p in projects:
         table.AddProject(p)
     self.assertEqual(projects[19], table.ProjectAtIndex(19))
     self.assertEqual(projects[12], table.ProjectAtIndex(12))
     self.assertTrue(table.ProjectCount() >= 20)
     # Test indexing off the end, which should return None
     self.assertEqual(None, table.ProjectAtIndex(2817372))
 def testAdd(self):
     """Tests both Add() and AddNew()."""
     for attr in ('Add', 'AddNew'):
         p = launcher.Project('/tmp/himom', 8123)
         # Avoid UI with a NoAskController
         controller = NoAskController(self.app, p)
         # Mock table to confirm AddProject() gets called
         table_mock = mox.MockObject(launcher.MainTable)
         table_mock.AddProject(p)
         table_mock._projects = None
         mox.Replay(table_mock)
         controller.SetModelsViews(table=table_mock)
         # UI should be noop, and table.AddProject() should be called in here
         getattr(controller, attr)(None)
         mox.Verify(table_mock)
     # Make sure the path makes it to the controller.
     c = NoAskController(self.app, None)
     c.Add(None, '/Path/To/Oblivion')
     self.assertEqual('/Path/To/Oblivion', c._path)
Ejemplo n.º 25
0
 def testTaskThreadForProject(self):
   project = launcher.Project('path', 8000, 'project_name')
   d = launcher.DeployController(launcher.Runtime(), launcher.Preferences(),
                                 [project])
   d._name = 'fred'
   d._password = '******'
   tt = d._TaskThreadForProject(project)
   self.assertFalse(tt.isAlive())
   # confirm stdin works.  Use python so we don't need cygwin.
   # Print out the 'Running application' string so that
   # taskthread will know to transition from WillStart to DidStart.
   script = ('import sys; print "Running application http://x:5"; '
             'print sys.stdin.read().strip()')
   cat_cmd = [sys.executable, '-c', script]
   tt = d._TaskThreadForProject(project, cat_cmd)
   output = ['']
   def collect(line, date=True):
     output[0] += line
   tt.LogOutput = collect
   starting = [0]
   started = [0]
   lock = threading.Lock()
   def _TaskWillStart():
     starting[0] = time.time()
   def _TaskDidStart():
     started[0] = time.time()
   def _TaskDidStop(code):
     lock.release()
   tt._TaskWillStart = _TaskWillStart
   tt._TaskDidStart = _TaskDidStart
   tt._TaskDidStop = _TaskDidStop
   lock.acquire()
   tt.start()
   lock.acquire()  # blocks until _TaskDidStop() releases it
   lock.release()
   self.assertNotEqual(0, starting[0])
   self.assertNotEqual(0, started[0])
   # Make sure the 'started' happens after 'starting'
   self.assertTrue(started > starting)
   self.assertTrue('himom' in output[0])
Ejemplo n.º 26
0
  def testNoDefaultsAllPrefsOverride(self):
    """None for ALL defaults, all pref overrides, and make sure all is happy."""
    pref = launcher.Preferences(self.filename, FakePlatform(None, None))
    pycmd = '/usr/bin/python'
    pref[launcher.Preferences.PREF_PYTHON] = pycmd
    pref[launcher.Preferences.PREF_APPENGINE] = '/tmp/foo/bar/baz'
    runtime = RuntimeNoDialog(preferences=pref)
    self.assertFalse(runtime.problem)
    project = launcher.Project('super-path', '123')

    # test of DevAppServerCommand()
    das = runtime.DevAppServerCommand(project, verify=False)
    self.assertTrue(pycmd in das)
    self.assertTrue('super-path' in das)
    self.assertTrue('--port=123' in das)
    self.assertFalse('--mega-flag' in das)
    self.assertRaises(launcher.RuntimeException,
                      runtime.DevAppServerCommand,
                      project, verify=True)

    # test project flags
    project.flags = ['--mega-flag', '--oops']
    das = runtime.DevAppServerCommand(project, verify=False)
    self.assertTrue('--mega-flag' in das)
    self.assertTrue('--oops' in das)

    # test DevAppServerCommand's extra_flags
    extras = ['--hammertime', '--singsong']
    for flag in extras:
      self.assertFalse(flag in das)
    das = runtime.DevAppServerCommand(project, extra_flags=extras, verify=False)
    for flag in extras:
      self.assertTrue(flag in das)

    # test of DeployCommand()
    deploy_cmd = runtime.DeployCommand(project, '*****@*****.**')
    for s in (pycmd, '[email protected]', 'update', 'super-path'):
      self.assertTrue(s in deploy_cmd)
    deploy_cmd = runtime.DeployCommand(project, '*****@*****.**', 'xazzy')
    self.assertTrue('--server=xazzy' in deploy_cmd)
Ejemplo n.º 27
0
    def InstallDemoByName(self, path, dest_dir=None, prompt=True):
        """Called by a demo sub-menu item.

    Copies the specified demo and adds to the current project list.

    Args:
      path: A full path to the demo we want to use.
      dest_dir: The destination directory for the demo to be copied, or
        None to use a default.
      prompt: Solicit the user before copying the demo files.
        Exists for unit tests to avoid a modal dialog.
    """
        # Find a destination path; ensure it is unique.
        dest_dir = dest_dir or wx.StandardPaths.Get().GetDocumentsDir()
        basename = os.path.basename(path)
        existing_files = os.listdir(dest_dir)
        count = 1
        newname = basename
        while newname in existing_files:
            newname = '%s-%d' % (basename, count)
            count += 1
        newpath = os.path.join(dest_dir, newname)

        if prompt:
            # Ask the user before doing anything.
            caption = 'Install Google App Engine demo?'
            message = (
                'Google App Engine Launcher wishes to copy the demo "%s" '
                'to %s' % (basename, newpath))
            allow_copy_dialog = wx.MessageDialog(
                None, message, caption, wx.OK | wx.CANCEL | wx.ICON_QUESTION)
            if allow_copy_dialog.ShowModal() != wx.ID_OK:
                return

        # Copy over, create a project, and add it to our table.
        shutil.copytree(path, newpath)
        project = launcher.Project(newpath, self._table.UniquePort())
        self._table.AddProject(project)
        self.RefreshMainView()
    def Project(self):
        """Return a project created from interaction with this dialog.

    Returns:
      a launcher.Project, or None.
    Side effect:
      Actually creates the project on disk from the template files.
    """
        if self._dialog_return_value != wx.ID_OK:
            return None
        path = self.GetPath()  # parent directory of project
        port = self.GetPort()
        name = self.GetName()
        if not (self._SanityCheckPort(port)
                and self._SanityCheckPath(path, check_contents=False)):
            return None
        newpath = os.path.join(path, name)
        if not self._SanityCheckPathDoesNotExist(newpath):
            return None
        if not self._CreateProjectOnDisk(newpath, name):
            return None
        return launcher.Project(newpath, port)
Ejemplo n.º 29
0
    def testFileSaving(self):
        # Make a temp file, and have the table save its projects there.
        table = launcher.MainTable(self._temp_filename)

        project = launcher.Project('/hurdy/gurdy/bonnie', 1910)
        table.AddProject(project)

        project = launcher.Project('/Users/bork/kim', 1975)
        table.AddProject(project)

        project = launcher.Project('/annie', 1860)
        table.AddProject(project)

        # Make sure paths with spaces are OK.
        project = launcher.Project('/ekky/ek ky/ekky/ek ky', 1967)
        table.AddProject(project)

        # It's valid to have multiple projects with the same name.
        project = launcher.Project('/little/orphan/annie', 1924)
        table.AddProject(project)

        # And for there to be duplicates.
        project = launcher.Project('/little/orphan/annie', 1924)
        table.AddProject(project)

        # Make another table, pointed at that file, and make sure everything
        # comes back that should.

        table2 = launcher.MainTable(self._temp_filename)
        # Reach in and get the projects array and make sure it has the
        # expected projects in the correct order.
        self.assertEqual(6, table.ProjectCount())

        self.checkProject(table.ProjectAtIndex(0), '/hurdy/gurdy/bonnie',
                          'bonnie', 1910)
        self.checkProject(table.ProjectAtIndex(1), '/Users/bork/kim', 'kim',
                          1975)
        self.checkProject(table.ProjectAtIndex(2), '/annie', 'annie', 1860)
        self.checkProject(table.ProjectAtIndex(3), '/ekky/ek ky/ekky/ek ky',
                          'ek ky', 1967)
        self.checkProject(table.ProjectAtIndex(4), '/little/orphan/annie',
                          'annie', 1924)
        self.checkProject(table.ProjectAtIndex(5), '/little/orphan/annie',
                          'annie', 1924)
Ejemplo n.º 30
0
 def testCloseHandler(self):
   """Test our close handler (if not force, hide window and save for later)"""
   project = launcher.Project('path', 8000, 'name')
   lc = launcher.LogConsole(project)
   self.did_hide = False
   self.did_destroy = False
   orig_show = lc.Show
   orig_destroy = lc.Destroy
   # Override some methods so we can track behavior
   lc.Show = self.ConfirmedShow
   lc.Destroy = self.ConfirmedDestroy
   # Call our wx.EVT_CLOSE handler; CAN be veto'ed
   lc.Close(force=False)
   self.assertTrue(self.did_hide)
   self.assertFalse(self.did_destroy)
   self.did_hide = False
   self.did_destroy = False
   # Call our wx.EVT_CLOSE handler; CANNOT be veto'ed
   lc.Close(force=True)
   self.assertFalse(self.did_hide)
   self.assertTrue(self.did_destroy)
   # Restore original methods
   lc.Show = orig_show
   lc.Destroy = orig_destroy