Unit Testing framework based on http://cpputest.github.io/

CppUTest

Where to find more information

Getting test reports on the console

You may need to tailor the file src/Platforms/mbed/UtestPlatform.cpp to your needs. In particular, if you want console output, you might want to look at the function PlatformSpecificPutchar().

Quick introduction (some code!)

To write your first test, all you need is a new cpp file with a TEST_GROUP and a TEST, like:

#include "CppUTest/TestHarness.h"

TEST_GROUP(FirstTestGroup)
{
};

TEST(FirstTestGroup, FirstTest)
{
   FAIL("Fail me!");
}

This test will fail.

You can add new tests to the test group by just writing more tests in the file, like this:

TEST(FirstTestGroup, SecondTest)
{
   STRCMP_EQUAL("hello", "world");
   LONGS_EQUAL(1, 2);
   CHECK(false);
}

You do need to trigger the tests from somewhere in your program. It could look something like:

#include "CppUTest/TestRegistry.h"
#include "CppUTest/CommandLineTestRunner.h"

int main(int ac, char** av)
{
    ....
    unsigned failureCount = 0;
    {
        ConsoleTestOutput output;
        CommandLineTestRunner runner(ac, av, &output, TestRegistry::getCurrentRegistry());
        failureCount = runner.runAllTestsMain();
    }

    if (failureCount == 0) {
        console.printf("PASSED\r\n");
    }
    ...
}

For more information, We’d recommend to read the manual or, even better, check some existing tests such as SimpleStringTest or (a bit more complicated) MemoryLeakDetectorTest or the mocking tests or just check out the Cheat Sheet.

Committer:
Rohit Grover
Date:
Tue Jun 17 15:52:54 2014 +0100
Revision:
1:4769360130ed
Parent:
0:0b799af9d58e
updating to the latest version of cppUtest; tested against nordic's m-kit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Rohit Grover 1:4769360130ed 1 /*
Rohit Grover 1:4769360130ed 2 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
Rohit Grover 1:4769360130ed 3 * All rights reserved.
Rohit Grover 1:4769360130ed 4 *
Rohit Grover 1:4769360130ed 5 * Redistribution and use in source and binary forms, with or without
Rohit Grover 1:4769360130ed 6 * modification, are permitted provided that the following conditions are met:
Rohit Grover 1:4769360130ed 7 * * Redistributions of source code must retain the above copyright
Rohit Grover 1:4769360130ed 8 * notice, this list of conditions and the following disclaimer.
Rohit Grover 1:4769360130ed 9 * * Redistributions in binary form must reproduce the above copyright
Rohit Grover 1:4769360130ed 10 * notice, this list of conditions and the following disclaimer in the
Rohit Grover 1:4769360130ed 11 * documentation and/or other materials provided with the distribution.
Rohit Grover 1:4769360130ed 12 * * Neither the name of the <organization> nor the
Rohit Grover 1:4769360130ed 13 * names of its contributors may be used to endorse or promote products
Rohit Grover 1:4769360130ed 14 * derived from this software without specific prior written permission.
Rohit Grover 1:4769360130ed 15 *
Rohit Grover 1:4769360130ed 16 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
Rohit Grover 1:4769360130ed 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Rohit Grover 1:4769360130ed 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Rohit Grover 1:4769360130ed 19 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
Rohit Grover 1:4769360130ed 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Rohit Grover 1:4769360130ed 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Rohit Grover 1:4769360130ed 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Rohit Grover 1:4769360130ed 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Rohit Grover 1:4769360130ed 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Rohit Grover 1:4769360130ed 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Rohit Grover 1:4769360130ed 26 */
Rohit Grover 1:4769360130ed 27
Rohit Grover 1:4769360130ed 28 #include "CppUTest/TestHarness.h"
Rohit Grover 1:4769360130ed 29 #include "CppUTest/TestFailure.h"
Rohit Grover 1:4769360130ed 30 #include "CppUTest/TestOutput.h"
Rohit Grover 1:4769360130ed 31 #include "CppUTest/PlatformSpecificFunctions.h"
Rohit Grover 1:4769360130ed 32
Rohit Grover 1:4769360130ed 33 static SimpleString removeAllPrintableCharactersFrom(const SimpleString& str)
Rohit Grover 1:4769360130ed 34 {
Rohit Grover 1:4769360130ed 35 size_t bufferSize = str.size()+1;
Rohit Grover 1:4769360130ed 36 char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
Rohit Grover 1:4769360130ed 37 str.copyToBuffer(buffer, bufferSize);
Rohit Grover 1:4769360130ed 38
Rohit Grover 1:4769360130ed 39 for (size_t i = 0; i < bufferSize-1; i++)
Rohit Grover 1:4769360130ed 40 if (buffer[i] != '\t' && buffer[i] != '\n')
Rohit Grover 1:4769360130ed 41 buffer[i] = ' ';
Rohit Grover 1:4769360130ed 42
Rohit Grover 1:4769360130ed 43 SimpleString result(buffer);
Rohit Grover 1:4769360130ed 44 PlatformSpecificFree(buffer);
Rohit Grover 1:4769360130ed 45 return result;
Rohit Grover 1:4769360130ed 46 }
Rohit Grover 1:4769360130ed 47
Rohit Grover 1:4769360130ed 48 static SimpleString addMarkerToString(const SimpleString& str, int markerPos)
Rohit Grover 1:4769360130ed 49 {
Rohit Grover 1:4769360130ed 50 size_t bufferSize = str.size()+1;
Rohit Grover 1:4769360130ed 51 char* buffer = (char*) PlatformSpecificMalloc(bufferSize);
Rohit Grover 1:4769360130ed 52 str.copyToBuffer(buffer, bufferSize);
Rohit Grover 1:4769360130ed 53
Rohit Grover 1:4769360130ed 54 buffer[markerPos] = '^';
Rohit Grover 1:4769360130ed 55
Rohit Grover 1:4769360130ed 56 SimpleString result(buffer);
Rohit Grover 1:4769360130ed 57 PlatformSpecificFree(buffer);
Rohit Grover 1:4769360130ed 58 return result;
Rohit Grover 1:4769360130ed 59
Rohit Grover 1:4769360130ed 60 }
Rohit Grover 1:4769360130ed 61
Rohit Grover 1:4769360130ed 62 TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& theMessage) :
Rohit Grover 1:4769360130ed 63 testName_(test->getFormattedName()), fileName_(fileName), lineNumber_(lineNumber), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_(theMessage)
Rohit Grover 1:4769360130ed 64 {
Rohit Grover 1:4769360130ed 65 }
Rohit Grover 1:4769360130ed 66
Rohit Grover 1:4769360130ed 67 TestFailure::TestFailure(UtestShell* test, const SimpleString& theMessage) :
Rohit Grover 1:4769360130ed 68 testName_(test->getFormattedName()), fileName_(test->getFile()), lineNumber_(test->getLineNumber()), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_(theMessage)
Rohit Grover 1:4769360130ed 69 {
Rohit Grover 1:4769360130ed 70 }
Rohit Grover 1:4769360130ed 71
Rohit Grover 1:4769360130ed 72 TestFailure::TestFailure(UtestShell* test, const char* fileName, int lineNum) :
Rohit Grover 1:4769360130ed 73 testName_(test->getFormattedName()), fileName_(fileName), lineNumber_(lineNum), testFileName_(test->getFile()), testLineNumber_(test->getLineNumber()), message_("no message")
Rohit Grover 1:4769360130ed 74 {
Rohit Grover 1:4769360130ed 75 }
Rohit Grover 1:4769360130ed 76
Rohit Grover 1:4769360130ed 77 TestFailure::TestFailure(const TestFailure& f) :
Rohit Grover 1:4769360130ed 78 testName_(f.testName_), fileName_(f.fileName_), lineNumber_(f.lineNumber_), testFileName_(f.testFileName_), testLineNumber_(f.testLineNumber_), message_(f.message_)
Rohit Grover 1:4769360130ed 79 {
Rohit Grover 1:4769360130ed 80 }
Rohit Grover 1:4769360130ed 81
Rohit Grover 1:4769360130ed 82
Rohit Grover 1:4769360130ed 83 TestFailure::~TestFailure()
Rohit Grover 1:4769360130ed 84 {
Rohit Grover 1:4769360130ed 85 }
Rohit Grover 1:4769360130ed 86
Rohit Grover 1:4769360130ed 87 SimpleString TestFailure::getFileName() const
Rohit Grover 1:4769360130ed 88 {
Rohit Grover 1:4769360130ed 89 return fileName_;
Rohit Grover 1:4769360130ed 90 }
Rohit Grover 1:4769360130ed 91
Rohit Grover 1:4769360130ed 92 SimpleString TestFailure::getTestFileName() const
Rohit Grover 1:4769360130ed 93 {
Rohit Grover 1:4769360130ed 94 return testFileName_;
Rohit Grover 1:4769360130ed 95 }
Rohit Grover 1:4769360130ed 96
Rohit Grover 1:4769360130ed 97 SimpleString TestFailure::getTestName() const
Rohit Grover 1:4769360130ed 98 {
Rohit Grover 1:4769360130ed 99 return testName_;
Rohit Grover 1:4769360130ed 100 }
Rohit Grover 1:4769360130ed 101
Rohit Grover 1:4769360130ed 102 int TestFailure::getFailureLineNumber() const
Rohit Grover 1:4769360130ed 103 {
Rohit Grover 1:4769360130ed 104 return lineNumber_;
Rohit Grover 1:4769360130ed 105 }
Rohit Grover 1:4769360130ed 106
Rohit Grover 1:4769360130ed 107 int TestFailure::getTestLineNumber() const
Rohit Grover 1:4769360130ed 108 {
Rohit Grover 1:4769360130ed 109 return testLineNumber_;
Rohit Grover 1:4769360130ed 110 }
Rohit Grover 1:4769360130ed 111
Rohit Grover 1:4769360130ed 112 SimpleString TestFailure::getMessage() const
Rohit Grover 1:4769360130ed 113 {
Rohit Grover 1:4769360130ed 114 return message_;
Rohit Grover 1:4769360130ed 115 }
Rohit Grover 1:4769360130ed 116
Rohit Grover 1:4769360130ed 117 bool TestFailure::isOutsideTestFile() const
Rohit Grover 1:4769360130ed 118 {
Rohit Grover 1:4769360130ed 119 return testFileName_ != fileName_;
Rohit Grover 1:4769360130ed 120 }
Rohit Grover 1:4769360130ed 121
Rohit Grover 1:4769360130ed 122 bool TestFailure::isInHelperFunction() const
Rohit Grover 1:4769360130ed 123 {
Rohit Grover 1:4769360130ed 124 return lineNumber_ < testLineNumber_;
Rohit Grover 1:4769360130ed 125 }
Rohit Grover 1:4769360130ed 126
Rohit Grover 1:4769360130ed 127 SimpleString TestFailure::createButWasString(const SimpleString& expected, const SimpleString& actual)
Rohit Grover 1:4769360130ed 128 {
Rohit Grover 1:4769360130ed 129 return StringFromFormat("expected <%s>\n\tbut was <%s>", expected.asCharString(), actual.asCharString());
Rohit Grover 1:4769360130ed 130 }
Rohit Grover 1:4769360130ed 131
Rohit Grover 1:4769360130ed 132 SimpleString TestFailure::createDifferenceAtPosString(const SimpleString& actual, size_t position)
Rohit Grover 1:4769360130ed 133 {
Rohit Grover 1:4769360130ed 134 SimpleString result;
Rohit Grover 1:4769360130ed 135 const size_t extraCharactersWindow = 20;
Rohit Grover 1:4769360130ed 136 const size_t halfOfExtraCharactersWindow = extraCharactersWindow / 2;
Rohit Grover 1:4769360130ed 137
Rohit Grover 1:4769360130ed 138 SimpleString paddingForPreventingOutOfBounds (" ", halfOfExtraCharactersWindow);
Rohit Grover 1:4769360130ed 139 SimpleString actualString = paddingForPreventingOutOfBounds + actual + paddingForPreventingOutOfBounds;
Rohit Grover 1:4769360130ed 140 SimpleString differentString = StringFromFormat("difference starts at position %lu at: <", (unsigned long) position);
Rohit Grover 1:4769360130ed 141
Rohit Grover 1:4769360130ed 142 result += "\n";
Rohit Grover 1:4769360130ed 143 result += StringFromFormat("\t%s%s>\n", differentString.asCharString(), actualString.subString(position, extraCharactersWindow).asCharString());
Rohit Grover 1:4769360130ed 144
Rohit Grover 1:4769360130ed 145 SimpleString markString = actualString.subString(position, halfOfExtraCharactersWindow+1);
Rohit Grover 1:4769360130ed 146 markString = removeAllPrintableCharactersFrom(markString);
Rohit Grover 1:4769360130ed 147 markString = addMarkerToString(markString, halfOfExtraCharactersWindow);
Rohit Grover 1:4769360130ed 148
Rohit Grover 1:4769360130ed 149 result += StringFromFormat("\t%s%s", SimpleString(" ", differentString.size()).asCharString(), markString.asCharString());
Rohit Grover 1:4769360130ed 150 return result;
Rohit Grover 1:4769360130ed 151 }
Rohit Grover 1:4769360130ed 152
Rohit Grover 1:4769360130ed 153 EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) :
Rohit Grover 1:4769360130ed 154 TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 155 {
Rohit Grover 1:4769360130ed 156 message_ = createButWasString(StringFromOrNull(expected), StringFromOrNull(actual));
Rohit Grover 1:4769360130ed 157 }
Rohit Grover 1:4769360130ed 158
Rohit Grover 1:4769360130ed 159 EqualsFailure::EqualsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual)
Rohit Grover 1:4769360130ed 160 : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 161 {
Rohit Grover 1:4769360130ed 162 message_ = createButWasString(expected, actual);
Rohit Grover 1:4769360130ed 163 }
Rohit Grover 1:4769360130ed 164
Rohit Grover 1:4769360130ed 165 static SimpleString StringFromOrNan(double d)
Rohit Grover 1:4769360130ed 166 {
Rohit Grover 1:4769360130ed 167 if (PlatformSpecificIsNan(d))
Rohit Grover 1:4769360130ed 168 return "Nan - Not a number";
Rohit Grover 1:4769360130ed 169 return StringFrom(d);
Rohit Grover 1:4769360130ed 170 }
Rohit Grover 1:4769360130ed 171
Rohit Grover 1:4769360130ed 172 DoublesEqualFailure::DoublesEqualFailure(UtestShell* test, const char* fileName, int lineNumber, double expected, double actual, double threshold) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 173 {
Rohit Grover 1:4769360130ed 174 message_ = createButWasString(StringFromOrNan(expected), StringFromOrNan(actual));
Rohit Grover 1:4769360130ed 175 message_ += " threshold used was <";
Rohit Grover 1:4769360130ed 176 message_ += StringFromOrNan(threshold);
Rohit Grover 1:4769360130ed 177 message_ += ">";
Rohit Grover 1:4769360130ed 178
Rohit Grover 1:4769360130ed 179 if (PlatformSpecificIsNan(expected) || PlatformSpecificIsNan(actual) || PlatformSpecificIsNan(threshold))
Rohit Grover 1:4769360130ed 180 message_ += "\n\tCannot make comparisons with Nan";
Rohit Grover 1:4769360130ed 181 }
Rohit Grover 1:4769360130ed 182
Rohit Grover 1:4769360130ed 183 CheckEqualFailure::CheckEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 184 {
Rohit Grover 1:4769360130ed 185 size_t failStart;
Rohit Grover 1:4769360130ed 186 for (failStart = 0; actual.asCharString()[failStart] == expected.asCharString()[failStart]; failStart++)
Rohit Grover 1:4769360130ed 187 ;
Rohit Grover 1:4769360130ed 188 message_ = createButWasString(expected, actual);
Rohit Grover 1:4769360130ed 189 message_ += createDifferenceAtPosString(actual, failStart);
Rohit Grover 1:4769360130ed 190
Rohit Grover 1:4769360130ed 191 }
Rohit Grover 1:4769360130ed 192
Rohit Grover 1:4769360130ed 193 ContainsFailure::ContainsFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& expected, const SimpleString& actual) :
Rohit Grover 1:4769360130ed 194 TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 195 {
Rohit Grover 1:4769360130ed 196 message_ = StringFromFormat("actual <%s>\n\tdid not contain <%s>", actual.asCharString(), expected.asCharString());
Rohit Grover 1:4769360130ed 197 }
Rohit Grover 1:4769360130ed 198
Rohit Grover 1:4769360130ed 199 CheckFailure::CheckFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& checkString, const SimpleString& conditionString, const SimpleString& text) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 200 {
Rohit Grover 1:4769360130ed 201 message_ = "";
Rohit Grover 1:4769360130ed 202 if (!text.isEmpty()) {
Rohit Grover 1:4769360130ed 203 message_ += "Message: ";
Rohit Grover 1:4769360130ed 204 message_ += text;
Rohit Grover 1:4769360130ed 205 message_ += "\n\t";
Rohit Grover 1:4769360130ed 206 }
Rohit Grover 1:4769360130ed 207 message_ += checkString;
Rohit Grover 1:4769360130ed 208 message_ += "(";
Rohit Grover 1:4769360130ed 209 message_ += conditionString;
Rohit Grover 1:4769360130ed 210 message_ += ") failed";
Rohit Grover 1:4769360130ed 211 }
Rohit Grover 1:4769360130ed 212
Rohit Grover 1:4769360130ed 213 FailFailure::FailFailure(UtestShell* test, const char* fileName, int lineNumber, const SimpleString& message) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 214 {
Rohit Grover 1:4769360130ed 215 message_ = message;
Rohit Grover 1:4769360130ed 216 }
Rohit Grover 1:4769360130ed 217
Rohit Grover 1:4769360130ed 218 LongsEqualFailure::LongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, long expected, long actual) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 219 {
Rohit Grover 1:4769360130ed 220 SimpleString aDecimal = StringFrom(actual);
Rohit Grover 1:4769360130ed 221 SimpleString aHex = HexStringFrom(actual);
Rohit Grover 1:4769360130ed 222 SimpleString eDecimal = StringFrom(expected);
Rohit Grover 1:4769360130ed 223 SimpleString eHex = HexStringFrom(expected);
Rohit Grover 1:4769360130ed 224
Rohit Grover 1:4769360130ed 225 SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
Rohit Grover 1:4769360130ed 226 SimpleString::padStringsToSameLength(aHex, eHex, '0');
Rohit Grover 1:4769360130ed 227
Rohit Grover 1:4769360130ed 228 SimpleString actualReported = aDecimal + " 0x" + aHex;
Rohit Grover 1:4769360130ed 229 SimpleString expectedReported = eDecimal + " 0x" + eHex;
Rohit Grover 1:4769360130ed 230 message_ = createButWasString(expectedReported, actualReported);
Rohit Grover 1:4769360130ed 231 }
Rohit Grover 1:4769360130ed 232
Rohit Grover 1:4769360130ed 233 UnsignedLongsEqualFailure::UnsignedLongsEqualFailure(UtestShell* test, const char* fileName, int lineNumber, unsigned long expected, unsigned long actual) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 234 {
Rohit Grover 1:4769360130ed 235 SimpleString aDecimal = StringFrom(actual);
Rohit Grover 1:4769360130ed 236 SimpleString aHex = HexStringFrom(actual);
Rohit Grover 1:4769360130ed 237 SimpleString eDecimal = StringFrom(expected);
Rohit Grover 1:4769360130ed 238 SimpleString eHex = HexStringFrom(expected);
Rohit Grover 1:4769360130ed 239
Rohit Grover 1:4769360130ed 240 SimpleString::padStringsToSameLength(aDecimal, eDecimal, ' ');
Rohit Grover 1:4769360130ed 241 SimpleString::padStringsToSameLength(aHex, eHex, '0');
Rohit Grover 1:4769360130ed 242
Rohit Grover 1:4769360130ed 243 SimpleString actualReported = aDecimal + " 0x" + aHex;
Rohit Grover 1:4769360130ed 244 SimpleString expectedReported = eDecimal + " 0x" + eHex;
Rohit Grover 1:4769360130ed 245 message_ = createButWasString(expectedReported, actualReported);
Rohit Grover 1:4769360130ed 246 }
Rohit Grover 1:4769360130ed 247
Rohit Grover 1:4769360130ed 248
Rohit Grover 1:4769360130ed 249 StringEqualFailure::StringEqualFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 250 {
Rohit Grover 1:4769360130ed 251 size_t failStart;
Rohit Grover 1:4769360130ed 252 for (failStart = 0; actual[failStart] == expected[failStart]; failStart++)
Rohit Grover 1:4769360130ed 253 ;
Rohit Grover 1:4769360130ed 254 message_ = createButWasString(expected, actual);
Rohit Grover 1:4769360130ed 255 message_ += createDifferenceAtPosString(actual, failStart);
Rohit Grover 1:4769360130ed 256 }
Rohit Grover 1:4769360130ed 257
Rohit Grover 1:4769360130ed 258 StringEqualNoCaseFailure::StringEqualNoCaseFailure(UtestShell* test, const char* fileName, int lineNumber, const char* expected, const char* actual) : TestFailure(test, fileName, lineNumber)
Rohit Grover 1:4769360130ed 259 {
Rohit Grover 1:4769360130ed 260 size_t failStart;
Rohit Grover 1:4769360130ed 261 for (failStart = 0; PlatformSpecificToLower(actual[failStart]) == PlatformSpecificToLower(expected[failStart]); failStart++)
Rohit Grover 1:4769360130ed 262 ;
Rohit Grover 1:4769360130ed 263 message_ = createButWasString(expected, actual);
Rohit Grover 1:4769360130ed 264 message_ += createDifferenceAtPosString(actual, failStart);
Rohit Grover 1:4769360130ed 265 }
Rohit Grover 1:4769360130ed 266
Rohit Grover 1:4769360130ed 267