Something

by Jack

Load testing SITS e:Vision

Load testing is really useful in been able to gauge a variety of things from how much resource you may ned through to determining how you manage processes that impact on load.

Load testing SITS can be a real pain in the balls.

Load testing e:Vision or IPP can be done by using multiple users, or multiple simultaneous browsers sessions (or tabs), but due to the security set up of the web, each login session must use a unique Master user access (MUA) record.

Due to the way HTTP web requests work it is possible to script multiple users accessing e:Vision or IPP simultaneously to perform automated load testing. However, again, each “scripted session” must use a unique Master user access (MUA) record. Commercial or open source tools can be used for this.

Due to the nature of the security requirements of e:Vision it can be time consuming to script each and every page to pull out the links and post back. It can also make changing scripts slightly difficult, as you often have to re-record the entire script.

To get around this two new logicals have been introduced LOAD_TESTING_MODE and LOAD_TESTING_IP. These turn off some of the encryption that takes place (it still happens in the background, so performance is identical) when generating a page. This allows for easier scripting of load tests. They will be in SITS 8.8.0 and might even be back ported.

When enabled it allows the passing of a single NKEY throughout all web links, and decrypts the &PARAMS on generated links.

For example:

<a href="siw_portal.url?1C4CB442795A41294MxgX2Jiljf_Tx8xQOrpGnY03TATcq3dM99hx3TjUa5Vg20ZpE369dOy7KHeQXzqKhWUi1LaCZCpDq7gQyzR_wxgX2Jiljf_Tx8xQOrpGn" id="JACK" title="Jack CPG">Jack's Testing Page</a>

Becomes something like:

<a href="siw_portal.url?EB7315D67B7F4E3BVSw5i2ChxWP2_nyNhYHddm0zqCY4YqvzeR6PVKK03RMU4wEAynoGJtPkDXZ9I8ofJgCFDTlhYdvCA2b7lukO_bE&PARAMS=INFRA" id="JACK" title="Jack CPG">Jack's Testing Page</a>

The bit to spot is &PARAMS=INFRA appended to the end. This is the PARAMS been passed into the running program (in this case siw_portal.url).

This allows for the PARAMS to be modified in the script, rather than having to parse a web page to find an exact link. The encrypted string is the NKEY – this is a unique ID that is created in the system, and under normal load will change with each page load and contain the parameters encrypted.

In load testing mode we can use the same NKEY and can pass parameters through in plain text. The NKEY needs to be grabbed from a page. Typically you would do this on the login redirection page (siw_lgn_red) or during IPP on the screen after account creation.

Tips

Make sure you monitor servers during your load tests, so you can view the machines performance.

Scripting will take longer than you think.

Load testing is an iterative process and a series of bottlenecks will be found, and slowly removed these might include:

  • Poorly written SRL’s
  • Incorrect use of functionality
  • Blank retrieves
  • Missing indexes on the data base
  • Poorly optimised OS on a virtual infrastructure
  • Poor performing SAN
  • Over committed virtual infrastructure
  • Poorly performing network
  • Non optimised Apache and Tomcat

Please allow several weeks to iterate over load tests, typically starting with a handful of users and working up. Be prepared to call on area specialists from across the business. Always set firm requirements and outcomes, and ensure that expectations are realistic.

Warning

Don’t enable LOAD_TESTING_MODE on a production system, and always lock down the IP range to those addresses where the load will be generated from.

New logicals

LOAD_TESTING_MODE This logical allows load testing mode. A single nkey could be used across the system as the form check does not occur. In this mode parameters can be added to the link in the format &PARAMS=. Gold characters should be entered as their URL % equivalents.

LOAD_TESTING_IP This logical restricts the effect of the LOAD_TESTING_MODE to listed IP addresses. Browser_ID checking must be on.

Example 1 - Login

Funkload is a python based load testing tool that can record scripts and generate high loads. I used Funkload to login to the application and click on a link.

import unittest
from funkload.FunkLoadTestCase import FunkLoadTestCase
from funkload.utils import extract_token

class Login(FunkLoadTestCase):
	"""XXX

	This test use a configuration file Login.conf.
	"""

	def setUp(self):
		"""Setting up test."""
		self.logd("setUp")
		self.server_url = self.conf_get('main', 'url')


	def test_login(self):
		# The description should be set in the configuration file
		server_url = self.server_url
		# details
		# in a real test script you would load a user from a list of users here
		# in a real test script you would load the users password here
		email = 'testtest@test.com'
		password = 'password'
		# begin of test ---------------------------------------------
		
		self.get(server_url + '/urd/sits.urd/run/SIW_LGN', description="Get base url")
		# here we extract the runtime token from the page, to use in the submit
		runtime_token = extract_token(self.getBody(), 'name="RUNTIME.DUMMY.MENSYS.1" value="', '"')
		# the login post
		self.post(server_url + "/urd/sits.urd/run/SIW_LGN", params=[
			['%.DUMMY.MENSYS.1', ''],
			['RUNTIME.DUMMY.MENSYS.1', runtime_token],
			['MUA_CODE.DUMMY.MENSYS.1', email],
			['PASSWORD.DUMMY.MENSYS.1', password],
			['BP101.DUMMY_B.MENSYS.1', 'Login >>']],
			description="Post login details")
		# redirect page
		self.assert_('automatically redirected to the portal' in self.getBody(), "no redirect page")
		# extract the nkey for use throughout the rest of this session
		nkey_token = extract_token(self.getBody(), 'siw_portal.url?', '&PARAMS')
		# mimic auto-redirection/clicking on the click here link
		self.get(server_url + "/urd/sits.urd/run/siw_portal.url?" + nkey_token + "&PARAMS=%23",
			description="Click redirect link")
		self.assert_('Applicant Home' in self.getBody(), "couldn't load home page")

		# mimic the call to fetch in-tray messages
		self.post(server_url + "/urd/sits.urd/run/siw_intray.getintray", params=[
			['NKEY', nkey_token],
			['PARAMS', 'MHV_CODE=ALL-APP'],
			['MHV_CODE', 'ALL-APP'],
			['SWITCH', 'N'],
			['LIMIT', '10'],
			['ORDER', ''],
			['PAGE', '']],
			description="Post /urd/sits.urd/run/siw_intray.getintray")
		self.assert_('Actions for you to complete' in self.getBody(), "couldn't load message list")
		# extract the intray link we want to use, we can't be certain what the parameters will be here
		intray_message_link = extract_token(self.getBody(), '<a href="../run/SIW_MCC_MHD.start_url?', '">Actions for you to complete</a>')
		self.get(server_url + "/urd/sits.urd/run/SIW_MCC_MHD.start_url?" + intray_message_link,
			description="Get messsage")
		self.assert_('Please review the following Clearance Check' in self.getBody(), "could not load intray message")

		

		# end of test -----------------------------------------------

	def tearDown(self):
		"""Setting up test."""
		self.logd("tearDown.\n")


if __name__ in ('main', '__main__'):
	unittest.main()

Example – IPP Application

This script is unlikely to work unless you have IPP configured identically, however it can be used as a guideline/template.

import unittest
from funkload.FunkLoadTestCase import FunkLoadTestCase
from webunit.utility import Upload
from funkload.utils import Data
from funkload.Lipsum import Lipsum
from funkload.utils import extract_token
from funkload.utils import xmlrpc_get_credential
from funkload.utils import xmlrpc_get_seq
import socket
import time

class Apply(FunkLoadTestCase):
	"""XXX

	This test use a configuration file BasicNavigation.conf.
	"""

	def setUp(self):
		"""Setting up test."""
		self.logd("setUp")
		self.server_url = self.conf_get('main', 'url')
		self.credential_host = self.conf_get('credential', 'host')
		self.credential_port = self.conf_getInt('credential', 'port')
		socket.setdefaulttimeout(60)

	def test_apply_maths(self):
		# The description should be set in the configuration file
		server_url = self.server_url
		# details
		seq = xmlrpc_get_seq(self.credential_host, self.credential_port)
		email = str(seq) + 'test19q@test.com'
		first_name = Lipsum().getWord()
		surname = Lipsum().getWord()
		# begin of test ---------------------------------------------

		# /tmp/tmpgNMXmc_funkload/watch0003.request
		self.get(server_url,
			description="Get base url")

		time.sleep(2)		
		# /tmp/tmpgNMXmc_funkload/watch0009.request
		self.get(server_url + "/urd/sits.urd/run/siw_ipp_lgn.login?process=siw_ipp_app_crs",
			description="Get /urd/sits.urd/run/siw_ipp_lgn.login")
		time.sleep(4)
		# /tmp/tmpgNMXmc_funkload/watch0010.request
		runtime_token = extract_token(self.getBody(), 'name="RUNTIME.DUMMY.MENSYS.1" value="', '"')
		self.post(server_url + "/urd/sits.urd/run/SIW_IPP_LGN", params=[
			['PROCESS.DUMMY.MENSYS.1', 'siw_ipp_app_crs'],
			['IPP_CODE.DUMMY.MENSYS.1', ''],
			['IPO_SEQN.DUMMY.MENSYS.1', ''],
			['RUN_MODE.DUMMY.MENSYS.1', ''],
			['RUNTIME.DUMMY.MENSYS.1', runtime_token],
			['ENQ_LOGIN.DUMMY.MENSYS.1', ''],
			['%.DUMMY.MENSYS.1', ''],
			['MUA_CODE.DUMMY.MENSYS.1', ''],
			['PASSWORD.DUMMY.MENSYS.1', ''],
			['NEW_USER.DUMMY.MENSYS.1', 'Create Account'],
			['%.DUMMY_B.MENSYS.1', '']],
			description="Post /urd/sits.urd/run/SIW_IPP_LGN")
		self.assert_('New User Details' in self.getBody(), "No New User Details")
		time.sleep(5)
		# /tmp/tmpgNMXmc_funkload/watch0011.request
		session_token = extract_token(self.getBody(), 'name="SESSION.DUMMY.MENSYS.1" value="', '"')
		runmode_token =	 extract_token(self.getBody(), 'name="RUN_MODE.DUMMY.MENSYS.1" value="', '"')
		self.post(server_url + "/urd/sits.urd/run/SIW_IPP_NEW", params=[
			['NKEY.DUMMY.MENSYS.1', ''],
			['PROCESS.DUMMY.MENSYS.1', 'siw_ipp_app_crs'],
			['IPP_CODE.DUMMY.MENSYS.1', ''],
			['IPO_SEQN.DUMMY.MENSYS.1', ''],
			['SESSION.DUMMY.MENSYS.1', session_token],
			['BACK.DUMMY.MENSYS.1', ''],
			['SOURCE.DUMMY.MENSYS.1', ''],
			['RUN_MODE.DUMMY.MENSYS.1', runmode_token],
			['EXISTING_MST.DUMMY.MENSYS.1', ''],
			['EXISTING_USERNAME.DUMMY.MENSYS.1', ''],
			['HID_USR.DUMMY.MENSYS.1', 'N'],
			['HID_PWD.DUMMY.MENSYS.1', 'N'],
			['%.DUMMY.MENSYS.1', ''],
			['TITLE.IPU.SRS.1', 'MR'],
			['IPU_FNM1.IPU.SRS.1', first_name],
			['IPU_SURN.IPU.SRS.1', surname],
			['IPU_GEND.IPU.SRS.1', 'M'],
			['IPU_DOB.IPU.SRS.1', '24/03/1982'],
			['USERCODE.IPU.SRS.1', email],
			['IPU_HAEM.IPU.SRS.1', email],
			['PASSWORD1.IPU.SRS.1', 'password'],
			['PASSWORD2.IPU.SRS.1', 'password'],
			['PROCEED.DUM1.SRS.1', 'Proceed'],
			['%.DUM1.SRS.1', ''],
			['#.IPU.SRS.1', '']],
			description="Post /urd/sits.urd/run/SIW_IPP_NEW")
		self.assert_('Please select a Program Type and Department' in self.getBody(), "Can't create an account. Email used:" + email)
		# /tmp/tmpgNMXmc_funkload/watch0015.request
		# these might be jscript requests
		nkey_token = extract_token(self.getBody(), 'name="NKEY.DUMMY.MENSYS.1" value="', '"')
		self.post(server_url + "/urd/sits.urd/run/SIW_IPP_CRSR.ajax", params=[
			['nkey', nkey_token],
			['mode', 'LIVE'],
			['vers', '870.2'],
			['KeyWords', ''],
			['Types', 'MA'],
			['School', 'DEM-BL01'],
			['ModeStudy', 'PT,FT,DL']],
			description="Post /urd/sits.urd/run/SIW_IPP_CRSR.ajax")
		self.assert_('{"results":{"DEM-BL01-PRG2"' in self.getBody(), "Can't get details")
		# /tmp/tmpgNMXmc_funkload/watch0016.request
		# this gets the date selection page
		time.sleep(5)
		self.get(server_url + "/urd/sits.urd/run/SIW_IPP_CRSO.start_url?" + nkey_token + "&PARAMS=IPP_CODE%3DDEM-BL01-PRG1%15%1Bprocess%3Dsiw_ipp_app_crs%15%1Bipo_seqn%3D%15%1B%24OPERATION_MODE%24%3DSTART%15%1Bcourse_type%3DMA%15%1Bschool_of_study%3DDEM-BL01%15%1Bkeyword%3D%15%1Bmode_of_study%3DPT%17FT%17DL",
			description="Get /urd/sits.urd/run/SIW_IPP_CRSO.start_url")
		self.assert_('When would you like to start your program?' in self.getBody(), "Can't program start details")
		# /tmp/tmpgNMXmc_funkload/watch0017.request
		# this is selecting date of course to apply to
		time.sleep(4)
		ipo_token = extract_token(self.getBody(), '#.IPO.SRS.1" value="', '"')
		crc_token = extract_token(self.getBody(), '#CRC.IPO.SRS.1" value="', '"')
		self.post(server_url + "/urd/sits.urd/run/SIW_IPP_CRSO", params=[
			['NKEY.DUMMY.MENSYS.1', nkey_token + '\x1bPARAMS=IPP_CODE=DEM-BL01-PRG1\\!\x1bprocess=siw_ipp_app_crs\\!\x1bipo_seqn=\\!\x1b$OPERATION_MODE$=START\\!\x1bcourse_type=MA\\!\x1bschool_of_study=DEM-BL01\\!\x1bkeyword=\\!\x1bmode_of_study=PT\\|FT\\|DL'],
			['RUN_MODE.DUMMY.MENSYS.1', 'URL'],
			['PROCESS.DUMMY.MENSYS.1', 'siw_ipp_app_crs'],
			['IPP_CODE.DUMMY.MENSYS.1', 'DEM-BL01-PRG1'],
			['SOURCE.DUMMY.MENSYS.1', ''],
			['IPO_SEQN.DUMMY.MENSYS.1', ''],
			['IPR_SEQN.DUMMY.MENSYS.1', ''],
			['SEARCHMODE.DUMMY.MENSYS.1', 'PT\\|FT\\|DL'],
			['SEARCHKEY.DUMMY.MENSYS.1', ''],
			['SEARCHTYPE.DUMMY.MENSYS.1', 'MA'],
			['SEARCHDEPT.DUMMY.MENSYS.1', 'DEM-BL01'],
			['%.DUMMY.MENSYS.1', ''],
			['AYR_NAME.AYR.SRS.1', '2014'],
			['MOA_NAME.MOA.SRS.1', 'Full time'],
			['IPO_BEGD.IPO.SRS.1', 'September 2014'],
			['IPO_ENDD.IPO.SRS.1', 'July 2015'],
			['APPLY.IPO.SRS.1', 'Apply'],
			['#.IPO.SRS.1', ipo_token],
			['#CRC.IPO.SRS.1', crc_token]],
			description="Post /urd/sits.urd/run/SIW_IPP_CRSO")
		self.assert_('My Details' in self.getBody(), "Can't show details")
		# /tmp/tmpgNMXmc_funkload/watch0018.request
		time.sleep(5)
		ipu_srs_token = extract_token(self.getBody(), '#.IPU.SRS.1" value="', '"')
		crc_ipu_srs_token = extract_token(self.getBody(), '#CRC.IPU.SRS.1" value="', '"')
		session_token = extract_token(self.getBody(), 'name="SESSION.DUMMY.MENSYS.1" value="', '"')
		runmode_token =	 extract_token(self.getBody(), 'name="RUN_MODE.DUMMY.MENSYS.1" value="', '"')
		self.post(server_url + "/urd/sits.urd/run/SIW_IPP_USR", params=[
			['NKEY.DUMMY.MENSYS.1', nkey_token + '&PARAMS=OPERATION_MODE%3DSTART%15%1B%24OPERATION_MODE%24%3DSTART%15%1Bprocess%3Dsiw_ipp_app_crs%15%1Bipp_code%3DDEM-BL01-PRG1%15%1Bipo_seqn%3D0001%15%1Bipr_seqn%3D'],
			['CNKEY.DUMMY.MENSYS.1', ''],
			['PROCESS.DUMMY.MENSYS.1', 'siw_ipp_app_crs'],
			['IPP_CODE.DUMMY.MENSYS.1', 'DEM-BL01-PRG1'],
			['SOURCE.DUMMY.MENSYS.1', ''],
			['SESSION.DUMMY.MENSYS.1', session_token],
			['IPO_SEQN.DUMMY.MENSYS.1', '0001'],
			['IPR_SEQN.DUMMY.MENSYS.1', ''],
			['RUN_MODE.DUMMY.MENSYS.1', runmode_token],
			['%.DUMMY.MENSYS.1', ''],
			['%.DUMMY_B.MENSYS.1', ''],
			['PROCEED.DUM3.SRS.1', 'Proceed'],
			['%.DUM3.SRS.1', ''],
			['ALIAS.MUA.MENSYS.1', email.upper()],
			['IPU_TITL.IPU.SRS.1', 'MR'],
			['IPU_FNM1.IPU.SRS.1', first_name.upper()],
			['IPU_SURN.IPU.SRS.1', surname.upper()],
			['GENDER.IPU.SRS.1', 'Male'],
			['IPU_DOB.IPU.SRS.1', '24/Mar/1982'],
			['IPU_HAEM.IPU.SRS.1', email],
			['#.IPU.SRS.1', ipu_srs_token],
			['#CRC.IPU.SRS.1', crc_ipu_srs_token],
			['%.DUMMY_B.MENSYS.1', '']],
			description="Post /urd/sits.urd/run/SIW_IPP_USR")
		self.assert_('Specialization' in self.getBody(), "Can't show details")
		# /tmp/tmpgNMXmc_funkload/watch0019.request
		#time.sleep(4)
		ipucode_token = extract_token(self.getBody(), 'ipu_code" value="', '"')
		iprseqn_token = extract_token(self.getBody(), 'ipr_seqn" value="', '"')
		self.post(server_url + "/urd/sits.urd/run/siw_ipp_cgi.start?", params=[
			['NKEY', nkey_token + '&PARAMS=OPERATION_MODE%3DSTART%15%1B%24OPERATION_MODE%24%3DSTART%15%1Bprocess%3DHIDEsiw_ipp_app_crs%15%1Bipp_code%3DDEM-BL01-PRG1%15%1Bipo_seqn%3D0001%15%1Bipr_seqn%3D' + iprseqn_token],
			['ipp_code', 'DEM-BL01-PRG1'],
			['ipo_seqn', '0001'],
			['ipu_code', ipucode_token],
			['ipr_seqn', iprseqn_token],
			['sits_page', 'GR_APP_1'],
			['sits_page_on', 'GR_APP_0'],
			['sits_process', 'NEXT'],
			['ipa_type', 'HTML'],
			['process', 'siw_ipp_app_crs'],
			['doc_action', ''],
			['show_cgi_error', 'Y'],
			['IPQ_GR_SPECIAL', 'GEN~SPZ01'],
			['IPQ_GR_PRG', 'GEN'],
			['IPQ_GR_ROU', 'SPZ01']],
			description="Post /urd/sits.urd/run/siw_ipp_cgi.start")
		self.assert_('Personal details' in self.getBody(), "Can't show personal details confirmation")
		#print(self.getBody())
		# /tmp/tmpgNMXmc_funkload/watch0020.request
		time.sleep(5)
		self.post(server_url + "/urd/sits.urd/run/siw_ipp_cgi.start?", params=[
			['NKEY', nkey_token + '&PARAMS=OPERATION_MODE%3DSTART%15%1B%24OPERATION_MODE%24%3DSTART%15%1Bprocess%3DHIDEsiw_ipp_app_crs%15%1Bipp_code%3DDEM-BL01-PRG1%15%1Bipo_seqn%3D0001%15%1Bipr_seqn%3D' + iprseqn_token],
			['ipp_code', 'DEM-BL01-PRG1'],
			['ipo_seqn', '0001'],
			['ipu_code', ipucode_token],
			['ipr_seqn', iprseqn_token],
			['sits_page', 'GR_APP_2'],
			['sits_page_on', 'GR_APP_1'],
			['sits_process', 'NEXT'],
			['ipa_type', 'HTML'],
			['process', 'siw_ipp_app_crs'],
			['doc_action', ''],
			['show_cgi_error', 'Y'],
			['IPR_TITL', 'MR'],
			['IPR_FNM1', first_name.upper()],
			['IPR_FNM2', ''],
			['IPR_FNM3', ''],
			['IPR_SURN', surname.upper()],
			['IPQ_TTPRVS', ''],
			['IPR_GEND', 'M'],
			['IPR_DOB', '24/Mar/1982'],
			['IPR_HAPC', 'HU13 0PD'],
			['IPR_HAD1', 'Address 1'],
			['IPR_HAD2', 'Address 2'],
			['IPR_HAD3', ''],
			['IPR_HAD4', ''],
			['IPR_HAD5', ''],
			['IPR_CODC', '839'],
			['IPR_HTEL', ''],
			['IPR_HAEM', email],
			['IPQ_HOMECOPY', 'N'],
			['IPR_CAPC', ''],
			['IPR_CAD1', ''],
			['IPR_CAD2', ''],
			['IPR_CAD3', ''],
			['IPR_CAD4', ''],
			['IPR_CAD5', ''],
			['IPR_COD2', ''],
			['IPR_CAT1', ''],
			['IPR_CAEM', ''],
			['IPR_UDF5', 'C'],
			['IPQ_TT_LANG', 'ENGLISH'],
			['IPQ_TT_NATC', ''],
			['IPQ_TT_DOA', '']],
			description="Post /urd/sits.urd/run/siw_ipp_cgi.start")
		self.assert_('Education History' in self.getBody(), "Can't show Education selection details")
		#print(self.getBody())
		# /tmp/tmpgNMXmc_funkload/watch0022.request
		time.sleep(13)
		self.post(server_url + "/urd/sits.urd/run/siw_ipp_cgi.start?", params=[
			['NKEY', nkey_token + '&PARAMS=OPERATION_MODE%3DSTART%15%1B%24OPERATION_MODE%24%3DSTART%15%1Bprocess%3DHIDEsiw_ipp_app_crs%15%1Bipp_code%3DDEM-BL01-PRG1%15%1Bipo_seqn%3D0001%15%1Bipr_seqn%3D' + iprseqn_token],
			['ipp_code', 'DEM-BL01-PRG1'],
			['ipo_seqn', '0001'],
			['ipu_code', ipucode_token],
			['ipr_seqn', iprseqn_token],
			['sits_page', 'GR_APP_3'],
			['sits_page_on', 'GR_APP_1'],
			['sits_process', 'NEXT'],
			['ipa_type', 'HTML'],
			['process', 'siw_ipp_app_crs'],
			['doc_action', ''],
			['show_cgi_error', 'Y'],
			['IPQ_TOTALQUALS', '1'],
			['IPQ_TOTALWORKS', '1'],
			['IPQ_TT_EDH_INS1', 'CN102'],
			['IPQ_GR_EDH_PRG1', 'French Chicken Preperation'],
			['IPQ_TT_EDH_INS2', 'IR101'],
			['IPQ_GR_EDH_PRG2', 'International Relations'],
			['IPQ_GR_QESU_1', 'Ecology in the Modern Suburb'],
			['IPQ_GR_QMOD_1', 'ONLINEAPP'],
			['IPQ_GR_QCRD_1', '100'],
			['IPQ_GR_QGPA_1', '4'],
			['IPQ_GR_QAYR_1', '2012/3'],
			['IPQ_GR_QESU_2', ''],
			['IPQ_GR_QMOD_2', ''],
			['IPQ_GR_QCRD_2', ''],
			['IPQ_GR_QGPA_2', ''],
			['IPQ_GR_QAYR_2', ''],
			['IPQ_GR_QESU_3', ''],
			['IPQ_GR_QMOD_3', ''],
			['IPQ_GR_QCRD_3', ''],
			['IPQ_GR_QGPA_3', ''],
			['IPQ_GR_QAYR_3', ''],
			['IPQ_GR_QESU_4', ''],
			['IPQ_GR_QMOD_4', ''],
			['IPQ_GR_QCRD_4', ''],
			['IPQ_GR_QGPA_4', ''],
			['IPQ_GR_QAYR_4', ''],
			['IPQ_GR_QESU_5', ''],
			['IPQ_GR_QMOD_5', ''],
			['IPQ_GR_QCRD_5', ''],
			['IPQ_GR_QGPA_5', ''],
			['IPQ_GR_QAYR_5', ''],
			['IPQ_GR_QESU_6', ''],
			['IPQ_GR_QMOD_6', ''],
			['IPQ_GR_QCRD_6', ''],
			['IPQ_GR_QGPA_6', ''],
			['IPQ_GR_QAYR_6', ''],
			['IPQ_GR_QESU_7', ''],
			['IPQ_GR_QMOD_7', ''],
			['IPQ_GR_QCRD_7', ''],
			['IPQ_GR_QGPA_7', ''],
			['IPQ_GR_QAYR_7', ''],
			['IPQ_GR_QESU_8', ''],
			['IPQ_GR_QMOD_8', ''],
			['IPQ_GR_QCRD_8', ''],
			['IPQ_GR_QGPA_8', ''],
			['IPQ_GR_QAYR_8', ''],
			['IPQ_GR_QESU_9', ''],
			['IPQ_GR_QMOD_9', ''],
			['IPQ_GR_QCRD_9', ''],
			['IPQ_GR_QGPA_9', ''],
			['IPQ_GR_QAYR_9', ''],
			['IPQ_GR_QESU_10', ''],
			['IPQ_GR_QMOD_10', ''],
			['IPQ_GR_QCRD_10', ''],
			['IPQ_GR_QGPA_10', ''],
			['IPQ_GR_QAYR_10', ''],
			['IPQ_GR_QESU_11', ''],
			['IPQ_GR_QMOD_11', ''],
			['IPQ_GR_QCRD_11', ''],
			['IPQ_GR_QGPA_11', ''],
			['IPQ_GR_QAYR_11', ''],
			['IPQ_GR_QESU_12', ''],
			['IPQ_GR_QMOD_12', ''],
			['IPQ_GR_QCRD_12', ''],
			['IPQ_GR_QGPA_12', ''],
			['IPQ_GR_QAYR_12', ''],
			['IPQ_GR_QESU_13', ''],
			['IPQ_GR_QMOD_13', ''],
			['IPQ_GR_QCRD_13', ''],
			['IPQ_GR_QGPA_13', ''],
			['IPQ_GR_QAYR_13', ''],
			['IPQ_GR_QESU_14', ''],
			['IPQ_GR_QMOD_14', ''],
			['IPQ_GR_QCRD_14', ''],
			['IPQ_GR_QGPA_14', ''],
			['IPQ_GR_QAYR_14', ''],
			['IPQ_GR_QESU_15', ''],
			['IPQ_GR_QMOD_15', ''],
			['IPQ_GR_QCRD_15', ''],
			['IPQ_GR_QGPA_15', ''],
			['IPQ_GR_QAYR_15', ''],
			['IPQ_TT_WNAM_1', ''],
			['IPQ_TT_WNAT_1', ''],
			['IPQ_TT_WSTA_1', ''],
			['IPQ_TT_WEND_1', ''],
			['IPQ_TT_WNAM_2', ''],
			['IPQ_TT_WNAT_2', ''],
			['IPQ_TT_WSTA_2', ''],
			['IPQ_TT_WEND_2', ''],
			['IPQ_TT_WNAM_3', ''],
			['IPQ_TT_WNAT_3', ''],
			['IPQ_TT_WSTA_3', ''],
			['IPQ_TT_WEND_3', '']],
			description="Post /urd/sits.urd/run/siw_ipp_cgi.start")
		self.assert_('Personal Statement' in self.getBody(), "Can't show personal statement entry")
		# /tmp/tmpgNMXmc_funkload/watch0028.request
		time.sleep(6)
		self.post(server_url + "/urd/sits.urd/run/siw_ipp_cgi.start?", params=[
			['NKEY', nkey_token + '&PARAMS=OPERATION_MODE%3DSTART%15%1B%24OPERATION_MODE%24%3DSTART%15%1Bprocess%3DHIDEsiw_ipp_app_crs%15%1Bipp_code%3DDEM-BL01-PRG1%15%1Bipo_seqn%3D0001%15%1Bipr_seqn%3D' + iprseqn_token],
			['ipp_code', 'DEM-BL01-PRG1'],
			['ipo_seqn', '0001'],
			['ipu_code', ipucode_token],
			['ipr_seqn', iprseqn_token],
			['sits_page', 'GR_APP_4'],
			['sits_page_on', 'GR_APP_3'],
			['sits_process', 'NEXT'],
			['ipa_type', 'HTML'],
			['process', 'siw_ipp_app_crs'],
			['doc_action', ''],
			['show_cgi_error', 'Y'],
			['IPQ_TTPS', Lipsum().getMessage()],
			['IPQ_REF_FN1', 'Ches'],
			['IPQ_REF_SN1', 'Hawks'],
			['IPQ_REF_RL1', 'Idol'],
			['IPQ_REF_EM1', 'ches.hawkes@example.com'],
			['IPQ_REF_FN2', ''],
			['IPQ_REF_SN2', ''],
			['IPQ_REF_RL2', ''],
			['IPQ_REF_EM2', '']],
			description="Post /urd/sits.urd/run/siw_ipp_cgi.start")
		self.assert_('Supporting Documentation' in self.getBody(), "Can't show supporting documentation")
		#print(self.getBody())
		# /tmp/tmpgNMXmc_funkload/watch0030.request
		time.sleep(4)
		self.post(server_url + "/urd/sits.urd/run/siw_ipp_cgi.start?", params=[
			['NKEY', nkey_token + '&PARAMS=OPERATION_MODE%3DSTART%15%1B%24OPERATION_MODE%24%3DSTART%15%1Bprocess%3DHIDEsiw_ipp_app_crs%15%1Bipp_code%3DDEM-BL01-PRG1%15%1Bipo_seqn%3D0001%15%1Bipr_seqn%3D' + iprseqn_token],
			['ipp_code', 'DEM-BL01-PRG1'],
			['ipo_seqn', '0001'],
			['ipu_code', ipucode_token],
			['ipr_seqn', iprseqn_token],
			['sits_page', 'END'],
			['sits_page_on', 'GR_APP_4'],
			['sits_process', 'SUBMIT'],
			['ipa_type', 'HTML'],
			['process', 'siw_ipp_app_crs'],
			['doc_action', ''],
			['show_cgi_error', 'Y']],
			description="Post /urd/sits.urd/run/siw_ipp_cgi.start")
		self.assert_('Application submitted' in self.getBody(), "Can't show successful submission")
		#print(self.getBody())
		# Now we log back into the application to view our status/message
		time.sleep(2)
		self.get(server_url + '/urd/sits.urd/run/SIW_LGN', description="Get base url")
		runtime_token = extract_token(self.getBody(), 'name="RUNTIME.DUMMY.MENSYS.1" value="', '"')
		#print(self.getBody())
		#print('runtime:'+ runtime_token)
		self.post(server_url + "/urd/sits.urd/run/SIW_LGN", params=[
			['%.DUMMY.MENSYS.1', ''],
			['RUNTIME.DUMMY.MENSYS.1', runtime_token],
			['MUA_CODE.DUMMY.MENSYS.1', email],
			['PASSWORD.DUMMY.MENSYS.1', 'password'],
			['BP101.DUMMY_B.MENSYS.1', 'Login >>']],
			description="Post login details")
		# redirect page
		self.assert_('automatically redirected to the portal' in self.getBody(), "no redirect page")
		nkey_token = extract_token(self.getBody(), 'siw_portal.url?', '&PARAMS')
		self.get(server_url + "/urd/sits.urd/run/siw_portal.url?" + nkey_token + "&PARAMS=%23",
			description="Click redirect link")
		self.assert_('Applicant Home' in self.getBody(), "couldn't load home page")

		# /tmp/tmpvOP5VB_funkload/watch0013.request
		self.post(server_url + "/urd/sits.urd/run/siw_intray.getintray", params=[
			['NKEY', nkey_token],
			['PARAMS', 'MHV_CODE=ALL-APP'],
			['MHV_CODE', 'ALL-APP'],
			['SWITCH', 'N'],
			['LIMIT', '10'],
			['ORDER', ''],
			['PAGE', '']],
			description="Get intray content")

		self.assert_('Actions for you to complete' in self.getBody(), "couldn't load message list")
		#print(self.getBody())
		# /tmp/tmpvOP5VB_funkload/watch0017.request
		time.sleep(3)
		#self.get(server_url + "/urd/sits.urd/run/SIW_MCC_MHD.start_url?" + nkey_token + "&PARAMS=14000040_76559227%15%1B14000040_76559227%15%1B14000040_76559226%15%1B14000040_76559225%15%1B%24ordr%24%3DALL-APP%15%1BSWITCH%3DN%15%1BLINK%3D",
		intray_message_link = extract_token(self.getBody(), '<a href="../run/SIW_MCC_MHD.start_url?', '">Actions for you to complete</a>')
		self.get(server_url + "/urd/sits.urd/run/SIW_MCC_MHD.start_url?" + intray_message_link,
			description="Get messsage")
		self.assert_('Please review the following Clearance Check' in self.getBody(), "could not load intray message")

		

		# end of test -----------------------------------------------

	def tearDown(self):
		"""Setting up test."""
		self.logd("tearDown.\n")



if __name__ in ('main', '__main__'):
	unittest.main()
#