You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
9.1 KiB
246 lines
9.1 KiB
#!/usr/bin/python2.7
|
|
#
|
|
# Copyright (c) 2014-2015, Intel Corporation
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without modification,
|
|
# are permitted provided that the following conditions are met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
|
# list of conditions and the following disclaimer.
|
|
#
|
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
# this list of conditions and the following disclaimer in the documentation and/or
|
|
# other materials provided with the distribution.
|
|
#
|
|
# 3. Neither the name of the copyright holder nor the names of its contributors
|
|
# may be used to endorse or promote products derived from this software without
|
|
# specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
import PyPfw
|
|
|
|
import logging
|
|
from decimal import Decimal
|
|
from math import log10
|
|
|
|
class PfwLogger(PyPfw.ILogger):
|
|
def __init__(self):
|
|
super(PfwLogger, self).__init__()
|
|
self.__logger = logging.root.getChild("parameter-framework")
|
|
|
|
def info(self, message):
|
|
self.__logger.info(message)
|
|
|
|
def warning(self, message):
|
|
self.__logger.warning(message)
|
|
|
|
class FixedPointTester():
|
|
""" Made for testing a particular Qn.m number
|
|
|
|
As a convention, we use:
|
|
* n is the fractional part
|
|
* m is the integral part
|
|
|
|
This class computes several specific numbers for a given Qn.m number.
|
|
|
|
For each of those numbers, we run 4 checks:
|
|
* Bound check
|
|
* Sanity check
|
|
* Consistency check
|
|
* Bijectivity check
|
|
Which are documented below.
|
|
"""
|
|
def __init__(self, pfwClient, size, integral, fractional):
|
|
self._pfwClient = pfwClient
|
|
self._paramPath = '/Test/test/%d/q%d.%d' % (size, integral, fractional)
|
|
|
|
# quantum is the step we have between two numbers
|
|
# encoded in Qn.m format
|
|
self._quantum = 2 ** -fractional
|
|
|
|
# The maximum value we can encode for a given Qn.m.
|
|
# Since we also need to encode the 0, we have one quantum missing on
|
|
# the positive maximum
|
|
self._upperAllowedBound = (2 ** integral) - self._quantum
|
|
|
|
# The minimum value that we can encode for a given Qn.m.
|
|
# This one does not need a quantum substraction since we already did
|
|
# that on the maximum
|
|
self._lowerAllowedBound = -(2 ** integral)
|
|
|
|
self._shouldWork = [
|
|
Decimal(0),
|
|
Decimal(self._lowerAllowedBound),
|
|
Decimal(self._upperAllowedBound)
|
|
]
|
|
|
|
# bigValue is to be sure a value far out of range is refused
|
|
bigValue = (2 * self._quantum)
|
|
# little is to be sure a value just out of range is refused
|
|
littleValue = 10 ** -(int(fractional * log10(2)))
|
|
self._shouldBreak = [
|
|
Decimal(self._lowerAllowedBound) - Decimal(bigValue),
|
|
Decimal(self._upperAllowedBound) + Decimal(bigValue),
|
|
Decimal(self._lowerAllowedBound) - Decimal(littleValue),
|
|
Decimal(self._upperAllowedBound) + Decimal(littleValue)
|
|
]
|
|
|
|
self._chainingTests = [
|
|
('Bound', self.checkBounds),
|
|
('Sanity', self.checkSanity),
|
|
('Consistency', self.checkConsistency),
|
|
('Bijectivity', self.checkBijectivity)]
|
|
|
|
|
|
def run(self):
|
|
""" Runs the test suite for a given Qn.m number
|
|
"""
|
|
|
|
runSuccess = True
|
|
|
|
for value in self._shouldWork:
|
|
value = value.normalize()
|
|
print('Testing %s for %s' % (value, self._paramPath))
|
|
|
|
for testName, testFunc in self._chainingTests:
|
|
value, success = testFunc(value)
|
|
if not success:
|
|
runSuccess = False
|
|
print("%s ERROR for %s" % (testName, self._paramPath))
|
|
break
|
|
|
|
for value in self._shouldBreak:
|
|
value = value.normalize()
|
|
print('Testing invalid value %s for %s' % (value, self._paramPath))
|
|
value, success = self.checkBounds(value)
|
|
if success:
|
|
runSuccess = False
|
|
print("ERROR: This test should have failed but it has not")
|
|
|
|
return runSuccess
|
|
|
|
def checkBounds(self, valueToSet):
|
|
""" Checks if we are able to set valueToSet via the parameter-framework
|
|
|
|
valueToSet -- the value we are trying to set
|
|
|
|
returns: the value we are trying to set
|
|
returns: True if we are able to set, False otherwise
|
|
"""
|
|
(success, errorMsg) = self._pfwClient.set(self._paramPath, str(valueToSet))
|
|
|
|
return valueToSet, success
|
|
|
|
|
|
def checkSanity(self, valuePreviouslySet):
|
|
""" Checks if the value we get is still approximately the same
|
|
as we attempted to set. The value can have a slight round error which
|
|
is tolerated.
|
|
|
|
valuePreviouslySet -- the value we had previously set
|
|
|
|
returns: the value the parameter-framework returns us after the get
|
|
returns: True if we are able to set, False otherwise
|
|
"""
|
|
firstGet = self._pfwClient.get(self._paramPath)
|
|
|
|
try:
|
|
returnValue = Decimal(firstGet)
|
|
except ValueError:
|
|
print("ERROR: Can't convert %s to a decimal" % firstGet)
|
|
return firstGet, False
|
|
|
|
upperAllowedValue = Decimal(valuePreviouslySet) + (Decimal(self._quantum) / Decimal(2))
|
|
lowerAllowedValue = Decimal(valuePreviouslySet) - (Decimal(self._quantum) / Decimal(2))
|
|
|
|
if not (lowerAllowedValue <= returnValue <= upperAllowedValue):
|
|
print('%s <= %s <= %s is not true' %
|
|
(lowerAllowedValue, returnValue, upperAllowedValue))
|
|
return firstGet, False
|
|
|
|
return firstGet, True
|
|
|
|
def checkConsistency(self, valuePreviouslyGotten):
|
|
""" Checks if we are able to set the value that the parameter framework
|
|
just returned to us.
|
|
|
|
valuePreviouslyGotten -- the value we are trying to set
|
|
|
|
valueToSet -- the value we are trying to set
|
|
returns: True if we are able to set, False otherwise
|
|
"""
|
|
(success, errorMsg) = pfw.set(self._paramPath, valuePreviouslyGotten)
|
|
|
|
return valuePreviouslyGotten, success
|
|
|
|
def checkBijectivity(self, valuePreviouslySet):
|
|
""" Checks that the second get value is strictly equivalent to the
|
|
consistency set. This ensures that the parameter-framework behaves as
|
|
expected.
|
|
|
|
valuePreviouslySet -- the value we had previously set
|
|
|
|
returns: value the parameter-framework returns us after the second get
|
|
returns: True if we are able to set, False otherwise
|
|
"""
|
|
secondGet = pfw.get(self._paramPath)
|
|
|
|
if secondGet != valuePreviouslySet:
|
|
return secondGet, False
|
|
|
|
return secondGet, True
|
|
|
|
class PfwClient():
|
|
|
|
def __init__(self, configPath):
|
|
self._instance = PyPfw.ParameterFramework(configPath)
|
|
|
|
self._logger = PfwLogger()
|
|
self._instance.setLogger(self._logger)
|
|
# Disable the remote interface because we don't need it and it might
|
|
# get in the way (e.g. the port is already in use)
|
|
self._instance.setForceNoRemoteInterface(True)
|
|
|
|
self._instance.start()
|
|
self._instance.setTuningMode(True)
|
|
|
|
def set(self, parameter, value):
|
|
print('set %s <--- %s' % (parameter, value))
|
|
(success, _, errorMsg) = self._instance.accessParameterValue(parameter, str(value), True)
|
|
return success, errorMsg
|
|
|
|
def get(self, parameter):
|
|
(success, value, errorMsg) = self._instance.accessParameterValue(parameter, "", False)
|
|
if not success:
|
|
raise Exception("A getParameter failed, which is unexpected. The"
|
|
"parameter-framework answered:\n%s" % errorMsg)
|
|
|
|
print('get %s ---> %s' % (parameter, value))
|
|
return value
|
|
|
|
if __name__ == '__main__':
|
|
# It is necessary to add a ./ in front of the path, otherwise the parameter-framework
|
|
# does not recognize the string as a path.
|
|
pfw = PfwClient('./ParameterFrameworkConfiguration.xml')
|
|
|
|
success = True
|
|
|
|
for size in [8, 16, 32]:
|
|
for integral in range(0, size):
|
|
for fractional in range (0, size - integral):
|
|
tester = FixedPointTester(pfw, size, integral, fractional)
|
|
success = tester.run() and success
|
|
|
|
exit(0 if success else 1)
|