<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<!DOCTYPE stax SYSTEM "../stax.dtd">
|
<!--
|
! CDDL HEADER START
|
!
|
! The contents of this file are subject to the terms of the
|
! Common Development and Distribution License, Version 1.0 only
|
! (the "License"). You may not use this file except in compliance
|
! with the License.
|
!
|
! You can obtain a copy of the license at
|
! trunk/opends/resource/legal-notices/OpenDS.LICENSE
|
! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
|
! See the License for the specific language governing permissions
|
! and limitations under the License.
|
!
|
! When distributing Covered Code, include this CDDL HEADER in each
|
! file and include the License file at
|
! trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
|
! add the following below this CDDL HEADER, with the fields enclosed
|
! by brackets "[]" replaced with your own identifying information:
|
! Portions Copyright [yyyy] [name of copyright owner]
|
!
|
! CDDL HEADER END
|
!
|
! Copyright 2007-2009 Sun Microsystems, Inc.
|
! -->
|
<stax>
|
<function name="checkRC">
|
<function-prolog>
|
This function checks a return code against an expected return code
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="returncode" type="required">
|
<function-arg-description>
|
return code received from command
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="result" type="required">
|
<function-arg-description>
|
the output of the result
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="expected" type="optional" default="0">
|
<function-arg-description>
|
the expected return code
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<if expr="expected == 'noCheck'">
|
<return/>
|
</if>
|
<if expr="returncode == expected">
|
<sequence>
|
<if expr="result == ''">
|
<message log="1">
|
'RC=%s, Result=Ok' % (returncode)
|
</message>
|
<else>
|
<message log="1">
|
'RC=%s, Result=%s' % (returncode,result)
|
</message>
|
</else>
|
</if>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'RC=%s, Expected %s, Result=%s' % (returncode,expected,result)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
<return>RC</return>
|
</sequence>
|
</function>
|
|
<function name="checktestRC">
|
<function-prolog>
|
This function checks the return code against an expected return code for a testcase
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="returncode" type="required">
|
<function-arg-description>
|
return code received from command
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="result" type="required">
|
<function-arg-description>
|
the output of the result
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="expected" type="optional" default="0">
|
<function-arg-description>
|
the expected return code
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="issue" type="optional" default="None">
|
<function-arg-description>
|
Issue id. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<if expr="expected == 'noCheck'">
|
<return/>
|
</if>
|
<if expr="returncode == expected">
|
<sequence>
|
<if expr="STAXCurrentTestcase != None">
|
<sequence>
|
<tcstatus result="'pass'"/>
|
</sequence>
|
</if>
|
<if expr="VERBOSE_MODE == 'true'">
|
<message log="1">
|
'SUCCESS: RC=%s, Expected %s, Result=%s' % (returncode,expected,result)
|
</message>
|
<else>
|
<message log="1">
|
'SUCCESS: RC=%s, Expected %s' % (returncode,expected)
|
</message>
|
</else>
|
</if>
|
<script>
|
RC=0
|
</script>
|
</sequence>
|
<else>
|
<sequence>
|
<if expr="STAXCurrentTestcase != None">
|
<sequence>
|
<if expr="issue == None">
|
<tcstatus result="'fail'"/>
|
<else>
|
<sequence>
|
<call function="'setKnownIssue'">
|
{ 'issueId' : issue }
|
</call>
|
</sequence>
|
</else>
|
</if>
|
|
</sequence>
|
</if>
|
<message log="1" level="'Error'">
|
'ERROR : RC=%s, Expected %s, Result=%s' % (returncode,expected,result)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</function>
|
|
<!-- Set Known Issue -->
|
<function name="setKnownIssue">
|
<function-prolog>
|
This function set the known issue flag and maintains list of known issues
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="issueId" type="required">
|
<function-arg-description>
|
Issue ID
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
try:
|
if issueId not in issuesList:
|
issuesList.append(issueId)
|
except:
|
print 'Issues list undefined. Unable to add issue %s' % issueId
|
</script>
|
<message log="1" level="'Error'">
|
'ERROR: HIT **** Known Issue (%s) ****' % issueId
|
</message>
|
<tcstatus result="'fail'">
|
'KnownIssue: %s' % issuesList
|
</tcstatus>
|
</sequence>
|
</function>
|
|
<!-- testPassed -->
|
<!-- Set the test status to PASS -->
|
|
<function name="testPassed">
|
<function-prolog>
|
This function set the status of the tests: PASS
|
</function-prolog>
|
|
<sequence>
|
<message>'Set test status to PASS'</message>
|
<tcstatus result="'pass'"/>
|
</sequence>
|
</function>
|
|
|
<!-- testFailed -->
|
<!-- Set the test status to FAIL -->
|
|
<function name="testFailed">
|
<function-prolog>
|
This function set the status of the tests: FAIL
|
</function-prolog>
|
|
<sequence>
|
<message>'Set test status to FAIL'</message>
|
<tcstatus result="'fail'"/>
|
</sequence>
|
</function>
|
|
<!-- Search string -->
|
<function name="searchString" scope="local">
|
<function-prolog>
|
This function search for a string in the retrun string of a testcase
|
Return 0 if the string is found, 1 otherwise
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="expectedString" type="required">
|
<function-arg-description>
|
the substring expected from the command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="returnString" type="required">
|
<function-arg-description>
|
the return string received from command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="searchType"
|
type="optional"
|
default="'substring'">
|
<function-arg-description>
|
the type of the search: substring, exact-case-insensitive or
|
exact-case-sensitive
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="knownIssue" type="optional" default="None">
|
<function-arg-description>
|
Known issue. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="expectedRC" type="optional" default="0">
|
<function-arg-description>
|
Expected return code value. Default value is 0.
|
Wildcard 'noCheck' to not check the RC
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>
|
searchre = re.compile('%s' % expectedString)
|
myRC = 0
|
myReason = 'None'
|
</script>
|
|
<!-- Check that returnString is really a string -->
|
<if expr='returnString.__class__ is not org.python.core.PyString'>
|
<sequence>
|
<message log="1" level="'Error'">
|
'ERROR : Invalid returnString type (%s), requires org.python.core.PyString.' \
|
% returnString.__class__
|
</message>
|
<script>
|
myRC = 1
|
myReason = 'Python error'
|
</script>
|
|
<return>[myRC, myReason]</return>
|
</sequence>
|
</if>
|
|
<script>
|
if searchType == 'substring':
|
searchResult = (re.search(searchre, returnString) != None)
|
elif searchType == 'exact-case-sensitive':
|
searchResult = (expectedString == returnString)
|
elif searchType == 'exact-case-insensitive':
|
searchResult = (expectedString.lower() == returnString.lower())
|
</script>
|
|
<!-- Search for the expectedString -->
|
<if expr='searchResult'>
|
<sequence>
|
<message log="1">
|
'Search type: %s Found substring, %s, in the return string' \
|
% (searchType, expectedString)
|
</message>
|
<script>
|
myRC = 0
|
myReason = 'String found'
|
</script>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1">
|
'Search type: %s Did not find substring, %s, in the return \
|
string, %s' % (searchType, expectedString, returnString)
|
</message>
|
<script>
|
myRC = 1
|
myReason = 'String not found'
|
</script>
|
</sequence>
|
</else>
|
</if>
|
|
<!-- Manage expectedRC and knownIssue -->
|
<if expr="expectedRC != 'noCheck'">
|
<if expr="myRC == expectedRC">
|
<sequence>
|
<message log="1">
|
'SUCCESS: searchString successful'
|
</message>
|
<tcstatus result="'pass'"/>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'ERROR: searchString fail'
|
</message>
|
<if expr="knownIssue == None">
|
<tcstatus result="'fail'"/>
|
<else>
|
<call function="'setKnownIssue'">
|
{ 'issueId' : knownIssue }
|
</call>
|
</else>
|
</if>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
<return>[myRC, myReason]</return>
|
</sequence>
|
</function>
|
|
<!-- DEPRECATED, use searchString function -->
|
<function name="checktestString">
|
<function-prolog>
|
This function checks the return string against an expected return substring for a testcase
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="expectedString" type="required">
|
<function-arg-description>
|
the substring expected from the command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="returnString" type="required">
|
<function-arg-description>
|
the return string received from command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="issue" type="optional" default="None">
|
<function-arg-description>
|
Known issue. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string" />
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>
|
searchre = re.compile('%s' % expectedString)
|
</script>
|
|
<!-- Check that returnString is really a string -->
|
<if expr='returnString.__class__ is not org.python.core.PyString'>
|
<sequence>
|
<message log="1" level="'Error'">
|
'ERROR : Invalid returnString type (%s), requires org.python.core.PyString.' % returnString.__class__
|
</message>
|
<tcstatus result="'fail'"/>
|
</sequence>
|
</if>
|
<if expr='re.search(searchre, returnString) != None'>
|
<sequence>
|
<tcstatus result="'pass'"/>
|
<message log="1">
|
'SUCCESS : Found substring, %s, in the return string' % (expectedString)
|
</message>
|
</sequence>
|
<else>
|
<sequence>
|
<if expr="issue == None">
|
<tcstatus result="'fail'"/>
|
<else>
|
<sequence>
|
<call function="'setKnownIssue'">
|
{ 'issueId' : issue }
|
</call>
|
</sequence>
|
</else>
|
</if>
|
<message log="1" level="'Error'">
|
'ERROR : Did not find substring, %s, in the return string, %s' % (expectedString, returnString)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</function>
|
|
<!-- DEPRECATED, use searchString function -->
|
<function name="checktestStringNotPresent">
|
<function-prolog>
|
This function checks the return string against an expected return substring that should not be present for a testcase
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="testString" type="required">
|
<function-arg-description>
|
the substring being tested from the command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="returnString" type="required">
|
<function-arg-description>
|
the return string received from command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="issue" type="optional" default="None">
|
<function-arg-description>
|
Known issue. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string" />
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>
|
searchre = re.compile('%s' % testString)
|
</script>
|
<if expr='re.search(searchre, returnString) == None'>
|
<sequence>
|
<tcstatus result="'pass'"/>
|
<message log="1">
|
'Did Not Find substring, %s, in the return string' % (testString)
|
</message>
|
</sequence>
|
<else>
|
<sequence>
|
<if expr="issue == None">
|
<tcstatus result="'fail'"/>
|
<else>
|
<sequence>
|
<call function="'setKnownIssue'">
|
{ 'issueId' : issue }
|
</call>
|
</sequence>
|
</else>
|
</if>
|
<message log="1" level="'Error'">
|
'Found substring, %s, in the return string, %s' % (testString, returnString)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</function>
|
|
<!-- DEPRECATED, use searchString function -->
|
<function name="searchStringForSubstring">
|
<function-prolog>
|
This function simply searches a string for a substring
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="testString" type="required">
|
<function-arg-description>
|
the substring being tested from the command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="returnString" type="required">
|
<function-arg-description>
|
the return string received from command
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="expectedResult" type="optional" default="'2'">
|
<function-arg-description>
|
the expected result, 0 for false (not present), 1 for true (present), 2 for old behavior
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<!-- Until all the test cases are refactored to use the expectedResult param,
|
we need this if-else conditional. -->
|
<sequence>
|
<if expr="expectedResult == '2'">
|
<sequence>
|
<script>
|
searchre = re.compile(testString)
|
</script>
|
<if expr='re.search(searchre, returnString) == None'>
|
<sequence>
|
<script>returnCode='0'</script>
|
<message log="1">
|
'Did Not Find substring, %s, in the return string' % (testString)
|
</message>
|
</sequence>
|
<else>
|
<sequence>
|
<script>returnCode='1'</script>
|
<message log="1">
|
'Found substring, %s, in the return string' % (testString)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
<return>returnCode</return>
|
</sequence>
|
<else>
|
<sequence>
|
<script>
|
searchre = re.compile(testString)
|
</script>
|
<if expr='re.search(searchre, returnString) == None'>
|
<sequence>
|
<script>returnCode='0'</script>
|
<if expr="expectedResult == '0'">
|
<sequence>
|
<tcstatus result="'pass'"/>
|
<message log="1">
|
'SUCCESS : Did Not Find substring, %s, in the return string' % (testString)
|
</message>
|
</sequence>
|
<else>
|
<sequence>
|
<tcstatus result="'fail'"/>
|
<message log="1" level="'Error'">
|
'ERROR : Did Not Find substring, %s, in the return string' % (testString)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
<else>
|
<sequence>
|
<script>returnCode='1'</script>
|
<if expr="expectedResult == '1'">
|
<sequence>
|
<tcstatus result="'pass'"/>
|
<message log="1">
|
'SUCCESS : Found substring, %s, in the return string' % (testString)
|
</message>
|
</sequence>
|
<else>
|
<sequence>
|
<tcstatus result="'fail'"/>
|
<message log="1" level="'Error'">
|
'ERROR : Found substring, %s, in the return string' % (testString)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</else>
|
</if>
|
<return>returnCode</return>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</function>
|
|
<function name="isAlive" scope="local">
|
<function-prolog>
|
Checks that the ldap server is running
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location" type="optional" default="STAF_REMOTE_HOSTNAME">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsPath" type="optional" default="'%s/%s' % (DIRECTORY_INSTANCE_BIN,OPENDSNAME)">
|
<function-arg-description>
|
Pathname to installation root
|
</function-arg-description>
|
<function-arg-property name="type" value="pathname"/>
|
</function-arg-def>
|
<function-arg-def name="noOfLoops" type="required">
|
<function-arg-description>
|
Number of iterations
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="noOfMilliSeconds" type="required">
|
<function-arg-description>
|
Number of seconds to wait between iterations
|
</function-arg-description>
|
<function-arg-property name="type" value="seconds"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstanceHost" type="optional" default="DIRECTORY_INSTANCE_HOST">
|
<function-arg-description>
|
Directory server hostname or IP address
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstancePort" type="optional" default="DIRECTORY_INSTANCE_PORT">
|
<function-arg-description>
|
Directory server port number
|
</function-arg-description>
|
<function-arg-property name="type" value="Port number"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstanceDn" type="optional" default="DIRECTORY_INSTANCE_DN">
|
<function-arg-description>
|
Bind DN
|
</function-arg-description>
|
<function-arg-property name="type" value="DN"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstancePswd" type="optional" default="DIRECTORY_INSTANCE_PSWD">
|
<function-arg-description>
|
Bind password
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<!-- Local variables -->
|
<script>
|
mylocation=location
|
mypath=dsPath
|
myhost=dsInstanceHost
|
myport=dsInstancePort
|
mydn=dsInstanceDn
|
mypswd=dsInstancePswd
|
</script>
|
|
<script>
|
myLoop=0
|
ldapRC=9999
|
</script>
|
<loop from="1" to="noOfLoops" while="ldapRC != 0">
|
<sequence>
|
<script>
|
myLoop=myLoop+1
|
</script>
|
|
<call function="'SearchObject'">
|
{ 'location' : mylocation,
|
'dsPath' : mypath,
|
'dsInstanceHost' : myhost ,
|
'dsInstancePort' : myport ,
|
'dsInstanceDn' : mydn ,
|
'dsInstancePswd' : mypswd ,
|
'dsScope' : 'base' ,
|
'dsBaseDN' : 'cn=config' ,
|
'dsFilter' : 'objectclass=*' ,
|
'attributes' : 'dn',
|
'expectedRC' : 'noCheck'
|
}
|
</call>
|
|
<script>
|
ldapRC=RC
|
</script>
|
|
<message>
|
'LOOP %s => RC=%s' % (myLoop, ldapRC)
|
</message>
|
|
<call function="'Sleep'">
|
{ 'sleepForMilliSeconds' : noOfMilliSeconds }
|
</call>
|
|
</sequence>
|
</loop>
|
|
<call function="'checktestRC'">
|
{ 'returncode' : ldapRC ,
|
'result' : 'Check is alive' }
|
</call>
|
</sequence>
|
</function>
|
|
<function name="isStopped" scope="local">
|
<function-prolog>
|
Checks that the ldap server is stopped
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAF_REMOTE_HOSTNAME">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsPath"
|
type="optional"
|
default="'%s/%s' % (DIRECTORY_INSTANCE_BIN,OPENDSNAME)">
|
<function-arg-description>
|
Pathname to installation root
|
</function-arg-description>
|
<function-arg-property name="type" value="pathname"/>
|
</function-arg-def>
|
<function-arg-def name="noOfLoops"
|
type="optional"
|
default="10">
|
<function-arg-description>
|
Number of iterations
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="noOfMilliSeconds"
|
type="optional"
|
default="2000">
|
<function-arg-description>
|
Number of seconds to wait between iterations
|
</function-arg-description>
|
<function-arg-property name="type" value="seconds"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>checkRC=9999</script>
|
<loop from="1" to="noOfLoops" var="loop" while="checkRC != 48">
|
<sequence>
|
<message>
|
'Check if %s/logs/server.pid still exists on host %s' \
|
% (dsPath,location)
|
</message>
|
|
<call function="'GetEntry'">
|
{ 'location' : location,
|
'entry' : '%s/logs/server.pid' % dsPath,
|
'attribute' : 'TYPE'
|
}
|
</call>
|
|
<script>
|
checkRC = RC
|
</script>
|
|
<message>'LOOP %s => RC %s' % (loop,checkRC)</message>
|
|
<message>'Sleep for %sms' % noOfMilliSeconds</message>
|
<call function="'Sleep'">
|
{ 'sleepForMilliSeconds' : noOfMilliSeconds }
|
</call>
|
</sequence>
|
</loop>
|
|
<if expr="checkRC != 48">
|
<message>
|
'Server is not stopped after %sms \
|
(%s/logs/server.pid still exists on %s)' \
|
% (noOfLoops*noOfMilliSeconds,dsPath,location)
|
</message>
|
</if>
|
</sequence>
|
</function>
|
|
<function name="Sleep">
|
<function-prolog>
|
Sleep for number of milliseconds
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="sleepForMilliSeconds" type="required">
|
<function-arg-description>
|
Number of milliseconds to sleep
|
</function-arg-description>
|
<function-arg-property name="type" value="seconds"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<stafcmd name="'STAF Command: Delay'">
|
<location>STAXServiceMachine</location>
|
<service>'delay'</service>
|
<request>
|
'delay %i' % sleepForMilliSeconds
|
</request>
|
</stafcmd>
|
|
<call function="'checkRC'">
|
{ 'returncode' : RC ,
|
'result' : STAFResult }
|
</call>
|
</sequence>
|
</function>
|
|
<function name="getOSvariables">
|
<function-prolog>
|
Get OS related variables
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="hostname" type="required">
|
<function-arg-description>
|
Name of host on which to retrieve variables
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<stafcmd name="'STAF Command: Get OS Name'">
|
<location>'%s' % hostname</location>
|
<service>'var'</service>
|
<request>
|
'get system var STAF/Config/OS/Name'
|
</request>
|
</stafcmd>
|
<message>
|
'OS Name= %s' % STAFResult
|
</message>
|
<return>STAFResult</return>
|
</sequence>
|
</function>
|
|
<function name="testCase_StartBanner">
|
<function-prolog>
|
Pretty prints a banner at the start of a test.
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
<message level="'start'">'testcase: %s' % STAXCurrentTestcase</message>
|
<message>'****************************************************'</message>
|
<message>'*** STARTING TEST CASE %s.' % STAXCurrentTestcase</message>
|
<message>'***'</message>
|
</sequence>
|
</function>
|
|
<function name="testCase_EndBanner">
|
<function-prolog>
|
Pretty prints a banner at the end of a test.
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
<message>'***'</message>
|
<message>'*** ENDING TEST CASE %s.' % STAXCurrentTestcase</message>
|
<message>'****************************************************'</message>
|
<message level="'stop'">'testcase: %s' % STAXCurrentTestcase</message>
|
</sequence>
|
</function>
|
|
<function name="testCase_Preamble">
|
<function-prolog>
|
Performs all the preoperations for a test case
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
<script>
|
import time
|
testcaseStart=int(time.time())
|
testcaseStartTime=strftime("%Y%m%d@%H:%M:%S",localtime())
|
issuesList=[]
|
for logType in ['errors','access']:
|
if os.path.exists('%s/%s/logs/%s' % (DIRECTORY_INSTANCE_DIR,OPENDSNAME,logType)):
|
logfile=open('%s/%s/logs/%s' % (DIRECTORY_INSTANCE_DIR,OPENDSNAME,logType),'a')
|
logfile.seek(0,2)
|
logfile.write('Begin testcase %s\n' % STAXCurrentTestcase)
|
logfile.close()
|
</script>
|
<call function="'testCase_StartBanner'" />
|
</sequence>
|
</function>
|
|
<function name="testCase_Postamble">
|
<function-prolog>
|
Performs all the post operations for a test suite
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
|
<!-- Check the SignalRaised flag -->
|
<if expr="SignalRaised">
|
<sequence>
|
<message>
|
'A signal (%s) was raised during this test case' % SignalRaised
|
</message>
|
<tcstatus result="'fail'"/>
|
</sequence>
|
</if>
|
|
<!-- Reset the SignalRaised flag -->
|
<script>
|
SignalRaised=''
|
</script>
|
|
<!-- Query the test case results -->
|
<call function="'queryTestcase'" />
|
|
<script>
|
if STAFResult.has_key('numPasses'):
|
numPass=int(STAFResult['numPasses'])
|
else:
|
numPass=int(0)
|
|
if STAFResult.has_key('numFails'):
|
numFail=int(STAFResult['numFails'])
|
else:
|
numFail=int(0)
|
|
if STAFResult.has_key('startedTimestamp'):
|
startTimestamp=STAFResult['startedTimestamp']
|
else:
|
startTimestamp=int(0)
|
|
if STAFResult.has_key('information'):
|
information=STAFResult['information']
|
else:
|
information=''
|
|
if numFail == 0:
|
if numPass == 0:
|
_status='INCONCLUSIVE'
|
_result='unknown'
|
else:
|
_status='PASS'
|
_result='pass'
|
else:
|
if len(issuesList)==0:
|
_status='FAIL'
|
_result='fail'
|
else:
|
_status='KNOWN ISSUES %s' % str(issuesList)
|
_result='fail'
|
</script>
|
|
<message level="'status'">
|
'## Test Verdict: %s ##' % _status
|
</message>
|
|
<call function="'testCase_EndBanner'" />
|
|
<script>
|
testcaseEndTime = strftime("%Y%m%d@%H:%M:%S",localtime())
|
|
testcaseStop=int(time.time())
|
testcaseDuration=testcaseStop-testcaseStart
|
shortName=get_test_name(STAXCurrentTestcase)
|
|
xml.testcase = doc.createElement("testcase")
|
xml.createAttr(doc,xml.testcase,"name",STAXCurrentTestcase)
|
xml.createAttr(doc,xml.testcase,"duration",testcaseDuration)
|
xml.createAttr(doc,xml.testcase,"group",ThisGroupName)
|
xml.createAttr(doc,xml.testcase,"result",_result)
|
xml.createAttr(doc,xml.testcase,"shortname",shortName.lower())
|
xml.createAttr(doc,xml.testcase,"start",startTimestamp)
|
xml.createAttr(doc,xml.testcase,"stop",testcaseEndTime)
|
xml.createAttr(doc,xml.testcase,"suite",ThisSuiteName)
|
xml.createAttr(doc,xml.testcase,"info",information)
|
xml.testsuite.appendChild(xml.testcase)
|
|
if len(issuesList)!=0:
|
xml.issues = doc.createElement("issues")
|
xml.testcase.appendChild(xml.issues)
|
|
for issueID in issuesList:
|
xml.issue = doc.createElement("issue")
|
xml.createAttr(doc,xml.issue,"id",issueID)
|
xml.issues.appendChild(xml.issue)
|
|
xml.writeXMLfile(doc,"%s/results2.xml" % logs.reports)
|
</script>
|
|
<call function="'queryLogs'">
|
{ 'location' : STAXServiceMachine,
|
'logname' : 'STAX_Job_%s_User' % STAXJobID,
|
'startfrom' : testcaseStartTime,
|
'endat' : testcaseEndTime }
|
</call>
|
|
</sequence>
|
</function>
|
|
<function name="testSuite_Preamble">
|
<function-prolog>
|
Performs all the pre operations for a test suite
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
|
<!-- Take the values from the current test path -->
|
<script>
|
if not CurrentTestPath.has_key('group'):
|
CurrentTestPath['group']='unknown-group'
|
|
if not CurrentTestPath.has_key('suite'):
|
CurrentTestPath['suite']='unknown-suite'
|
|
ThisGroupName=CurrentTestPath['group']
|
ThisSuiteName=CurrentTestPath['suite']
|
|
#Create testsuite element
|
xml.testsuite = doc.createElement("testsuite")
|
xml.createAttr(doc,xml.testsuite,"name",ThisSuiteName)
|
xml.createAttr(doc,xml.testsuite,"shortname",ThisSuiteName)
|
xml.testgroup.appendChild(xml.testsuite)
|
|
xml.writeXMLfile(doc,"%s/results2.xml" % logs.reports)
|
|
</script>
|
|
<!-- Start time of test suite -->
|
<script>
|
TestSuiteStartTime=strftime("%Y%m%d@%H:%M:%S",localtime())
|
</script>
|
|
<message>
|
'#### %s/%s suite preamble ####' % (ThisGroupName,ThisSuiteName)
|
</message>
|
|
</sequence>
|
</function>
|
|
<function name="testSuite_Postamble">
|
<function-prolog>
|
Performs all the post operations for a test suite
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
|
<!-- Take the values from the current test path -->
|
<script>
|
if CurrentTestPath.has_key('suite'):
|
ThisSuiteName=CurrentTestPath['suite']
|
else:
|
ThisSuiteName='unknown-suite'
|
|
if CurrentTestPath.has_key('group'):
|
ThisGroupName=CurrentTestPath['group']
|
else:
|
ThisGroupName='unknown-group'
|
</script>
|
|
<message>
|
'#### %s/%s suite postamble ####' % (ThisGroupName,ThisSuiteName)
|
</message>
|
|
<!-- Start time of test suite -->
|
<script>
|
TestSuiteEndTime=strftime("%Y%m%d@%H:%M:%S",localtime())
|
</script>
|
|
<!-- Format the test group and suite names to create folder -->
|
<script>
|
FormattedTestcase=format_testcase()
|
FormattedTestgroup=FormattedTestcase.group(ThisGroupName)
|
FormattedTestsuite=FormattedTestcase.suite(ThisSuiteName)
|
|
TestLogDir= '%s/%s' % (logs.tests,FormattedTestgroup)
|
TestLogFile='%s/%s' % (TestLogDir,FormattedTestsuite)
|
</script>
|
|
<call function="'WriteLogsForTestCase'">
|
{ 'starttime' : TestSuiteStartTime,
|
'endtime' : TestSuiteEndTime,
|
'logFile' : TestLogFile }
|
</call>
|
|
<script>
|
if CurrentTestPath.has_key('suite'):
|
del CurrentTestPath['suite']
|
</script>
|
|
</sequence>
|
</function>
|
|
<function name="testGroup_Preamble">
|
<function-prolog>
|
Performs all the pre operations for a test group
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
<!-- Take the values from the current test path -->
|
<script>
|
if not CurrentTestPath.has_key('group'):
|
CurrentTestPath['group']='unknown-group'
|
|
ThisGroupName=CurrentTestPath['group']
|
|
xml=xmldoc_service()
|
|
doc = xml.parseXMLfile("%s/results2.xml" % logs.reports)
|
|
qa = doc.getDocumentElement()
|
ft = qa.getChildNodes().item(1)
|
results = ft.getChildNodes().item(3)
|
|
#Create testgroup element
|
xml.testgroup = doc.createElement("testgroup")
|
xml.createAttr(doc,xml.testgroup,"name",ThisGroupName)
|
results.appendChild(xml.testgroup)
|
|
xml.writeXMLfile(doc,"%s/results2.xml" % logs.reports)
|
|
</script>
|
<message>'##### %s group preamble #####' % ThisGroupName</message>
|
</sequence>
|
</function>
|
|
<function name="testGroup_Postamble">
|
<function-prolog>
|
Performs all the post operations for a test group
|
</function-prolog>
|
<function-no-args />
|
<sequence>
|
|
<script>
|
if CurrentTestPath.has_key('group'):
|
ThisGroupName=CurrentTestPath['group']
|
else:
|
ThisGroupName='unknown-group'
|
|
coverage='N/A'
|
</script>
|
|
<message>'##### %s group postamble #####' % ThisGroupName</message>
|
|
<script>
|
emmaJar='%s/%s/lib/emma.jar' % (DIRECTORY_INSTANCE_DIR,OPENDSNAME)
|
</script>
|
|
<if expr="os.path.exists(emmaJar)">
|
<sequence>
|
<script>
|
coveragePath=os.path.join(LOGS_ROOT,'coverage')
|
coverageEm=os.path.join(coveragePath,'coverage.em')
|
ecPath=os.path.join(coveragePath,CurrentTestPath['group'])
|
coverageEcs=[ os.path.join(ecPath,ec) for ec in os.listdir(ecPath) if ec.startswith('coverage') and ec.endswith('.ec')]
|
coverageFiles=','.join(coverageEcs)
|
coverageXml=os.path.join(ecPath,'coverage.xml')
|
coverageHtml=os.path.join(ecPath,'coverage.html')
|
srcPathPrefix = os.path.join(TMPDIR,"..","..","..","..","..","..","src")
|
srcPaths = [ os.path.join(srcPathPrefix,"server"),
|
os.path.join(srcPathPrefix,"ads"),
|
os.path.join(srcPathPrefix,"server","org"),
|
os.path.join(srcPathPrefix,"admin","defn","org"),
|
os.path.join(srcPathPrefix,"snmp","src","org"),
|
os.path.join(srcPathPrefix,"ads","org"),
|
os.path.join(srcPathPrefix,"dsml","org"),
|
os.path.join(srcPathPrefix,"messages","src","org")
|
]
|
srcArgs = " -sp ".join(srcPaths)
|
</script>
|
<call function="'runCommand'">
|
{ 'name' : 'Generate coverage xml report for test group %s' % CurrentTestPath['group'],
|
'command' : 'java',
|
'arguments' : ' -Xms64M -Xmx1G -cp %s emma report -r html -in %s,%s -Dreport.html.out.file=%s -sp %s' % (emmaJar, coverageEm, coverageFiles, coverageHtml, srcArgs),
|
'path' : TMPDIR
|
}
|
</call>
|
</sequence>
|
</if>
|
|
<script>
|
if CurrentTestPath.has_key('group'):
|
del CurrentTestPath['group']
|
</script>
|
</sequence>
|
</function>
|
|
<function name="WriteLogsForTestCase" scope="local">
|
|
<function-prolog>
|
Queries the staf logs for the test case and write to file as text
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="starttime" type="required">
|
<function-arg-description>
|
timestamp to start logging from
|
</function-arg-description>
|
<function-arg-property name="type" value="timestamp"/>
|
</function-arg-def>
|
<function-arg-def name="endtime" type="required">
|
<function-arg-description>
|
timestamp to start logging to
|
</function-arg-description>
|
<function-arg-property name="type" value="timestamp"/>
|
</function-arg-def>
|
<function-arg-def name="logFile" type="required">
|
<function-arg-description>
|
name of file to write the logs
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
|
<script>
|
xmlFile = '%s-log.xml' % logFile
|
htmlFile = '%s-log.html' % logFile
|
xslFile = '%s/gen-logs.xsl' % TESTS_XSL_DIR
|
</script>
|
|
<!-- Query STAF to obtain the logs for the test case -->
|
<call function="'queryLogs'">
|
{ 'location' : STAXServiceMachine,
|
'logname' : 'STAX_Job_%s_User' % STAXJobID,
|
'startfrom' : starttime,
|
'endat' : endtime }
|
</call>
|
|
<!-- Write out the logs into an XML file -->
|
<call function="'WriteXmlLogs'">
|
{ 'queryresult' : STAFResult,
|
'output' : xmlFile }
|
</call>
|
|
<!-- Transform the XML file into an HTML file -->
|
<call function="'WriteHtmlLogs'">
|
{ 'input' : xmlFile,
|
'stylesheet' : xslFile,
|
'output' : htmlFile }
|
</call>
|
|
</sequence>
|
|
</function>
|
|
<function name="WriteXmlLogs" scope="local">
|
|
<function-prolog>
|
Process staf log query results and write them to a file
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="queryresult" type="required">
|
<function-arg-description>
|
result of the staf log query
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="output" type="required">
|
<function-arg-description>
|
name of the XML file to where results are written
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
|
<script>
|
logFile=output
|
NewLogDir=os.path.dirname(logFile)
|
</script>
|
|
<message>'Creating XML log file %s' % logFile</message>
|
|
<call function="'createFolder'">
|
{ 'location' : STAXServiceMachine,
|
'foldername' : NewLogDir }
|
</call>
|
|
<script>
|
from xml.dom.minidom import Document
|
doc = Document()
|
|
# Create the qa base element
|
qa = doc.createElement("qa")
|
doc.appendChild(qa)
|
|
# Create the base element
|
logs = doc.createElement("logs")
|
qa.appendChild(logs)
|
|
# Try to pass only the pretty print of the test suite name
|
try:
|
suite=CurrentTestPath['suite'].split('.')[2].strip()
|
except:
|
formattedTestcase = format_testcase()
|
suite = formattedTestcase.suite(CurrentTestPath['suite'])
|
|
# Create the log element
|
log = doc.createElement("log")
|
log.setAttribute("group", "%s" % CurrentTestPath['group'])
|
log.setAttribute("suite", "%s" % suite)
|
log.setAttribute("jobid", "%s" % STAXJobID)
|
log.setAttribute("parent", "%s" % STAXParentID)
|
logs.appendChild(log)
|
</script>
|
|
<if expr="queryresult == '[]'">
|
<sequence>
|
<script>
|
output1 = 'queryresult is empty'
|
output2 = 'check the date between the OS, the logs'
|
output3 = 'and the local time zone'
|
output = '%s %s %s' % (output1,output2,output3)
|
</script>
|
<call function="'checktestRC'">
|
{ 'returncode' : '1' ,
|
'result' : output,
|
'expected' : '0' }
|
</call>
|
</sequence>
|
<else>
|
<iterate var="element" in="queryresult">
|
<script>
|
level=element['level']
|
message=element['message']
|
timestamp=element['timestamp']
|
|
line = doc.createElement("line")
|
line.setAttribute("timestamp", "%s" % timestamp)
|
line.setAttribute("level", "%s" % level)
|
line.setAttribute("message", "%s" % message)
|
if level == 'Start':
|
tag=get_test_name(message.replace('testcase: ',''))
|
line.setAttribute("tag", "%s" % tag.lower())
|
log.appendChild(line)
|
</script>
|
</iterate>
|
</else>
|
</if>
|
|
<script>
|
_message='Generated XML test case report.'
|
testlogfh=open('%s' % logFile,'w')
|
try:
|
testlogfh.writelines(doc.toprettyxml(indent=" "))
|
except AttributeError,details:
|
_message='Unable to generate XML test case report %s.' % details
|
except:
|
_message='Unable to generate XML test case report !!!'
|
testlogfh.close()
|
|
firstline=0
|
newlines=[]
|
testlogfh=open('%s' % logFile,'r')
|
lines=testlogfh.readlines()
|
|
for l in lines:
|
if firstline==0:
|
newlines.append('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
|
firstline=1
|
else:
|
newlines.append(l)
|
|
testlogfh.close()
|
|
testlogfh=open('%s' % logFile,'w')
|
testlogfh.writelines(newlines)
|
testlogfh.close()
|
</script>
|
|
<message>_message</message>
|
|
</sequence>
|
|
</function>
|
|
<function name="WriteHtmlLogs" scope="local">
|
|
<function-prolog>
|
Process XML file and transform that to an HTML log file
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="input" type="required">
|
<function-arg-description>
|
name of the XML file to where results are obtained
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="output" type="required">
|
<function-arg-description>
|
name of the HTML file to where results are written
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="stylesheet" type="required">
|
<function-arg-description>
|
name of the XSL stylesheet used to transform results
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
|
<script>
|
xmlFile=input
|
htmlFile=output
|
xslFile=stylesheet
|
</script>
|
|
<message>'Inputting XML file %s' % xmlFile</message>
|
<message>'Transform XSL file %s' % xslFile</message>
|
<message>'Creating HTML file %s' % htmlFile</message>
|
|
<script>
|
_message='Generated test case logs.'
|
testCaseLogs=report_generation()
|
stringParamsDict={}
|
|
try:
|
testCaseLogs.transformReport(xslFile,xmlFile,htmlFile,stringParamsDict)
|
except java.io.FileNotFoundException,details:
|
_message='Unable to generate test case logs %s.' % details
|
except IOError,details:
|
_message='Unable to generate test case logs %s.' % details
|
except:
|
_message='Unable to generate test case logs !!!'
|
</script>
|
|
<message>'%s' % _message</message>
|
|
</sequence>
|
|
</function>
|
|
<function name="CheckMatches">
|
<function-prolog>
|
check the number of matching sub-string in a string
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="string2find" type="required">
|
<function-arg-description>
|
the sub-string to check
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="mainString" type="required">
|
<function-arg-description>
|
the main string where the search is done
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="caseSensitive" type="optional" default="True">
|
<function-arg-description>
|
comparison using case sensitive, or not value is : True/False
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="nbExpected" type="optional" default="1">
|
<function-arg-description>
|
number of expected sub-string that must be in the main string
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="issue" type="optional" default="None">
|
<function-arg-description>
|
Issue id. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>
|
caseSensitiveInfo = '[case sensitive mode]'
|
|
if caseSensitive == False:
|
string2find = string2find.lower()
|
mainString = mainString.lower()
|
caseSensitiveInfo = '[case insensitive mode]'
|
|
nbFound = mainString.count(string2find)
|
if nbFound == nbExpected:
|
myMessage = 'SUCCESS : %s matches %s time(s) (expected %s) %s' % (string2find,nbFound,nbExpected,caseSensitiveInfo)
|
myRC=0
|
else:
|
myMessage = 'ERROR : %s matches %s time(s) (expected %s) in "%s" %s' % (string2find,nbFound,nbExpected,mainString,caseSensitiveInfo)
|
myRC=1
|
</script>
|
<if expr="myRC == 0">
|
<sequence>
|
<tcstatus result="'pass'"/>
|
<message log="1">
|
'%s' % myMessage
|
</message>
|
</sequence>
|
<else>
|
<sequence>
|
<if expr="issue == None">
|
<tcstatus result="'fail'"/>
|
<else>
|
<sequence>
|
<call function="'setKnownIssue'">
|
{ 'issueId' : issue }
|
</call>
|
</sequence>
|
</else>
|
</if>
|
<message log="1" level="'Error'">
|
'%s' % myMessage
|
</message>
|
</sequence>
|
</else>
|
</if>
|
<return>myRC,myMessage</return>
|
</sequence>
|
</function>
|
|
<function name="runFunction" scope="local">
|
<function-map-args>
|
<function-arg-def name="functionName" type="required">
|
<function-arg-description>
|
Name of the function to run
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="functionArguments" type="optional">
|
<function-arg-description>
|
Arguments to be passed on to the called function.
|
This can be a map or a list of arguments, whatever the called function
|
expects will be carried on here.
|
. for a map, pass the arguments like this:
|
{ 'argumentA' : 'argumentAvalue' ,
|
'argumentB' : 1 ,
|
...
|
}
|
. for a list, pass the arguments like this:
|
[ 'argumentAvalue, 1, ... ]
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="expectedRC" type="optional" default="0">
|
<function-arg-description>
|
The expected return code of the function to run.
|
This is then passed onto the checkRC function.
|
It is also used to throw an exception if the argument
|
functionException is provided and set the test case status if the
|
argument functionSetsTCStatus is provided
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
|
<function-arg-def name="functionException" type="optional">
|
<function-arg-description>
|
The exception to throw if the return code differs from the expected
|
RC. The exception is appended to STAXException.
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="functionMessage" type="optional">
|
<function-arg-description>
|
An optional message to display before running the function
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="functionSetsTCStatus" type="optional">
|
<function-arg-description>
|
Whether the function to run sets the testcase status or not.
|
If this is set, the test case status is set according to whether
|
or not the function meets the expected return code.
|
True or False should be used for this argument.
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="functionFailureTC" type="optional">
|
<function-arg-description>
|
If this argument is provided, a testcase will be created with
|
this argument's value for name and set to fail only upon failure
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="functionSignal" type="optional">
|
<function-arg-description>
|
If this argument is provided, a signal will be raised upon unsuccesful
|
execution of the function to run
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="functionCallBack" type="optional">
|
<function-arg-description>
|
If this argument is provided then functionCallBack will be called
|
after the execution of function name.
|
</function-arg-description>
|
</function-arg-def>
|
|
<function-arg-def name="functionCallBackArguments" type="optional">
|
<function-arg-description>
|
This allows to specify arguments for the call back function
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
<!-- defining the booleans here should temporary while I find a nicer
|
solution. We have a chicken and egg problem between the
|
loadGlobalEnvironment and loadSharedLibraries functions in
|
environment.xml at the moment.
|
-->
|
if not False:
|
False=0
|
|
if not True:
|
True=1
|
|
_expectedRC=int(expectedRC)
|
|
_throwException=False
|
if functionException:
|
_throwException=True
|
|
_displayMessage=False
|
if functionMessage:
|
_displayMessage=True
|
|
_tcStatus='fail'
|
_doSetTCStatus=False
|
if functionSetsTCStatus:
|
_doSetTCStatus=True
|
|
_createFailureTC=False
|
if functionFailureTC:
|
_createFailureTC=True
|
</script>
|
<message log="1" level="'info'" if="_displayMessage == True">
|
'%s' % functionMessage
|
</message>
|
<message log="1" level="'debug'">
|
'runFunction: %s: called with parameters [%s]' % (functionName,functionArguments)
|
</message>
|
<call function="functionName">functionArguments</call>
|
<script>
|
_functionRC = int(RC)
|
_functionResult = STAXResult
|
</script>
|
|
<!-- this section handles the optional case when we need to set the
|
test case status
|
-->
|
<if expr="_doSetTCStatus == True">
|
<sequence>
|
<if expr="_functionRC == _expectedRC">
|
<script>_tcStatus='pass'</script>
|
</if>
|
<tcstatus result="_tcStatus" />
|
</sequence>
|
</if>
|
|
<!-- this section handles the optional case when we need to throw an
|
exception upon unexpected function return code
|
-->
|
<if expr="_throwException == True" >
|
<if expr="_functionRC != _expectedRC" >
|
<throw exception="'STAXException.%s' % functionException" />
|
</if>
|
</if>
|
|
<!-- this section handles the optional case when we need to set a
|
test case status to fail to reflect the failure in the test report.
|
-->
|
<if expr="_createFailureTC == True" >
|
<if expr="_functionRC != _expectedRC" >
|
<testcase name="'!!! %s [%s]' % (functionFailureTC,functionName)">
|
<tcstatus result="'fail'" />
|
</testcase>
|
</if>
|
</if>
|
|
<!-- TODO: implement the signal raising mechanism -->
|
<!-- TODO: implement the call back function mechanism -->
|
|
<!-- bubble the function return code and result up one level -->
|
<return>[_functionRC,_functionResult]</return>
|
</sequence>
|
</function>
|
|
<function name="runCommand" >
|
<function-description>
|
A general wrapper to run a command without having to write a dedicated
|
function for it
|
</function-description>
|
<function-map-args>
|
<function-arg-def name="command" type="required">
|
<function-arg-description>
|
the command to run
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="path" type="optional" default="dsBinPath">
|
<function-arg-description>
|
the path where the command is to be run from
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="arguments" type="optional" default="''">
|
<function-arg-description>
|
the path where the command is to be found
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="envCmd"
|
type="optional"
|
default="''">
|
<function-arg-description>
|
the environment variables to set. The default set here should just
|
work for OpenDS commands
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAXServiceMachine">
|
<function-arg-description>
|
Which machine should the command be executed on
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="name"
|
default="'Running %s' % command"
|
type="optional">
|
<function-arg-description>
|
The name to give the process (only matters in the STAX Monitor really)
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="stripOutput" default="True" type="optional">
|
<function-arg-description>
|
A boolean (use True or False here, case matters) to enable disable
|
stripping the output of a command
|
TODO: consider allowing passing a function name to enable custom
|
output manipulation (overkill?)
|
</function-arg-description>
|
<function-arg-property name="type" value="enum">
|
<function-arg-property-description>
|
This argument can only have boolean values
|
</function-arg-property-description>
|
<function-arg-property-data type="choice" value="True"/>
|
<function-arg-property-data type="choice" value="False"/>
|
</function-arg-property>
|
</function-arg-def>
|
<function-arg-def name="timerDuration"
|
type="optional"
|
default="'5m'">
|
<function-arg-description>
|
The duration that the process is allowed to run
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="inputFile" type="optional" default="'None'">
|
<function-arg-description>
|
input file containing the command input
|
</function-arg-description>
|
<function-arg-property name="type" value="file"/>
|
</function-arg-def>
|
<function-arg-def name="outputFile" type="optional" default="'None'">
|
<function-arg-description>
|
Output file containing the command output
|
</function-arg-description>
|
<function-arg-property name="type" value="file"/>
|
</function-arg-def>
|
<function-arg-def name="expectedRC" type="optional" default="0">
|
<function-arg-description>
|
Expected return code value. Default value is 0.
|
Wildcard 'noCheck' to not check the RC
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="knownIssue" type="optional" default="None">
|
<function-arg-description>
|
Known issue. Corresponds to an issue number.
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="logStderr" type="optional" default="True">
|
<function-arg-description>
|
If true, stderr for the command is redirect to stdout.
|
</function-arg-description>
|
<function-arg-property name="type" value="enum">
|
<function-arg-property-description>
|
This argument can only have boolean values
|
</function-arg-property-description>
|
<function-arg-property-data type="choice" value="True"/>
|
<function-arg-property-data type="choice" value="False"/>
|
</function-arg-property>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
import random
|
import java.util.Date
|
random.seed(java.util.Date().getTime())
|
_id = '%s#%d' % (strftime('%Y-%m-%d %H:%M:%S',localtime()),random.randint(0,999))
|
|
env=[]
|
for item in envCmd:
|
env.append('%s' % item)
|
if is_windows_platform(location):
|
env.append('PATH=%s\\bin;C:\\Windows;C:\\Windows\\system32;%s' % (REMOTE_STAF_ROOT,path))
|
env.append('JAVA_HOME=%s' % JAVA_HOME)
|
else:
|
env.append('PATH=/bin:/usr/bin:%s' % path)
|
env.append('JAVA_HOME=%s' % JAVA_HOME)
|
|
if command.endswith('setup.bat') or command.endswith('uninstall.bat'):
|
arguments = arguments + ' & set PROCESSRC=%ERRORLEVEL% & exit %PROCESSRC%'
|
|
if TESTS_TYPE == 'functional-tests':
|
timerDuration = '5m'
|
else:
|
timerDuration = '24h'
|
</script>
|
<message>
|
'%s: Running command:\n %s %s\nlocation: %s\nenv: %s\nworkdir: %s' % (_id,command,arguments,location,env,path)
|
</message>
|
|
<timer duration="timerDuration">
|
<sequence>
|
<!-- If 'logStderr' is True then redirect sdterr to sdtout -->
|
<if expr="logStderr == True">
|
<process name="name">
|
<location>location</location>
|
<command>command</command>
|
<parms>arguments</parms>
|
<workdir>path</workdir>
|
<envs>env</envs>
|
<console use="'same'"/>
|
<stdout if="outputFile != 'None'" mode="'replace'">'%s' % outputFile</stdout>
|
<stderr mode="'stdout'"/>
|
<returnstdout/>
|
</process>
|
<elseif expr="inputFile != 'None'">
|
<process name="name">
|
<location>location</location>
|
<command>command</command>
|
<parms>arguments</parms>
|
<workdir>path</workdir>
|
<envs>env</envs>
|
<console use="'same'"/>
|
<stdin>'%s' % inputFile</stdin>
|
<returnstdout/>
|
</process>
|
</elseif>
|
<else>
|
<process name="name">
|
<location>location</location>
|
<command>command</command>
|
<parms>arguments</parms>
|
<workdir>path</workdir>
|
<envs>env</envs>
|
<console use="'same'"/>
|
<stdout if="outputFile != 'None'" mode="'replace'">'%s' % outputFile</stdout>
|
<returnstdout/>
|
</process>
|
</else>
|
</if>
|
|
<!-- The problem here is that STAXResult can either be a
|
string, list or a map object -->
|
<script>
|
try:
|
cmdOutput=STAXResult[0][1]
|
cmdRC = RC
|
except:
|
cmdOutput=STAXResult
|
cmdRC = RC
|
|
cmdResult=STAXResult
|
</script>
|
|
<script>
|
def dig(var):
|
try:
|
if var.__class__==[].__class__:
|
for i in range(len(var)):
|
var[i]=dig(var[i])
|
return var
|
else:
|
if var.__class__==''.__class__:
|
return re.compile(r'EMMA:.*\n').sub('',var)
|
else:
|
return var
|
except TypeError:
|
return 'could not evaluate the following component: %s' % var
|
|
if stripOutput == True:
|
cmdResult=dig(cmdResult)
|
</script>
|
|
<if expr="expectedRC != 'noCheck'">
|
<call function="'checktestRC'">
|
{ 'returncode' : cmdRC,
|
'result' : cmdResult,
|
'expected' : expectedRC,
|
'issue' : knownIssue
|
}
|
</call>
|
</if>
|
</sequence>
|
</timer>
|
|
<if expr="RC == 1">
|
<sequence>
|
<script>
|
cmdResult=[[1,'Timeout']]
|
</script>
|
|
<message log="1" level="'Error'">
|
'ERROR: COMMAND HANGING, not completed after %s' % timerDuration
|
</message>
|
|
<tcstatus result="'fail'"/>
|
</sequence>
|
</if>
|
|
<return>
|
cmdResult
|
</return>
|
</sequence>
|
</function>
|
|
|
|
<function name="killDs">
|
<function-prolog>
|
Kill the ldap server
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAF_REMOTE_HOSTNAME">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsPath"
|
type="optional"
|
default="'%s/%s'
|
% (DIRECTORY_INSTANCE_DIR,OPENDSNAME)">
|
<function-arg-description>
|
Pathname to installation root
|
</function-arg-description>
|
<function-arg-property name="type" value="pathname"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<message>
|
'Kill server running on %s at %s' % (location, dsPath)
|
</message>
|
|
<script>
|
pidPath = '%s/logs/server.pid' % dsPath
|
_args = '%s' % pidPath
|
</script>
|
|
<call function="'runSTAFCommand'">
|
{ 'name' : 'Read server pid file',
|
'location' : location,
|
'service' : 'FS',
|
'request' : 'GET FILE',
|
'arguments' : _args
|
}
|
</call>
|
|
<script>
|
if is_windows_platform(location):
|
_cmd = 'tskill'
|
_args = STAXResult
|
else:
|
_cmd = '/bin/kill'
|
pid = STAXResult[:-1]
|
_args = '-9 %s' % pid
|
</script>
|
<call function="'runCommand'">
|
{ 'name' : 'Kill DS server',
|
'location' : location,
|
'command' : _cmd,
|
'arguments' : _args
|
}
|
</call>
|
<return>STAXResult</return>
|
</sequence>
|
</function>
|
|
<function name="runSTAFCommand" >
|
<function-description>
|
A general wrapper to run a STAF command without having to write a
|
dedicated function for it
|
</function-description>
|
<function-map-args>
|
<function-arg-def name="location" type="optional" default="STAXServiceMachine">
|
<function-arg-description>
|
Which machine should the command be executed on
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="name" type="required">
|
<function-arg-description>
|
The name to give the process
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="service" type="required">
|
<function-arg-description>
|
the command to run
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="request" type="required">
|
<function-arg-description>
|
the command to run
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="arguments" type="optional" default="''">
|
<function-arg-description>
|
the arguments for the service request
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
import random
|
import java.util.Date
|
random.seed(java.util.Date().getTime())
|
_id = '%s#%d' % (strftime('%Y-%m-%d %H:%M:%S',localtime()),random.randint(0,99999))
|
|
</script>
|
<message>
|
'%s: Running STAF command:\n %s %s %s\nlocation: %s\n' % (_id,service,request,arguments,location)
|
</message>
|
|
<block name="'%s:Wrapper for %s' % (_id,name)">
|
<stafcmd name="'STAF Command: %s' % name">
|
<location>'%s' % location</location>
|
<service>service</service>
|
<request>
|
'%s %s' % (request,arguments)
|
</request>
|
</stafcmd>
|
</block>
|
|
<message level="'info'">
|
'%s: STAF Command returned:\n%s' % (_id,STAFResult)
|
</message>
|
|
<return>
|
STAFResult
|
</return>
|
</sequence>
|
</function>
|
|
<function name="grep">
|
<function-prolog>
|
This function search for a given string in a given file.
|
BEWARE! of potential performance degradation when grepping big files due
|
to the use of getFile, which loads the whole file content into a variable.
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAF_REMOTE_HOSTNAME">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="filename" type="required">
|
<function-arg-description>
|
File path
|
</function-arg-description>
|
<function-arg-property name="type" value="pathname"/>
|
</function-arg-def>
|
<function-arg-def name="testString" type="required">
|
<function-arg-description>
|
String searched
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="expectedRC" type="optional" default="0">
|
<function-arg-description>
|
Expected return code value.
|
0 for successful grep, 1 for unsuccessful grep. Default value is 0.
|
Wildcard 'noCheck' to not check the RC
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<message>
|
'Search for string \"%s\" in file %s on host %s' % \
|
(testString, filename, location)
|
</message>
|
|
<call function="'getFile'">
|
{
|
'location' : location,
|
'filename' : filename
|
}
|
</call>
|
|
<script>
|
# getFile returns: STAXResult = [cmdRC, cmdResult]
|
filecontent = STAXResult[1]
|
|
if (expectedRC == 'noCheck'):
|
# don't care about expected result
|
myExpectedResult = '2'
|
elif (expectedRC == 0):
|
# expect testString to be present in filecontent
|
myExpectedResult = '1'
|
else:
|
# expect testString not to be present in filecontent
|
myExpectedResult = '0'
|
</script>
|
|
<call function="'searchStringForSubstring'">
|
{
|
'testString' : testString,
|
'returnString' : filecontent,
|
'expectedResult' : myExpectedResult
|
}
|
</call>
|
|
<return>STAXResult</return>
|
</sequence>
|
</function>
|
|
<function name="compareFile">
|
<function-prolog>
|
This function compares two files.
|
Print the differences if the comparison failed.
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAXServiceMachine">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="remotehost"
|
type="optional"
|
default="STAF_REMOTE_HOSTNAME">
|
<function-arg-description>
|
The name of remote host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsPath"
|
type="optional"
|
default="'%s/%s' % (DIRECTORY_INSTANCE_BIN,OPENDSNAME)">
|
<function-arg-description>
|
Pathname to installation root
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="outputFile" type="required">
|
<function-arg-description>
|
file containing output from the command
|
</function-arg-description>
|
<function-arg-property name="type" value="file"/>
|
</function-arg-def>
|
<function-arg-def name="outputPath" type="optional">
|
<function-arg-description>
|
path containing outputFile
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="refFile" type="optional">
|
<function-arg-description>
|
reference file containing expected output
|
</function-arg-description>
|
<function-arg-property name="type" value="file"/>
|
</function-arg-def>
|
<function-arg-def name="refPath" type="optional">
|
<function-arg-description>
|
reference path containing refFile
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="diffFile" type="optional">
|
<function-arg-description>
|
file containing diff output
|
</function-arg-description>
|
<function-arg-property name="type" value="file"/>
|
</function-arg-def>
|
<function-arg-def name="diffPath" type="optional">
|
<function-arg-description>
|
file containing diffFile
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="knownIssue" type="optional" default="None">
|
<function-arg-description>
|
Known issue. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string" />
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>
|
if CurrentTestPath.has_key('group'):
|
ThisGroupName = CurrentTestPath['group']
|
else:
|
ThisGroupName = 'unknown-group'
|
|
FormattedTestcase = format_testcase()
|
FormattedTestgroup = FormattedTestcase.group(ThisGroupName)
|
|
if not outputPath:
|
outputPath = '%s/..' % (dsPath)
|
|
if not refFile:
|
regexp = re.compile('\..*$')
|
tmpName = re.sub(regexp, '', outputFile)
|
refFile = '%s.ref' % tmpName
|
|
if not refPath:
|
refPath = '%s/%s' % (local.data,FormattedTestgroup)
|
|
if not diffFile:
|
regexp = re.compile('\..*$')
|
tmpName = re.sub(regexp, '', outputFile)
|
diffFile = '%s.diff' % tmpName
|
|
if not diffPath:
|
diffPath = '%s/%s/diffs' % (logs.tests,FormattedTestgroup)
|
else:
|
diffPath = '%s/diffs' % (diffPath)
|
|
cflocation=location
|
cfremotehost=remotehost
|
</script>
|
|
<!-- Check if 'diffPath' is already created -->
|
<call function="'GetEntry'">
|
{
|
'location' : cflocation,
|
'entry' : diffPath,
|
'attribute' : 'TYPE'
|
}
|
</call>
|
<!-- If 'diffPath' is not already created then create it -->
|
<if expr="RC == 48">
|
<sequence>
|
<message>
|
'Create folder %s' % diffPath
|
</message>
|
<call function="'createFolder'">
|
{
|
'location' : cflocation ,
|
'foldername' : diffPath
|
}
|
</call>
|
</sequence>
|
</if>
|
|
<message>
|
'Copy file %s/%s (on %s) to %s/%s (on %s)' % \
|
(outputPath, outputFile, cfremotehost, diffPath, outputFile, cflocation)
|
</message>
|
<call function="'copyFile'">
|
{
|
'location' : cfremotehost ,
|
'srcfile' : '%s/%s' % (outputPath, outputFile) ,
|
'destfile' : '%s/%s' % (diffPath, outputFile) ,
|
'remotehost' : cflocation
|
}
|
</call>
|
<script>
|
outputRC=RC
|
</script>
|
|
<message>
|
'Copy file %s/%s (on %s) to %s/%s (on %s)' % \
|
(refPath, refFile, cflocation, diffPath, refFile, cflocation)
|
</message>
|
<call function="'copyFile'">
|
{
|
'location' : cflocation ,
|
'srcfile' : '%s/%s' % (refPath, refFile) ,
|
'destfile' : '%s/%s' % (diffPath, refFile) ,
|
'remotehost' : cflocation
|
}
|
</call>
|
<script>
|
refRC=RC
|
</script>
|
|
<!-- If the copy of 'outputFile' and 'refFile' succeed
|
then compare these files -->
|
<if expr="outputRC == 0 and refRC == 0">
|
<sequence>
|
<message>
|
'Compare file %s/%s to %s/%s on %s' % \
|
(diffPath, outputFile, diffPath, refFile, cflocation)
|
</message>
|
<script>
|
CompareFile = compare_file('%s/%s' % (diffPath, outputFile),
|
'%s/%s' % (diffPath, refFile),
|
'%s/%s' % (diffPath, diffFile))
|
diff = CompareFile.genDiff()
|
</script>
|
|
<if expr="diff == ''">
|
<sequence>
|
<tcstatus result="'pass'"/>
|
<message log="1">
|
'SUCCESS : No differences were found between %s and %s' % \
|
(outputFile, refFile)
|
</message>
|
</sequence>
|
<else>
|
<sequence>
|
<if expr="knownIssue == None">
|
<tcstatus result="'fail'"/>
|
<else>
|
<call function="'setKnownIssue'">
|
{ 'issueId' : knownIssue }
|
</call>
|
</else>
|
</if>
|
<message log="1">
|
'ERROR : Differences were found between %s and %s\n%s' % \
|
(outputFile, refFile, diff)
|
</message>
|
<message log="1">
|
'ERROR : Diff file is here: %s/%s' % (diffPath, diffFile)
|
</message>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
<else>
|
<sequence>
|
<tcstatus result="'fail'"/>
|
<message log="1">
|
'ERROR : Error during file comparision'
|
</message>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</function>
|
|
<function name="compileJava" scope="local">
|
<function-prolog>
|
This function compile java files.
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAXServiceMachine">
|
<function-arg-description>
|
Location of remote host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="foldername" type="optional">
|
<function-arg-description>
|
Path containing java files to compile
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="destfolder" type="optional">
|
<function-arg-description>
|
Path where to place generated class files
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="classpath" type="optional">
|
<function-arg-description>
|
Additional classpath
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="expectedRC" type="optional" default="0">
|
<function-arg-description>
|
Expected return code value. Default value is 0.
|
Wildcard 'noCheck' to not check the RC
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
|
<!-- Build the command -->
|
<script>
|
cmdOptions = ''
|
|
if is_windows_platform(location):
|
separator=';'
|
else:
|
separator=':'
|
|
if classpath:
|
cp = 'CLASSPATH=%s%s.' % (classpath, separator)
|
else:
|
cp = 'CLASSPATH=.'
|
|
if location == STAXServiceMachine:
|
cmd = '%s/bin/javac' % LOCAL_JAVA_HOME
|
env = ['%s' % cp]
|
else:
|
cmd = '%s/bin/javac' % JAVA_HOME
|
env = ['JAVA_HOME=%s' % JAVA_HOME, '%s' % cp]
|
|
if destfolder:
|
cmdOptions = '-d %s' % destfolder
|
</script>
|
|
<call function="'listFolderByExtension'" >
|
{
|
'location' : location ,
|
'foldername' : foldername ,
|
'extension' : 'java'
|
}
|
</call>
|
|
<script>
|
cmdResult = STAXResult
|
</script>
|
|
<if expr="cmdResult != 'Folder does not exist.'">
|
<sequence>
|
<script>
|
list = ""
|
for file in cmdResult:
|
list = list + " " + file
|
</script>
|
|
<call function="'runCommand'" >
|
{
|
'name' : 'Compile Java files' ,
|
'command' : cmd ,
|
'arguments' : '-target 1.5 %s %s' % (cmdOptions,list) ,
|
'location' : location ,
|
'path' : foldername ,
|
'envCmd' : env ,
|
'expectedRC' : expectedRC
|
}
|
</call>
|
</sequence>
|
<else>
|
<tcstatus result="'fail'"></tcstatus>
|
</else>
|
</if>
|
|
<return>
|
STAXResult
|
</return>
|
</sequence>
|
</function>
|
|
<function name="createJar" scope="local">
|
<function-prolog>
|
This function create a jar file.
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAXServiceMachine">
|
<function-arg-description>
|
Location of remote host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="jarname" type="required">
|
<function-arg-description>
|
Name of the jar file to create
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="entrypoint" type="required">
|
<function-arg-description>
|
Path where to find generated class files
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="pathfolder" type="required">
|
<function-arg-description>
|
Execution path
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="manifestpath" type="optional">
|
<function-arg-description>
|
Path to the manifest file
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="expectedRC" type="optional" default="0">
|
<function-arg-description>
|
Expected return code value. Default value is 0.
|
Wildcard 'noCheck' to not check the RC
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
|
<!-- Build the command -->
|
<script>
|
if location == STAXServiceMachine:
|
cmd = '%s/bin/jar' % LOCAL_JAVA_HOME
|
else:
|
cmd = '%s/bin/jar' % JAVA_HOME
|
|
if manifestpath:
|
cmdOptions = 'cmf %s' % manifestpath
|
else:
|
cmdOptions = 'cf'
|
</script>
|
|
<!-- Check if the classfolder exists -->
|
<call function="'GetEntry'">
|
{
|
'location' : location ,
|
'entry' : '%s/%s' % (pathfolder,entrypoint) ,
|
'attribute' : 'TYPE'
|
}
|
</call>
|
<if expr="RC != 48">
|
<sequence>
|
<call function="'runCommand'" >
|
{
|
'name' : 'Create Jar file' ,
|
'command' : cmd ,
|
'arguments' : '%s %s %s' % (cmdOptions,jarname,entrypoint) ,
|
'location' : location ,
|
'path' : pathfolder ,
|
'expectedRC' : expectedRC
|
}
|
</call>
|
</sequence>
|
<else>
|
<tcstatus result="'fail'"></tcstatus>
|
</else>
|
</if>
|
|
<return>
|
STAXResult
|
</return>
|
</sequence>
|
</function>
|
|
<function name="getFreePort" scope="local">
|
<function-description>
|
Returns the first free TCP port greater or equal to given number
|
</function-description>
|
<function-map-args>
|
<function-arg-def name="host"
|
type="optional"
|
default="STAXServiceMachine">
|
<function-arg-description>
|
Which machine to look for the free port
|
</function-arg-description>
|
</function-arg-def>
|
<function-arg-def name="port" type="required">
|
<function-arg-description>
|
The minimal port number to be returned
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
# returns first free port in [port; port+5]
|
# if no free port in this interval, return -1
|
from java.net import Socket
|
from java.net import InetAddress
|
from java.io import IOException
|
|
hostAddr = InetAddress.getByName(host)
|
i = 0
|
|
while 1:
|
i = i + 1
|
if i > 5:
|
port = -1
|
break
|
try:
|
s = Socket(hostAddr, port)
|
s.close()
|
port = port + 1
|
except IOException, ioe:
|
break
|
</script>
|
<return>port</return>
|
</sequence>
|
</function>
|
|
<function name="checkFileExists" scope="local">
|
<function-description>
|
Set testcase result to FAIL if file (as param) does not exist
|
</function-description>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAXServiceMachine">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="file" type="required">
|
<function-arg-description>
|
The file to check existence
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<call function="'GetEntry'">
|
{
|
'location' : STAF_REMOTE_HOSTNAME ,
|
'entry' : file ,
|
'attribute' : 'TYPE'
|
}
|
</call>
|
<if expr="RC == 48">
|
<sequence>
|
<tcstatus result="'fail'"/>
|
<message log="1" level="'Error'">
|
'ERROR : File %s does not exist' % file
|
</message>
|
</sequence>
|
</if>
|
</sequence>
|
</function>
|
|
<function name="checkFileNotExists" scope="local">
|
<function-description>
|
Set testcase result to FAIL if file (as param) exists
|
</function-description>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAXServiceMachine">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="file" type="required">
|
<function-arg-description>
|
The file to check absence
|
</function-arg-description>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<call function="'GetEntry'">
|
{
|
'location' : STAF_REMOTE_HOSTNAME ,
|
'entry' : file ,
|
'attribute' : 'TYPE'
|
}
|
</call>
|
<if expr="RC != 48">
|
<sequence>
|
<tcstatus result="'fail'"/>
|
<message log="1" level="'Error'">
|
'ERROR : File %s does not exist' % file
|
</message>
|
</sequence>
|
</if>
|
</sequence>
|
</function>
|
|
|
<function name="ldclt">
|
<function-prolog>
|
This function execute the ldclt tools.
|
</function-prolog>
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAF_CLIENT_HOSTNAME">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstanceHost"
|
type="optional"
|
default="DIRECTORY_INSTANCE_HOST">
|
<function-arg-description>
|
Directory server hostname or IP address
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstancePort"
|
type="optional"
|
default="DIRECTORY_INSTANCE_PORT">
|
<function-arg-description>
|
Directory server port number
|
</function-arg-description>
|
<function-arg-property name="type" value="Port number"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstanceDn"
|
type="optional"
|
default="DIRECTORY_INSTANCE_DN">
|
<function-arg-description>
|
Bind DN
|
</function-arg-description>
|
<function-arg-property name="type" value="DN"/>
|
</function-arg-def>
|
<function-arg-def name="dsInstancePswd"
|
type="optional"
|
default="DIRECTORY_INSTANCE_PSWD">
|
<function-arg-description>
|
Bind password
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="dsBaseDn"
|
type="optional"
|
default="DIRECTORY_INSTANCE_SFX">
|
<function-arg-description>
|
The baseDN for the LDAP operation
|
</function-arg-description>
|
<function-arg-property name="type" value="dn"/>
|
</function-arg-def>
|
<function-arg-def name="ldcltOptions"
|
type="required">
|
<function-arg-description>
|
The ldclt options
|
</function-arg-description>
|
<function-arg-property name="type" value="dn"/>
|
</function-arg-def>
|
<function-arg-def name="outputFile"
|
type="required">
|
<function-arg-description>
|
File containing output from the command
|
</function-arg-description>
|
<function-arg-property name="type" value="file"/>
|
</function-arg-def>
|
<function-arg-def name="outputPath"
|
type="optional"
|
default="remote.temp">
|
<function-arg-description>
|
Path containing outputFile
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="expectedRC" type="optional" default="0">
|
<function-arg-description>
|
Expected return code value. Default value is 0
|
Wildcard 'noCheck' to not check the RC
|
</function-arg-description>
|
<function-arg-property name="type" value="integer"/>
|
</function-arg-def>
|
<function-arg-def name="knownIssue"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
Known issue. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>
|
STAFCmdParamsList=[]
|
STAFCmdParams=''
|
|
STAFCmd='%s/bin/ldclt' % LDCLT_DIR
|
|
if dsInstanceHost:
|
STAFCmdParamsList.append('-h %s' % dsInstanceHost)
|
|
if dsInstanceHost:
|
STAFCmdParamsList.append('-p %s' % dsInstancePort)
|
|
if dsInstanceDn:
|
STAFCmdParamsList.append('-D "%s"' % dsInstanceDn)
|
|
if dsInstancePswd:
|
STAFCmdParamsList.append('-w %s' % dsInstancePswd)
|
|
if dsBaseDn:
|
STAFCmdParamsList.append('-b "%s"' % dsBaseDn)
|
|
STAFCmdParamsList.append(ldcltOptions)
|
|
STAFCmdParams=' '.join(STAFCmdParamsList)
|
|
ld = 'LD_LIBRARY_PATH='
|
env = ['%s' % ld]
|
</script>
|
|
<call function="'runCommand'" >
|
{
|
'name' : 'LDCLT Script' ,
|
'command' : STAFCmd ,
|
'arguments' : STAFCmdParams ,
|
'location' : location ,
|
'path' : LDCLT_DIR ,
|
'envCmd' : env ,
|
'outputFile' : '%s/%s' % (outputPath, outputFile) ,
|
'expectedRC' : expectedRC ,
|
'logStderr' : True ,
|
'knownIssue' : knownIssue
|
}
|
</call>
|
|
<return>
|
STAXResult
|
</return>
|
</sequence>
|
</function>
|
|
<!-- This function uses make ldif to generate LDIF data files -->
|
<function name="MakeALdcltTemplate">
|
<function-prolog>
|
This function makes a ldclt template file
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="templateFile" type="required">
|
<function-arg-description>
|
Template file name
|
</function-arg-description>
|
<function-arg-property name="type" value="filename"/>
|
</function-arg-def>
|
<function-arg-def name="templateLocation"
|
type="optional"
|
default="STAF_CLIENT_HOSTNAME">
|
<function-arg-description>
|
Template file location
|
</function-arg-description>
|
<function-arg-property name="type" value="filename"/>
|
</function-arg-def>
|
<function-arg-def name="extraLine" type="optional">
|
<function-arg-description>
|
Extra line to add to the mkae-ldif template
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<!-- Build the import task configuration object -->
|
<script>
|
ldifLines=[]
|
|
ldifLines.append('objectClass: top')
|
ldifLines.append('objectClass: person')
|
ldifLines.append('objectClass: organizationalPerson')
|
ldifLines.append('objectClass: inetOrgPerson')
|
ldifLines.append('givenName: [A=RNDFROMFILE(%s/ldap/lib/names/Firstname.txt)]' % LDCLT_DIR)
|
ldifLines.append('sn: [B=RNDFROMFILE(%s/ldap/lib/names/Lastname.txt)]' % LDCLT_DIR)
|
ldifLines.append('employeeNumber: [C]')
|
ldifLines.append('cn: [A] [B] [C]')
|
ldifLines.append('mail: user.[C]@example.com')
|
ldifLines.append('initials: [A][B]')
|
ldifLines.append('homePhone: 0[RNDN(1;5;1)] [RNDN(0;99;2)] [RNDN(0;99;2)] [RNDN(0;99;2)] [RNDN(0;99;2)]')
|
ldifLines.append('mobile: 06 [RNDN(0;99;2)] [RNDN(0;99;2)] [RNDN(0;99;2)] [RNDN(0;99;2)]')
|
ldifLines.append('street: [D=RNDFROMFILE(%s/ldap/lib/names/Firstname.txt)]' % LDCLT_DIR)
|
ldifLines.append('l: [E=RNDFROMFILE(%s/ldap/lib/names/Lastname.txt)]' % LDCLT_DIR)
|
ldifLines.append('st: [F=RNDFROMFILE(%s/ldap/lib/names/Firstname.txt)]' % LDCLT_DIR)
|
ldifLines.append('postalCode: [G=RNDN(0;80000;5)]')
|
ldifLines.append('postalAddress: [A] [B] [C][D][E], [F] [G]')
|
ldifLines.append('telephoneNumber: 0[RNDN(1;5;1)] [RNDN(0;99;2)] [RNDN(0;99;2)] [RNDN(0;99;2)] [RNDN(0;99;2)]')
|
ldifLines.append('description: This is the description for user.[C].')
|
</script>
|
|
<!-- Write out the make-ldif template file -->
|
<script>
|
tmpTemplateFile = '%s/tempLdcltTemplateFile' % local.temp
|
outfile = open(tmpTemplateFile,"w")
|
|
for line in ldifLines:
|
outfile.write("%s\n" % line)
|
|
outfile.close()
|
</script>
|
<script>
|
STAXCode=RC
|
STAXReason=STAXResult
|
</script>
|
<if expr="STAXCode != 0">
|
<sequence>
|
<message level="'error'">
|
'creation of a ldclt template failed (Code=%s,Reason=%s).' % (STAXCode,STAXReason)
|
</message>
|
</sequence>
|
</if>
|
<call function="'checktestRC'">
|
{ 'returncode' : STAXCode ,
|
'result' : STAXReason }
|
</call>
|
|
<call function="'copyFile'">
|
{ 'location' : STAXServiceMachine,
|
'srcfile' : tmpTemplateFile,
|
'destfile' : templateFile,
|
'remotehost' : templateLocation }
|
</call>
|
|
<call function="'checktestRC'">
|
{
|
'returncode' : RC ,
|
'result' : STAXResult
|
}
|
</call>
|
|
<return>[RC, STAXResult]</return>
|
|
</sequence>
|
</function>
|
|
|
<!-- This function parses an ldif entry -->
|
<function name="parseLdifEntry">
|
<function-prolog>
|
This function parses an ldif entry and returns a dictionary, e.g.:
|
{'dn':['o=example'],'objectclass':['top','organization'],'o':['example']}
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="ldifEntry" type="required">
|
<function-arg-description>
|
Ldif entry to parse (single string).
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
parsedEntry = {}
|
prevAttr = None
|
prevVal = None
|
|
for line in ldifEntry.splitlines():
|
notBlank = (len(line.strip()) != 0)
|
if notBlank and (not line.startswith(' ')):
|
# line corresponds to an attr:val
|
attr = line[:line.find(':')].strip().lower()
|
val = line[line.find(':') + 1:].lstrip()
|
if val.startswith(':'):
|
val = val[1:].lstrip()
|
if attr == 'objectclass':
|
val = val.lower()
|
|
if not (attr in parsedEntry.keys()):
|
# This is the first occurrence of this attr
|
parsedEntry[attr] = [val]
|
else:
|
# There is already some value for this attr
|
parsedEntry[attr].append(val)
|
|
prevAttr = attr
|
prevVal = val
|
elif notBlank:
|
# line corresponds to a trailing value
|
parsedEntry[prevAttr].remove(prevVal)
|
val = prevVal + line.lstrip()
|
parsedEntry[prevAttr].append(val)
|
prevVal = val
|
</script>
|
|
<return> parsedEntry </return>
|
</sequence>
|
</function>
|
|
|
<!-- This function parses several ldif entries -->
|
<function name="parseLdifEntries">
|
<function-prolog>
|
This function parses several ldif entries and returns a list of
|
dictionaries such as those produced by parseLdifEntry
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="ldifEntries" type="required">
|
<function-arg-description>
|
Ldif entries to parse (single string).
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
parsedEntryList = []
|
ldifEntryList = []
|
ldifEntryLines = []
|
ldifEntry = None
|
|
for line in ldifEntries.splitlines():
|
notBlank = (len(line.strip()) != 0)
|
if notBlank:
|
ldifEntryLines.append(line)
|
else:
|
if len(ldifEntryLines) != 0:
|
ldifEntry = '\n'.join(ldifEntryLines)
|
ldifEntryList.append(ldifEntry)
|
ldifEntryLines = []
|
|
if len(ldifEntryLines) != 0:
|
ldifEntry = '\n'.join(ldifEntryLines)
|
ldifEntryList.append(ldifEntry)
|
ldifEntryLines = []
|
</script>
|
|
<if expr="len(ldifEntryList) != 0">
|
<iterate var="entryToParse" in="ldifEntryList">
|
<sequence>
|
<call function="'parseLdifEntry'">
|
{ 'ldifEntry' : entryToParse }
|
</call>
|
<script>
|
parsedEntryList.append(STAXResult)
|
</script>
|
</sequence>
|
</iterate>
|
</if>
|
|
<return> parsedEntryList </return>
|
</sequence>
|
</function>
|
|
|
|
<!-- This function parses an ldif change -->
|
<function name="parseLdifChange">
|
<function-prolog>
|
This function parses an ldif change and returns a list, e.g.:
|
[ ['replace','l','London'], ['add','description','This is a test'] ]
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="ldifChange" type="required">
|
<function-arg-description>
|
Ldif change to parse (single string).
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
</function-map-args>
|
<sequence>
|
<script>
|
parsedChange = []
|
mod = []
|
prevAttr = None
|
prevVal = None
|
|
for line in ldifChange.splitlines():
|
notBlank = (len(line.strip()) != 0)
|
if notBlank and (not line.startswith(' ')) and (not line.startswith('-')):
|
# line corresponds to an attr:val
|
attr = line[:line.find(':')].strip().lower()
|
val = line[line.find(':') + 1:].lstrip()
|
|
if val.startswith(':'):
|
val = val[1:].lstrip()
|
|
if attr == 'objectclass':
|
val = val.lower()
|
|
if (prevVal != None) and (attr == prevVal.lower()):
|
# attr represents indeed an attribute type, so we may assume the
|
# mod already has [mod_type,attr_type]
|
mod.append(val)
|
else:
|
# attr represents the mod_type, and val the attr_type
|
mod.append(attr)
|
mod.append(val.lower())
|
|
prevAttr = attr
|
prevVal = val
|
elif notBlank and line.startswith(' '):
|
# line corresponds to a trailing value
|
mod.remove(prevVal)
|
val = prevVal + line.lstrip()
|
mod.append(val)
|
prevVal = val
|
else:
|
# line is empty or line starts with '-'; this means that
|
# the mod is complete, so we can add it to the parsedChange list
|
parsedChange.append(mod)
|
mod = []
|
|
if len(mod) != 0:
|
# add the trailing mod to the parsedChange list
|
parsedChange.append(mod)
|
</script>
|
|
<return> parsedChange </return>
|
</sequence>
|
</function>
|
|
<!-- This function checks the content of an external changelog entry -->
|
<function name="checkChangelogEntry">
|
<function-prolog>
|
This function checks the content of an external changelog entry
|
</function-prolog>
|
|
<function-map-args>
|
<function-arg-def name="location"
|
type="optional"
|
default="STAF_REMOTE_HOSTNAME">
|
<function-arg-description>
|
Location of target host
|
</function-arg-description>
|
<function-arg-property name="type" value="hostname"/>
|
</function-arg-def>
|
<function-arg-def name="dsPath"
|
type="optional"
|
default="'%s/%s' % (DIRECTORY_INSTANCE_BIN,OPENDSNAME)">
|
<function-arg-description>
|
Pathname to installation root
|
</function-arg-description>
|
<function-arg-property name="type" value="filepath"/>
|
</function-arg-def>
|
<function-arg-def name="changelogEntry" type="required">
|
<function-arg-description>
|
External changelog entry (as an output of parseLdifEntry)
|
</function-arg-description>
|
<function-arg-property name="type" value="dictionary"/>
|
</function-arg-def>
|
<function-arg-def name="targetDN" type="required">
|
<function-arg-description>
|
DN of the target entry for the change
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="changeType" type="required">
|
<function-arg-description>
|
Change type (e.g. add, delete, modify)
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="changeTime"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
Change time
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="changeNumber"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
Changenumber (only for changelog draft-compatible mode)
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="replicationCSN"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
Replication CSN
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="targetEntryUUID"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
Target entry uuid
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="replicaIdentifier"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
Replica Identifier
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="newRDN"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
NewRDN
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="deleteOldRDN"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
DeleteOldRDN
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="newSuperior"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
NewSuperior
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="changes"
|
type="optional"
|
default="None">
|
<function-arg-description>
|
Changes. If changetype == add, changes should be a map, e.g.:
|
{'dn':['o=example'],'objectclass':['top','organization'],'o':['example']}
|
If changetype == modify, changes should be a list, e.g.:
|
[ ['replace','l','London'], ['add','description','This is a test'] ]
|
</function-arg-description>
|
<function-arg-property name="type" value="string"/>
|
</function-arg-def>
|
<function-arg-def name="knownIssue" type="optional" default="None">
|
<function-arg-description>
|
Known issue. Corresponds to an issue number.
|
</function-arg-description>
|
<function-arg-property name="type" value="string" />
|
</function-arg-def>
|
</function-map-args>
|
|
<sequence>
|
<script>
|
myLocation = location
|
myPath = dsPath
|
|
# Mandatory attributes in a changeLogEntry
|
ecl_DN = changelogEntry['dn'][0]
|
ecl_targetDN = changelogEntry['targetdn'][0]
|
ecl_changeType = changelogEntry['changetype'][0]
|
ecl_changeTime = changelogEntry['changetime'][0]
|
ecl_changeNumber = changelogEntry['changenumber'][0]
|
|
# Optional attributes
|
ecl_replicationCSN = None
|
ecl_replicaIdentifier = None
|
ecl_targetEntryUUID = None
|
ecl_newRDN = None
|
ecl_deleteOldRDN = None
|
ecl_newSuperior = None
|
ecl_changes = None
|
|
if 'replicationcsn' in changelogEntry.keys():
|
ecl_replicationCSN = changelogEntry['replicationcsn'][0]
|
if 'replicaidentifier' in changelogEntry.keys():
|
ecl_replicaIdentifier = changelogEntry['replicaidentifier'][0]
|
if 'targetentryuuid' in changelogEntry.keys():
|
ecl_targetEntryUUID = changelogEntry['targetentryuuid'][0]
|
if 'newrdn' in changelogEntry.keys():
|
ecl_newRDN = changelogEntry['newrdn'][0]
|
if 'deleteoldrdn' in changelogEntry.keys():
|
ecl_deleteOldRDN = changelogEntry['deleteoldrdn'][0]
|
if 'newsuperior' in changelogEntry.keys():
|
ecl_newSuperior = changelogEntry['newsuperior'][0]
|
if 'changes' in changelogEntry.keys():
|
ecl_changes = changelogEntry['changes'][0]
|
</script>
|
|
<message>
|
'checkChangelogEntry: Checking changelog entry %s against expected \
|
values' % ecl_DN
|
</message>
|
|
<message>
|
'checkChangelogEntry: Checking targetDN'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_targetDN,
|
'expectedString' : targetDN,
|
'searchType' : 'exact-case-insensitive'
|
}
|
</call>
|
|
<message>
|
'checkChangelogEntry: Checking changeType'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_changeType,
|
'expectedString' : changeType,
|
'searchType' : 'exact-case-insensitive'
|
}
|
</call>
|
|
<if expr="changeTime">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking changeTime'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_changeTime,
|
'expectedString' : changeTime,
|
'searchType' : 'exact-case-insensitive'
|
}
|
</call>
|
</sequence>
|
</if>
|
|
<if expr="changeNumber">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking changeNumber'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_changeNumber,
|
'expectedString' : changeNumber,
|
'searchType' : 'exact-case-sensitive'
|
}
|
</call>
|
</sequence>
|
</if>
|
|
<if expr="replicationCSN">
|
<if expr="ecl_replicationCSN">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking replicationCSN'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_replicationCSN,
|
'expectedString' : replicationCSN,
|
'searchType' : 'exact-case-insensitive'
|
}
|
</call>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No replicationCSN could be found in the changelog entry'
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
<if expr="replicaIdentifier">
|
<if expr="ecl_replicaIdentifier">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking replicaIdentifier'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_replicaIdentifier,
|
'expectedString' : replicaIdentifier,
|
'searchType' : 'exact-case-sensitive'
|
}
|
</call>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No replicaIdentifier could be found in the changelog entry'
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
<if expr="targetEntryUUID">
|
<if expr="ecl_targetEntryUUID">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking targetEntryUUID'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_targetEntryUUID,
|
'expectedString' : targetEntryUUID,
|
'searchType' : 'exact-case-insensitive'
|
}
|
</call>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No targetEntryUUID could be found in the changelog entry'
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
<if expr="newRDN">
|
<if expr="ecl_newRDN">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking newRDN'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_newRDN,
|
'expectedString' : newRDN,
|
'searchType' : 'exact-case-insensitive'
|
}
|
</call>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No newRDN could be found in the changelog entry'
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
<if expr="deleteOldRDN">
|
<if expr="ecl_deleteOldRDN">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking deleteOldRDN'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_deleteOldRDN,
|
'expectedString' : deleteOldRDN,
|
'searchType' : 'exact-case-sensitive'
|
}
|
</call>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No deleteOldRDN could be found in the changelog entry'
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
<if expr="newSuperior">
|
<if expr="ecl_newSuperior">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking newSuperior'
|
</message>
|
<call function="'searchString'">
|
{ 'returnString' : ecl_newSuperior,
|
'expectedString' : newSuperior,
|
'searchType' : 'exact-case-insensitive'
|
}
|
</call>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No newSuperior could be found in the changelog entry'
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
<if expr="changes">
|
<if expr="ecl_changes">
|
<sequence>
|
<!-- Decode the changes that are encoded in base64 -->
|
<message>
|
'checkChangelogEntry: Decode external changelog entry changes'
|
</message>
|
<call function="'Base64WithScript'">
|
{ 'location' : myLocation,
|
'dsPath' : myPath,
|
'subcommand' : 'decode',
|
'encodedData' : ecl_changes
|
}
|
</call>
|
<!-- STAXResult is not always a list-->
|
<script>
|
try:
|
decodeRC, decodedChanges = STAXResult[0]
|
except AttributeError, details:
|
decodedChanges = 'AttributeError: can not parse STAXResult %s' \
|
% details
|
decodeRC = '1'
|
</script>
|
<message>
|
'checkChangelogEntry: Decoded changes:\n%s' % decodedChanges
|
</message>
|
|
<message>
|
'checkChangelogEntry: Checking changes'
|
</message>
|
<if expr="decodeRC == 0 and changeType == 'add'">
|
<!-- If changetype:add, the changes look like a sequence of
|
! attribute:value, so we may parse them as an ldif entry -->
|
<sequence>
|
<call function="'parseLdifEntry'">
|
{ 'ldifEntry' : decodedChanges }
|
</call>
|
<script>
|
ecl_changesMap = STAXResult
|
</script>
|
<message>
|
'Parsed changelog entry changes: \n%s' % ecl_changesMap
|
</message>
|
<iterate var="attr" in="changes.keys()">
|
<sequence>
|
<script>
|
valueList = changes[attr]
|
ecl_valueList = None
|
|
if attr in ecl_changesMap.keys():
|
ecl_valueList = ecl_changesMap[attr]
|
ecl_valueList.sort()
|
valueList.sort()
|
</script>
|
<if expr="ecl_valueList != None">
|
<sequence>
|
<message>
|
'checkChangelogEntry: Checking changes: %s' % attr
|
</message>
|
<if expr="valueList == ecl_valueList">
|
<message>
|
'Found expected values in changes: %s' % valueList
|
</message>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'Expected values %s could not be found in %s' \
|
% (valueList, ecl_valueList)
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No %s could be found in the changes' % attr
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</iterate>
|
</sequence>
|
|
<elseif expr="decodeRC == 0">
|
<!-- If changetype:modify, the changes look like a sequence of
|
! mod_type:attribute
|
! attribute:value
|
! so we need to treat them differently -->
|
<sequence>
|
<call function="'parseLdifChange'">
|
{ 'ldifChange' : decodedChanges }
|
</call>
|
<script>
|
ecl_changesList = STAXResult
|
</script>
|
<message>
|
'Parsed changelog entry changes: \n%s' % ecl_changesList
|
</message>
|
<iterate var="mod" in="changes">
|
<sequence>
|
<script>
|
mod_type = mod[0]
|
mod_attr = mod[1]
|
mod_val = None
|
if len(mod) == 3:
|
mod_val = mod[2]
|
</script>
|
<message>
|
'checkChangelogEntry: Checking changes: %s' % mod
|
</message>
|
<if expr="mod in ecl_changesList">
|
<message>
|
'Found expected change:\n %s: %s\n %s: %s\n' \
|
% (mod_type, mod_attr, mod_attr, mod_val)
|
</message>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'Expected change %s could not be found in %s'\
|
% (mod, ecl_changesList)
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</sequence>
|
</iterate>
|
</sequence>
|
</elseif>
|
</if>
|
|
</sequence>
|
<else>
|
<sequence>
|
<message log="1" level="'Error'">
|
'No changes could be found in the changelog entry'
|
</message>
|
<call function="'testFailed'"/>
|
</sequence>
|
</else>
|
</if>
|
</if>
|
|
</sequence>
|
</function>
|
</stax>
|