PageRenderTime 33ms CodeModel.GetById 18ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/appengine_django/tests/commands_test.py

http://google-app-engine-django.googlecode.com/
Python | 186 lines | 110 code | 14 blank | 62 comment | 12 complexity | e40e8287f7a61e04d9d18e5a6a9c747f MD5 | raw file
  1#!/usr/bin/python2.4
  2#
  3# Copyright 2008 Google Inc.
  4#
  5# Licensed under the Apache License, Version 2.0 (the "License");
  6# you may not use this file except in compliance with the License.
  7# You may obtain a copy of the License at
  8#
  9#     http://www.apache.org/licenses/LICENSE-2.0
 10#
 11# Unless required by applicable law or agreed to in writing, software
 12# distributed under the License is distributed on an "AS IS" BASIS,
 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14# See the License for the specific language governing permissions and
 15# limitations under the License.
 16
 17"""
 18Tests that the manage.py commands execute correctly.
 19
 20These tests only verify that the commands execute and exit with a success code.
 21They are intended to catch import exceptions and similar problems, it is left
 22up to tests in other modules to verify that the functionality of each command
 23works correctly.
 24"""
 25
 26
 27import os
 28import re
 29import signal
 30import subprocess
 31import tempfile
 32import time
 33import unittest
 34import sys
 35
 36from django.db.models import get_models
 37
 38from google.appengine.ext import db
 39from appengine_django.models import BaseModel
 40from appengine_django.models import ModelManager
 41from appengine_django.models import ModelOptions
 42from appengine_django.models import RegistrationTestModel
 43
 44
 45class CommandsTest(unittest.TestCase):
 46  """Unit tests for the manage.py commands."""
 47
 48  # How many seconds to wait for a command to exit.
 49  COMMAND_TIMEOUT = 10
 50
 51  def runCommand(self, command, args=None, int_after=None, input=None):
 52    """Helper to run the specified command in a child process.
 53
 54    Args:
 55      command: The name of the command to run.
 56      args: List of command arguments to run the command with.
 57      int_after: If set to a positive integer, SIGINT will be sent to the
 58        running child process after this many seconds to cause an exit. This
 59        should be less than the COMMAND_TIMEOUT value (10 seconds).
 60      input: A string to write to stdin when the command starts. stdin is
 61        closed after the string is written.
 62
 63    Returns:
 64      rc: The integer return code of the process.
 65      output: A string containing the childs output.
 66    """
 67    if not args:
 68      args = []
 69    start = time.time()
 70    int_sent = False
 71    fd = subprocess.PIPE
 72
 73    child = subprocess.Popen([sys.executable, "manage.py", command] + args,
 74                             stdin=fd, stdout=fd, stderr=fd, cwd=os.getcwdu())
 75    if input:
 76      child.stdin.write(input)
 77      child.stdin.close()
 78
 79    while 1:
 80      rc = child.poll()
 81      if rc is not None:
 82        # Child has exited.
 83        break
 84      elapsed = time.time() - start
 85      if int_after and int_after > 0 and elapsed > int_after and not int_sent:
 86        # Sent SIGINT as requested, give child time to exit cleanly.
 87        os.kill(child.pid, signal.SIGINT)
 88        start = time.time()
 89        int_sent = True
 90        continue
 91      if elapsed < self.COMMAND_TIMEOUT:
 92        continue
 93      # Command is over time, kill and exit loop.
 94      os.kill(child.pid, signal.SIGKILL)
 95      time.sleep(2)  # Give time for the signal to be received.
 96      break
 97
 98    # Return status and output.
 99    return rc, child.stdout.read(), child.stderr.read()
100
101  def assertCommandSucceeds(self, command, *args, **kwargs):
102    """Asserts that the specified command successfully completes.
103
104    Args:
105      command: The name of the command to run.
106      All other arguments are passed directly through to the runCommand
107      routine.
108
109    Raises:
110      This function does not return anything but will raise assertion errors if
111      the command does not exit successfully.
112    """
113    rc, stdout, stderr = self.runCommand(command, *args, **kwargs)
114    fd, tempname = tempfile.mkstemp()
115    os.write(fd, stdout)
116    os.close(fd)
117    self.assertEquals(0, rc,
118                      "%s did not return successfully (rc: %d): Output in %s" %
119                      (command, rc, tempname))
120    os.unlink(tempname)
121
122  def getCommands(self):
123    """Returns a list of valid commands for manage.py.
124
125    Args:
126      None
127
128    Returns:
129      A list of valid commands for manage.py as read from manage.py's help
130      output.
131    """
132    rc, stdout, stderr = self.runCommand("help")
133    parts = re.split("Available subcommands:", stderr)
134    if len(parts) < 2:
135      return []
136
137    return [t.strip() for t in parts[-1].split("\n") if t.strip()]
138
139  def testDiffSettings(self):
140    """Tests the diffsettings command."""
141    self.assertCommandSucceeds("diffsettings")
142
143  def testDumpData(self):
144    """Tests the dumpdata command."""
145    self.assertCommandSucceeds("dumpdata")
146
147  def testFlush(self):
148    """Tests the flush command."""
149    self.assertCommandSucceeds("flush")
150
151  def testLoadData(self):
152    """Tests the loaddata command."""
153    self.assertCommandSucceeds("loaddata")
154
155  def testLoadData(self):
156    """Tests the loaddata command."""
157    self.assertCommandSucceeds("loaddata")
158
159  def testReset(self):
160    """Tests the reste command."""
161    self.assertCommandSucceeds("reset", ["appengine_django"])
162
163  # Disabled due to flakiness - re-enable when it can be guaranteed to succeed
164  # reliably.
165  #def testRunserver(self):
166  #  """Tests the runserver command."""
167  #  self.assertCommandSucceeds("runserver", int_after=2.0)
168
169  def testShell(self):
170    """Tests the shell command."""
171    self.assertCommandSucceeds("shell", input="exit")
172
173  def testUpdate(self):
174    """Tests that the update command exists.
175
176    Cannot test that it works without mocking out parts of dev_appserver so for
177    now we just assume that if it is present it will work.
178    """
179    cmd_list = self.getCommands()
180    self.assert_("update" in cmd_list)
181
182  def testZipCommandListFiltersCorrectly(self):
183    """When running under a zipfile test that only valid commands are found."""
184    cmd_list = self.getCommands()
185    self.assert_("__init__" not in cmd_list)
186    self.assert_("base" not in cmd_list)