summaryrefslogtreecommitdiffstats
path: root/test/test-fixed-point-parameter/Main.py
diff options
context:
space:
mode:
authorDavid Wagner <david.wagner@intel.com>2014-06-25 11:36:45 +0200
committerDavid Wagner <david.wagner@intel.com>2014-06-25 11:36:45 +0200
commitbf2f826f20b355f579ab8967ec38b794bbb2a868 (patch)
treee19fcfd40bca485acee5735a0a132f2575fd180a /test/test-fixed-point-parameter/Main.py
parentfb474cce72215e432308264ada9c5a7197a21125 (diff)
parent0fbd572ff8095725b47a69f08134d5efbc1336e8 (diff)
downloadexternal_parameter-framework-bf2f826f20b355f579ab8967ec38b794bbb2a868.zip
external_parameter-framework-bf2f826f20b355f579ab8967ec38b794bbb2a868.tar.gz
external_parameter-framework-bf2f826f20b355f579ab8967ec38b794bbb2a868.tar.bz2
Merge pull request #9 from 01org/dev-features
Realign from internal tree
Diffstat (limited to 'test/test-fixed-point-parameter/Main.py')
-rwxr-xr-xtest/test-fixed-point-parameter/Main.py240
1 files changed, 240 insertions, 0 deletions
diff --git a/test/test-fixed-point-parameter/Main.py b/test/test-fixed-point-parameter/Main.py
new file mode 100755
index 0000000..09cff28
--- /dev/null
+++ b/test/test-fixed-point-parameter/Main.py
@@ -0,0 +1,240 @@
+#!/usr/bin/python2.7
+#
+# Copyright (c) 2014, 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 sys
+import subprocess
+from decimal import Decimal
+
+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, integral, fractional):
+ self._pfwClient = pfwClient
+ self._paramPath = '/Test/test/q%d.%d' % (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 ** -fractional
+ self._shouldBreak = [
+ Decimal(self._lowerAllowedBound) - Decimal(bigValue),
+ Decimal(self._upperAllowedBound) + Decimal(bigValue),
+ Decimal(self._lowerAllowedBound) - Decimal(littleValue),
+ Decimal(self._upperAllowedBound) + Decimal(littleValue)
+ ]
+
+
+ def run(self):
+ """ Runs the test suite for a given Qn.m number
+ """
+ for value in self._shouldWork:
+ print('Testing %s for %s' % (value, self._paramPath))
+ value, success = self.checkBounds(value)
+ if not success:
+ print('Bound ERROR for %s' % self._paramPath)
+ continue
+
+ value, success = self.checkSanity(value)
+ if not success:
+ print('Sanity ERROR %s' % self._paramPath)
+ continue
+
+ value, success = self.checkConsistency(value)
+ if not success:
+ print('Consistency ERROR %s' % self._paramPath)
+ continue
+
+ value, success = self.checkBijectivity(value)
+ if not success:
+ print('Bijectivity ERROR %s' % self._paramPath)
+ continue
+
+ for value in self._shouldBreak:
+ print('Testing invalid value %s for %s' % (value, self._paramPath))
+ value, success = self.checkBounds(value)
+ if success:
+ print("ERROR: This test should have failed but it has not")
+
+ 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
+ """
+ returnCode = self._pfwClient.set(self._paramPath, str(valueToSet))
+ if returnCode != 0:
+ return (valueToSet, False)
+
+ return (valueToSet, True)
+
+
+ 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
+ """
+ returnCode = pfw.set(self._paramPath, valuePreviouslyGotten)
+ if returnCode != 0:
+ return valuePreviouslyGotten, False
+
+ return valuePreviouslyGotten, True
+
+ 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._address = 'localhost'
+ self._port = '5066'
+ self._testPlatformPort = '5063'
+ self._pathToExec = 'remote-process_host'
+ self._configPath = configPath
+
+ def __enter__(self):
+ # launch test platform in deamon mode
+ subprocess.call(['test-platform_host', '-d', self._configPath, self._testPlatformPort])
+ subprocess.call([self._pathToExec, self._address, self._testPlatformPort, 'start'])
+ self._callCommand(['setTuningMode', 'on'])
+ return self
+
+ def __exit__(self, type, value, traceback):
+ subprocess.call([self._pathToExec, self._address, self._testPlatformPort, 'exit'])
+
+ def _callCommand(self, commandList):
+ shellCommand = [self._pathToExec, self._address, self._port]
+ shellCommand.extend(commandList)
+ # pipes are used to redirect the command output to a variable
+ subProc = subprocess.Popen(shellCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ commandOutPut, _ = subProc.communicate()
+ returnCode = subProc.returncode
+ return commandOutPut, returnCode
+
+ def set(self, parameter, value):
+ print('set %s <--- %s' % (parameter, value))
+ (returnValue, returnCode) = self._callCommand(['setParameter', parameter, value])
+ return returnCode
+
+ def get(self, parameter):
+ (returnValue, _) = self._callCommand(['getParameter', parameter])
+ print('get %s ---> %s' % (parameter, returnValue.strip()))
+ return returnValue.strip()
+
+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.
+ configPath = './ParameterFrameworkConfiguration.xml'
+
+ with PfwClient(configPath) as pfw:
+ for integral in range(0, 31):
+ for fractional in range (0, 31 - integral):
+ tester = FixedPointTester(pfw, integral, fractional)
+ tester.run()
+