blob: c8db916114546b17022fcddcd8ccdf68d3e9b2d3 [file] [log] [blame]
#// Copyright (c) 2000-2017 Ericsson Telecom AB //
#// All rights reserved. This program and the accompanying materials are made available under the terms //
#// of the Eclipse Public License v1.0 which accompanies this distribution, and is available at //
#// http://www.eclipse.org/legal/epl-v10.html //
#/////////////////////////////////////////////////////////////////////////////////////////////////////////
import unittest, json, time, os
import Microservices.Playlist
from Microservices.Playlist.ScheduledPlaylist import ScheduledPlaylist
from test.utils.Utils import *
def loadPlaylist(path):
with open(path, 'r') as f:
playlist = json.load(f)
return playlist
class ScheduledPlaylistTest(unittest.TestCase):
def setUp(self):
self.next = 0
self.failed = False
self.reason = ''
def test_requestHandlingWithConditionTrue(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_requestHandlingWithConditionTrue
Tested component: ServiceFramework
Feature: ServiceFramework - ScheduledPlaylist
Requirement: playlist execution
Action_To_Be_taken:
execute the playlist and check expected behaviour
Expected_Result: pass
'''
self.expected = (
(
lambda type, url, credentials: (type, url, credentials['username']),
('LOGIN', 'http://localhost:8000/api.appagent', 'admin'),
None
),
(
lambda type, url, requests: (type, url, requests[0]['getData']['filter']),
('REQUEST', 'http://localhost:8000/api.appagent', {'dataValue': 'false'}),
{'contentList': [{'node': {'val': '1', 'tp': 1}}]}
),
(
lambda type, amount: (type, amount),
('WAIT', 0.2),
None
),
(
lambda type, url, requests: (type, url, requests[0]['setData']['element']),
('REQUEST', 'http://localhost:8000/api.appagent', 'string'),
{'contentList': [{'node': {'val': '1', 'tp': 1}}]}
),
(
lambda type: type,
'LOGOUT',
None
)
)
self.runPlaylist(PLAYLIST_DIR + '/Playlists/admin/simple.json', 'blue')
def test_relativeTo(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_relativeTo
Tested component: ServiceFramework
Feature: ServiceFramework - ScheduledPlaylist
Requirement: playlist execution
Action_To_Be_taken:
execute the playlist and check expected behaviour
Expected_Result: pass
'''
self.expected = (
(
lambda type, url, credentials: (type, url, credentials['username']),
('LOGIN', 'http://localhost:8000/api.appagent', 'admin'),
None
),
(
lambda type, url, requests: (time.sleep(0.1), requests[0]['setData']['content']),
(None, 'new_str1'),
{'contentList': [{'node': {'val': '1', 'tp': 1}}]}
),
(
lambda type, url, requests: (time.sleep(0.1), requests[0]['setData']['content']),
(None, 'new_str2'),
{'contentList': [{'node': {'val': '1', 'tp': 1}}]}
),
(
lambda type, url, requests: (time.sleep(0.1), requests[0]['setData']['content']),
(None, 'new_str3'),
{'contentList': [{'node': {'val': '1', 'tp': 1}}]}
),
(
lambda type: type,
'LOGOUT',
None
)
)
self.runPlaylist(PLAYLIST_DIR + '/Playlists/admin/relativeto.json', 'blue')
def test_conditionMaxTriesExceeded(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_conditionMaxTriesExceeded
Tested component: ServiceFramework
Feature: ServiceFramework - ScheduledPlaylist
Requirement: playlist execution
Action_To_Be_taken:
execute the playlist and check expected behaviour
Expected_Result: pass
'''
self.expected = (
(
lambda type, url, credentials: (type, url, credentials['username']),
('LOGIN', 'http://localhost:8000/api.appagent', 'admin'),
None
),
(
lambda type, url, requests: (type, url, requests[0]['getData']['filter']),
('REQUEST', 'http://localhost:8000/api.appagent', {'dataValue': 'false'}),
{'contentList': [{'node': {'val': '', 'tp': 0}}]}
),
(
lambda type, amount: (type, amount),
('WAIT', 0.1),
None
),
(
lambda type, url, requests: (type, url, requests[0]['getData']['filter']),
('REQUEST', 'http://localhost:8000/api.appagent', {'dataValue': 'false'}),
{'contentList': [{'node': {'val': '', 'tp': 0}}]}
),
(
lambda type, amount: (type, amount),
('WAIT', 0.1),
None
),
(
lambda type, url, requests: (type, url, requests[0]['getData']['filter']),
('REQUEST', 'http://localhost:8000/api.appagent', {'dataValue': 'false'}),
{'contentList': [{'node': {'val': '', 'tp': 0}}]}
),
(
lambda type: type,
'LOGOUT',
None
)
)
self.runPlaylist(PLAYLIST_DIR + '/Playlists/admin/try.json', 'red')
def test_conditionsMaxTimeExceeded(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_conditionsMaxTimeExceeded
Tested component: ServiceFramework
Feature: ServiceFramework - ScheduledPlaylist
Requirement: playlist execution
Action_To_Be_taken:
execute the playlist and check expected behaviour
Expected_Result: pass
'''
self.expected = (
(
lambda type, url, credentials: (type, url, credentials['username']),
('LOGIN', 'http://localhost:8000/api.appagent', 'admin'),
None
),
(
lambda type, url, requests: time.sleep(0.5),
None,
{'contentList': [{'node': {'val': '', 'tp': 0}}]}
),
(
lambda type: type,
'LOGOUT',
None
)
)
self.runPlaylist(PLAYLIST_DIR + '/Playlists/admin/wait.json', 'red')
def test_stop(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_stop
Tested component: ServiceFramework
Feature: ServiceFramework - ScheduledPlaylist
Requirement: playlist execution
Action_To_Be_taken:
execute the playlist and check expected behaviour
Expected_Result: pass
'''
self.expected = (
(
lambda type, url, credentials: (type, url, credentials['username']),
('LOGIN', 'http://localhost:8000/api.appagent', 'admin'),
None
),
(
lambda type, url, requests: self.handler.stop(),
None,
{'contentList': [{'node': {'val': '', 'tp': 0}}]}
),
(
lambda type: type,
'LOGOUT',
None
)
)
self.runPlaylist(PLAYLIST_DIR + '/Playlists/admin/relativeto.json', 'black')
def test_pause(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_pause
Tested component: ServiceFramework
Feature: ServiceFramework - ScheduledPlaylist
Requirement: playlist execution
Action_To_Be_taken:
start the playlist
pause the playlist
check if the playlist was paused
resume the playlist
check if it was resumed
stop the playlist
Expected_Result: pass
'''
# we count the number of 'actions'; when paused, the counter should not change
count = [0] # we can't modify an outer variable directly...
def magicHandler(*args):
count[0] += 1
time.sleep(0.1)
return {'contentList': [{'node': {'val': '', 'tp': 0}}]}
# start the playlist
self.handler = ScheduledPlaylist(loadPlaylist(PLAYLIST_DIR + '/Playlists/admin/longtry.json'))
self.handler._login = magicHandler
self.handler._logout = magicHandler
self.handler._wait = magicHandler
self.handler._sendRequestsToUrl = magicHandler
self.handler.start(ADMIN)
# pause the playlist
time.sleep(0.5)
self.handler.pause()
# check if the playlist was paused
time.sleep(0.2)
currentCount = count[0]
time.sleep(0.5)
self.assertEqual(count[0], currentCount, 'there should be no calls when paused') # there were no additional calls
# resume the playlist
self.handler.pause()
# check if it was resumed
time.sleep(0.5)
self.assertNotEqual(count[0], currentCount, 'there should be calls when unpaused') # there were calls after unpause
# stop the playlist
self.handler.stop()
time.sleep(0.2)
def startPlaylist(self, fileName):
self.handler = ScheduledPlaylist(loadPlaylist(fileName))
self.handler._login = self.mockedLogin
self.handler._logout = self.mockedLogout
self.handler._wait = self.mockedWait
self.handler._sendRequestsToUrl = self.mockedSendRequest
self.handler.start(ADMIN)
def runPlaylist(self, fileName, color, timeout = 1):
self.startPlaylist(fileName)
startTime = time.time()
while self.handler.isRunning():
if time.time() - startTime > timeout:
self.fail('Playlist execution timed out')
time.sleep(0.1)
while color not in self.handler.getStatus()['node']['val']:
if time.time() - startTime > timeout:
self.fail('Playlist status is wrong, expected ' + color + ', got ' + self.handler.getStatus()['node']['val'])
time.sleep(0.1)
if self.failed:
self.fail(self.reason)
def handle(self, *args):
time.sleep(0.1) # this is needed to imitate non-blocking behaviour (this is the only way we can check the status led color reliably)
if self.next >= len(self.expected):
self.failed = True
self.reason = 'Too few expected values: ' + str(len(self.expected))
return None
if len(self.expected[self.next]) < 3:
self.failed = True
self.reason = 'Not all 3 arguments present, only got: ' + str(len(self.expected[self.next]))
return None
transformer, expected, returnValue = self.expected[self.next]
self.next += 1
try:
self.assertEqual(transformer(*args), expected)
except Exception as e:
self.failed = True
self.reason = e
return returnValue
def mockedLogin(self, opener, url, userCredentials):
return self.handle('LOGIN', url, userCredentials)
def mockedLogout(self):
return self.handle('LOGOUT')
def mockedWait(self, amount):
return self.handle('WAIT', amount)
def mockedSendRequest(self, opener, url, requests):
return self.handle('REQUEST', url, requests)
class PlaylistTest(unittest.TestCase):
def magicHandler(self, *args):
# a function that mocks parts of the ScheduledPlaylist
time.sleep(0.1)
return {'contentList': [{'node': {'val': '', 'tp': 0}}]}
def createPlaylistExecutor(self, descriptor):
# create a mocked ScheduledPlaylist
executor = ScheduledPlaylist(descriptor)
executor._login = self.magicHandler
executor._logout = self.magicHandler
executor._wait = self.magicHandler
executor._sendRequestsToUrl = self.magicHandler
return executor
def setUp(self):
# the "microservice" under test
self.handler = Microservices.Playlist.createHandler(PLAYLIST_DIR)
# the datasource handlers of the microservice
self.datasourceHandlers = self.handler.getDataSourceHandlers()
# mock the creation of ScheduledPlaylist
self.handler._createPlaylistExecutor = self.createPlaylistExecutor
# a list of created files to delete at the end
self.created = []
def tearDown(self):
# close tested "microservice"
self.handler.close()
# delete the created files
for fileName in self.created:
if os.path.exists(fileName):
os.unlink(fileName)
def test_playlistHandling(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_playlistHandling
Tested component: ServiceFramework
Feature: ServiceFramework - Playlist
Requirement: playlist microservice request handling
Action_To_Be_taken:
start a playlist
check elements of a running and an idle playlist
pause the running playlist
check status led
resume playlist
check status led
stop playlist
check status led
Expected_Result: pass
'''
# start a playlist
self.set('Start', '0', 1, 'admin/longtry')
time.sleep(0.2)
# check elements of a running and an idle playlist
self.check('0', 'Start', 'admin/longtry')
self.check('0', 'Start', 'admin/try')
self.check('0', 'Stop', 'admin/longtry')
self.check('0', 'Stop', 'admin/try')
self.check('0', 'Pause', 'admin/longtry')
self.check('0', 'Pause', 'admin/try')
self.check('0', 'Start', 'admin/longtry')
self.check('0', 'Start', 'admin/try')
self.check('green', 'Status', 'admin/longtry')
self.check('blue', 'Status', 'admin/try')
# pause the running playlist
self.set('Pause', '0', 1, 'admin/longtry')
time.sleep(0.2)
# check status led
self.check('yellow', 'Status', 'admin/longtry')
# resume playlist
self.set('Pause', '0', 1, 'admin/longtry')
time.sleep(0.2)
# check status led
self.check('green', 'Status', 'admin/longtry')
# stop playlist
self.set('Stop', '0', 1, 'admin/longtry')
time.sleep(0.2)
# check status led
self.check('black', 'Status', 'admin/longtry')
def test_playlistFileHandling(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_playlistFileHandling
Tested component: ServiceFramework
Feature: ServiceFramework - Playlist
Requirement: playlist microservice file handling
Action_To_Be_taken:
create a playlist
check if it was created
check if the descriptor is the same as the one that was saved
delete the playlist
check that it no longer exists
Expected_Result: pass
'''
# create a playlist
self.created.append(PLAYLIST_DIR + '/Playlists/admin/test.json')
self.set('Descriptor', '[]', 4, 'admin/test')
# check if it was created
self.assertIn('admin/test', self.makeList(self.get('Playlists')))
# check if the descriptor is the same as the one that was saved
self.check('[]', 'Descriptor', 'admin/test')
# delete the playlist
self.set('Delete', '1', 1, 'admin/test')
# check that it no longer exists
self.assertNotIn('admin/test', self.makeList(self.get('Playlists')))
def test_microService(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_microService
Tested component: ServiceFramework
Feature: ServiceFramework - Playlist
Requirement: playlist behaviour as a microservice
Action_To_Be_taken:
invoke the request handler with a simple request and check the result
Expected_Result: pass
'''
response = getEmptyResponse()
self.handler.handleMessage('POST', 'api.playlist', {}, '''{
"requests": [
{
"getData": {
"source": "Playlist",
"element": "Playlists"
}
}
]
}''', ADMIN, response)
playlists = self.makeList(json.loads(response['body'])['contentList'][0])
self.assertIn('admin/longtry', playlists)
def test_help(self):
'''
Author: EDNIGBO Daniel Gobor
Testcase: test_help
Tested component: ServiceFramework
Feature: ServiceFramework - Playlist
Requirement: datasource help in Playlist
Action_To_Be_taken:
get help
check help syntax
Expected_Result: pass
'''
# get help
help = self.get('help')['node']['val']
# check help syntax
json.loads(help.decode('hex'))
def makeList(self, response):
return [element['node']['val'] for element in response['list']]
def check(self, expected, element, playlist = None, user = ADMIN):
response = self.get(element, playlist, user)
self.assertIn(expected, response['node']['val'])
def get(self, element, playlist = None, user = ADMIN):
request = {
'source': self.handler.SOURCE_ID,
'element': element,
'params': []
}
if playlist is not None:
request['params'].append({
'paramName': 'Playlist',
'paramValue': playlist
})
return self.datasourceHandlers[self.handler.SOURCE_ID]['getDataHandler'](request, user)
def set(self, element, content, tp, playlist = None, user = ADMIN):
request = {
'source': self.handler.SOURCE_ID,
'element': element,
'params': [],
'tp': tp,
'content': content
}
if playlist is not None:
request['params'].append({
'paramName': 'Playlist',
'paramValue': playlist
})
return self.datasourceHandlers[self.handler.SOURCE_ID]['setDataHandler'](request, user)