#!/usr/bin/env python3.2 ###################################################################### # Copyright (c)2013, Cisco Systems, Inc. # # test/P4OO/Client.py # # See COPYRIGHT AND LICENSE section below for usage # and distribution rights. # ###################################################################### #NAME / DESCRIPTION ''' unittest test suite for P4OO.Client ''' ###################################################################### # Includes # import os # used for managing environment variables import sys # used her for include path mgmt sys.path.append('.') sys.path.append('../lib') # P4OO._Base brings in our Exception hierarchy import P4OO._Base import unittest # _P4GoldenEgg is used for our test environment setup and destruction import tempfile import _P4GoldenEgg # We use dependency injection with P4 for our tests import P4 # We might just need these yo import P4OO.Client ###################################################################### # Configuration # p4d = "/export/disk2/tools/perforce-v10.2/bin.linux26x86_64/p4d" testEgg = "./_P4GoldenEggs/Client.tar.gz" tmpDir = "./tmp" p4PythonObj = None p4Port = None p4RootDir = None ###################################################################### # Class Initialization # class TestP4OO_Client(unittest.TestCase): def test_construction(self): testObj1 = P4OO.Client.P4OOClient() self.assertTrue(isinstance(testObj1, P4OO._P4Python.P4OOClient)) self.assertTrue(isinstance(testObj1, P4OO._SpecObji._P4OOSpecObj)) #p4c1 = P4OOChange(p4PythonObj=p4PythonObj) def test_connectDisconnect(self): # test connection using our global p4PythonObj testObj1 = P4OO._P4Python._P4OOP4Python(p4PythonObj=p4PythonObj) testP4PythonObj = testObj1._connect() self.assertEqual(testP4PythonObj, p4PythonObj, 'not getting back p4 connection injected dependency') self.assertEqual(testObj1._disconnect(), True, '_disconnect() should always return True') # Since we injected the connection, it should still be connected. self.assertEqual(testP4PythonObj.connected(), True, 'dependency injected p4python object should not be disconnected') # Should still return True, even if disconnected self.assertEqual(testObj1._disconnect(), True, '_disconnect() should always return True') # Now use the same global P4PORT but have the test object instantiate a new connection os.environ['P4PORT'] = p4Port testP4PythonObj = testObj1._connect() # should be equivalent, but distinct connection objects self.assertNotEqual(testP4PythonObj, p4PythonObj, 'not getting back new p4 connection object after disconnect') self.assertEqual(testObj1._disconnect(), True, '_disconnect() should always return True') # Since the connection object was "owned" by the test object, it should be disconnected now too. self.assertEqual(testP4PythonObj.connected(), False, 'owned p4python object should be disconnected') def test_destructor(self): # Basically testing disconnect # test destruction using our global p4PythonObj testObj1 = P4OO._P4Python._P4OOP4Python(p4PythonObj=p4PythonObj) testObj1 = None # Since we injected the connection, it should still be connected. self.assertEqual(p4PythonObj.connected(), True, 'dependency injected p4python object should not be disconnected at destruction') # Now use the same global P4PORT but have the test object instantiate a new connection os.environ['P4PORT'] = p4Port testObj1 = P4OO._P4Python._P4OOP4Python(p4PythonObj=p4PythonObj) testP4PythonObj = testObj1._connect() testObj1 = None # Since we injected the connection, it should still be connected. self.assertEqual(testP4PythonObj.connected(), True, 'owned p4python object should be disconnected at destruction') def test__initialize(self): self.assertEqual(P4OO._P4Python._P4OOP4Python._P4PYTHON_COMMAND_TRANSLATION, None, '_P4PYTHON_COMMAND_TRANSLATION should be "None" before _initialize()') testObj1 = P4OO._P4Python._P4OOP4Python(p4PythonObj=p4PythonObj) self.assertEqual(testObj1._initialize(), True, '_initialize() should always return True') # We won't check the content, we don't care as long as comamnds work self.assertIsInstance(P4OO._P4Python._P4OOP4Python._P4PYTHON_COMMAND_TRANSLATION, dict, '_P4PYTHON_COMMAND_TRANSLATION should be dict after _initialize()') def test__execCmd(self): testObj1 = P4OO._P4Python._P4OOP4Python(p4PythonObj=p4PythonObj) # test with 0 args p4Out = testObj1._execCmd("info") self.assertIsInstance(p4Out, list, '_execCmd("info" didn\'t return list') self.assertEqual(len(p4Out), 1, '_execCmd("info" didn\'t return list length 1') self.assertIsInstance(p4Out[0], dict, '"info" p4Out[0] should be a dict') global p4RootDir self.assertEqual(p4Out[0]['serverRoot'], p4RootDir, 'info["serverRoot"] should be our test environment: ' + p4RootDir) # test with multiple args for default spec values p4Out = testObj1._execCmd("user", "-o", "testuser") self.assertIsInstance(p4Out[0], dict, '"user -o testuser" p4Out[0] should be a dict') # test with last arg empty... P4Python doesn't like this normally p4Out = testObj1._execCmd("user", "-o", "testuser", "") self.assertIsInstance(p4Out[0], dict, '"user -o testuser \'\'" p4Out[0] should be a dict') # test with multiple args for spec that won't and will not have defaults def exceptCallable(*args, **kwargs): testObj1._execCmd("change", "-o", 99999) self.assertRaises(P4.P4Exception, exceptCallable, '"change -o 99999" should raise P4.P4Exception') # test p4Port override on connected object # P4.P4Exception: Can't change port once you've connected. def exceptCallable(*args, **kwargs): testObj1._execCmd("info", port=p4Port) self.assertRaises(P4.P4Exception, exceptCallable, '_execCmd overriding P4PORT on connected object should raise P4.P4Exception') # test p4Port override on new/unconnected object p4Out = testObj1._execCmd("user", "-o", user="testUser") self.assertEqual(p4Out[0]["User"], "testUser", '_execCmd overriding P4USER for "user -o" should return overridden userid') def test__parseOutput(self): testObj1 = P4OO._P4Python._P4OOP4Python(p4PythonObj=p4PythonObj) # test user spec parsing p4Out = testObj1._execCmd("users") # print(p4Out) parsedOutput = testObj1._parseOutput("users", p4Out) # print(parsedOutput) def test_runCommand(self): pass #TODO readSpec and saveSpec are pretty important. Modularity says test them here somehow ###################################################################### # Test Environment Initialization and Clean up # def initializeTests(): # sanitize P4 environment variables for p4Var in ('P4CONFIG', 'P4PORT', 'P4USER', 'P4CLIENT'): if p4Var in os.environ: del(os.environ[p4Var]) global tmpDir, testEgg, p4RootDir, p4d, p4PythonObj, p4Port p4RootDir = tempfile.mkdtemp(dir=tmpDir) eggDir = _P4GoldenEgg.eggTarball(testEgg).unpack(p4RootDir) p4Port = eggDir.getP4Port(p4d=p4d) # Connect to the Perforce Service p4PythonObj = P4.P4() p4PythonObj.port = p4Port p4PythonObj.connect() def cleanUpTests(): #TODO... # self.eggDir.destroy() # self._initialized = None pass ###################################################################### # MAIN # if __name__ == '__main__': initializeTests() unittest.main() cleanUpTests() ###################################################################### # Standard authorship and copyright for documentation # # AUTHOR # # David L. Armstrong # # COPYRIGHT AND LICENSE # # Copyright (c)2013, Cisco Systems, Inc. # # This module is distributed under the terms of the Artistic License # 2.0. For more details, see the full text of the license in the file # LICENSE. # # SUPPORT AND WARRANTY # # This program is distributed in the hope that it will be # useful, but it is provided "as is" and without any expressed # or implied warranties. #