1# -*-coding:utf-8 -* 2 3# Copyright (c) 2011-2015, Intel Corporation 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without modification, 7# are permitted provided that the following conditions are met: 8# 9# 1. Redistributions of source code must retain the above copyright notice, this 10# list of conditions and the following disclaimer. 11# 12# 2. Redistributions in binary form must reproduce the above copyright notice, 13# this list of conditions and the following disclaimer in the documentation and/or 14# other materials provided with the distribution. 15# 16# 3. Neither the name of the copyright holder nor the names of its contributors 17# may be used to endorse or promote products derived from this software without 18# specific prior written permission. 19# 20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31import os 32import subprocess 33import unittest 34import time 35import socket 36 37class RemoteCli(object): 38 39 def setRemoteProcess(self, remoteProcess): 40 self.remoteProcess = remoteProcess 41 42 def sendCmd(self, cmd, *args, **kwargs): 43 """ Execute a remote-process command and assert its result. 44 @param[in] cmd, *args the command to execute and its arguments 45 @param[in] expectSuccess If True, assert that the command will succeed 46 If False, assert that the command will succeed 47 If None, do not assert result 48 Default to True 49 @return (command stdout, None) None is return for legacy reason 50 """ 51 expectSuccess=kwargs.get("expectSuccess", True) 52 53 assert self.remoteProcess.poll() == None, "Can not send command to Test platform as it has died. Return code: %s" % self.remoteProcess.returncode 54 55 sys_cmd = self.platform_command + [cmd] 56 if args is not None: 57 sys_cmd += args 58 print("CMD : %s" % sys_cmd) 59 60 try: 61 p = subprocess.Popen(sys_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 62 except OSError as error: 63 return None, error.strerror 64 out, err = p.communicate() 65 out = out.rstrip('\r\n') 66 67 if (expectSuccess != None): 68 assert (p.returncode == 0) == expectSuccess, "Unexpected command result:\nexpectedSuccess=%s\nCMD=%s\nreturncode=%s\nstdout=%s\nstderr=%s" % (expectSuccess, sys_cmd, p.returncode, out, err) 69 70 return out, None 71 72class Pfw(RemoteCli): 73 platform_command = ["remote-process", "localhost", "5000"] 74 75class Hal(RemoteCli): 76 # Arbitrary choosen port, try to avoid conflicting with IANA registered ports 77 testPlatformBindAddress = "18444" 78 platform_command = ["remote-process", "localhost", testPlatformBindAddress] 79 80 def __init__(self, pfw): 81 self.pfw = pfw 82 83 # Starts the HAL exe 84 def startHal(self): 85 cmd= ["test-platform", os.environ["PFW_TEST_CONFIGURATION"], self.testPlatformBindAddress] 86 self.setRemoteProcess(subprocess.Popen(cmd)) 87 # Wait for the test-platform listening socket 88 while socket.socket().connect_ex(("localhost", int(self.testPlatformBindAddress))) != 0: 89 assert self.remoteProcess.poll() == None, "Test platform has failed to start. Return code: %s" % self.remoteProcess.returncode 90 time.sleep(0.01) 91 92 # Send command "stop" to the HAL 93 def stopHal(self): 94 try: 95 self.sendCmd("exit") 96 except Exception as exitEx: 97 # Kill test-platform as cooperative exit failed 98 try: 99 self.remoteProcess.terminate() 100 except Exception as killEx: 101 raise Exception("Fail to terminate after a exit request failed", exitEx, killEx) 102 raise 103 else: 104 # exit request accepted, wait for server to stop 105 returncode = self.remoteProcess.wait() 106 assert returncode == 0, "test-platform did not stop succesfully: %s" % returncode 107 108 def createInclusiveCriterion(self, name, nb): 109 self.sendCmd("createInclusiveSelectionCriterion", name, nb) 110 111 def createExclusiveCriterion(self, name, nb): 112 self.sendCmd("createExclusiveSelectionCriterion", name, nb) 113 114 # Starts the Pfw 115 def start(self): 116 self.sendCmd("setSchemaUri", os.environ["PFW_SCHEMAS"]) 117 self.sendCmd("setValidateSchemasOnStart", "true") 118 self.sendCmd("start") 119 self.pfw.setRemoteProcess(self.remoteProcess) 120 121# A PfwTestCase gather tests performed on one instance of the PFW. 122class PfwTestCase(unittest.TestCase): 123 124 pfw = Pfw() 125 hal = Hal(pfw) 126 127 @classmethod 128 def setUpClass(cls): 129 cls.startHal() 130 131 @classmethod 132 def tearDownClass(cls): 133 cls.stopHal() 134 135 @classmethod 136 def startHal(cls): 137 # set up the Hal & pfw 138 cls.hal.startHal() 139 try: 140 # create criterions 141 cls.hal.createInclusiveCriterion("Crit_0", "2") 142 cls.hal.createExclusiveCriterion("Crit_1", "2") 143 # start the Pfw 144 cls.hal.start() 145 except Exception as startE: 146 # Leave the hal stopped in case of start failure 147 try: 148 cls.stopHal() 149 except Exception as stopE: 150 raise Exception("Fail to stop after a failed start: ", startE, stopE) 151 raise 152 153 @classmethod 154 def stopHal(cls): 155 cls.hal.stopHal() 156