Adding corruption component used for testing processing component behaviour under...
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 1 Sep 2010 22:59:17 +0000 (22:59 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 1 Sep 2010 22:59:17 +0000 (22:59 +0000)
Used to have various custom ways of performing such tests. Now the corruption component can be used to test all components in the same way.

HLT/AliHLTUtilLinkDef.h
HLT/BASE/util/AliHLTAgentUtil.cxx
HLT/BASE/util/AliHLTCorruptorComponent.cxx [new file with mode: 0644]
HLT/BASE/util/AliHLTCorruptorComponent.h [new file with mode: 0644]
HLT/BASE/util/test/testAliHLTCorruptorComponent.C [new file with mode: 0644]
HLT/libAliHLTUtil.pkg

index 32d0da1..e71e802 100644 (file)
@@ -20,6 +20,7 @@
 #pragma link C++ class AliHLTDataGenerator+;
 #pragma link C++ class AliHLTBlockFilterComponent+;
 #pragma link C++ class AliHLTCompStatCollector+;
+#pragma link C++ class AliHLTCorruptorComponent+;
 #pragma link C++ class AliHLTAgentUtil+;
 #endif
 
index 11eb03c..8dc1941 100644 (file)
@@ -44,6 +44,7 @@
 #include "AliHLTReadoutListDumpComponent.h"
 #include "AliHLTOUTPublisherComponent.h"
 #include "AliHLTCompStatCollector.h"
+#include "AliHLTCorruptorComponent.h"
 
 /** global instance for agent registration */
 AliHLTAgentUtil gAliHLTAgentUtil;
@@ -127,6 +128,7 @@ int AliHLTAgentUtil::RegisterComponents(AliHLTComponentHandler* pHandler) const
   pHandler->AddComponent(new AliHLTReadoutListDumpComponent);
   pHandler->AddComponent(new AliHLTOUTPublisherComponent);
   pHandler->AddComponent(new AliHLTCompStatCollector);
+  pHandler->AddComponent(new AliHLTCorruptorComponent);
   return 0;
 }
 
diff --git a/HLT/BASE/util/AliHLTCorruptorComponent.cxx b/HLT/BASE/util/AliHLTCorruptorComponent.cxx
new file mode 100644 (file)
index 0000000..552c108
--- /dev/null
@@ -0,0 +1,1322 @@
+// $Id: $
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ *                                                                        *
+ * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
+ *                  for The ALICE HLT Project.                            *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/// @file   AliHLTCorruptorComponent.cxx
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   5 Aug 2010
+/// @brief  Implementation of the AliHLTCorruptorComponent class.
+///
+/// The AliHLTCorruptorComponent is used to generate corruption of various kind
+/// in the input data blocks it sees. The blocks will be copied to the output
+/// but with various bit flips and garbage inserted.
+/// This kind of component is used for testing purposes.
+
+#include "AliHLTCorruptorComponent.h"
+#include "TRandom3.h"
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+ClassImp(AliHLTCorruptorComponent)
+
+
+AliHLTCorruptorComponent::AliHLTCorruptorComponent() :
+       AliHLTProcessor(),
+       fBufferMultiplier(2.),
+       fBlockIdList(),
+       fCorruptionInfoList(),
+       fPatterns()
+{
+       // Default constructor.
+}
+
+
+AliHLTCorruptorComponent::~AliHLTCorruptorComponent()
+{
+       // Default destructor.
+}
+
+
+const char* AliHLTCorruptorComponent::GetComponentID()
+{
+       // Returns the component ID.
+       return "CorruptorComponent";
+}
+
+
+void AliHLTCorruptorComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
+{
+       // Returns the list of input data types that are handled.
+       list.push_back(kAliHLTAnyDataType);
+}
+
+
+AliHLTComponentDataType AliHLTCorruptorComponent::GetOutputDataType()
+{
+       // Returns kAliHLTMultipleDataType.
+       return kAliHLTMultipleDataType;
+}
+
+
+int AliHLTCorruptorComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
+{
+       // Returns the list of output data blocks handled.
+       list.push_back(kAliHLTAnyDataType);
+       return int(list.size());
+}
+
+
+void AliHLTCorruptorComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
+{
+       // Returns the buffer size requirements.
+       
+       unsigned long total = 0;
+       for (size_t i = 0; i < fCorruptionInfoList.size(); ++i)
+       {
+               AliCorruptionInfo& info = fCorruptionInfoList[i];
+               if (info.fType == kInsert)
+               {
+                       total += (info.fLastPattern - info.fFirstPattern) / sizeof(AliPattern) * sizeof(AliHLTUInt64_t);
+               }
+               else if (info.fType == kInsertRandom)
+               {
+                       total += info.fMaxBits / 8 + 1;
+               }
+       }
+       
+       constBase = total;
+       inputMultiplier = fBufferMultiplier;
+}
+
+
+AliHLTComponent* AliHLTCorruptorComponent::Spawn()
+{
+       // Creates a new instance of the component.
+       return new AliHLTCorruptorComponent;
+}
+
+
+bool AliHLTCorruptorComponent::ConvertToPositiveInt(const char* value, AliHLTUInt64_t& num, bool printErrors) const
+{
+       // Converts a string value to a positive integer.
+       
+       char* err = NULL;
+       errno = 0;
+       unsigned long long tmpnum = strtoull(value, &err, 0);
+       if (err == NULL or *err != '\0')
+       {
+               if (printErrors) HLTError("Cannot convert '%s' to a positive integer.", value);
+               return false;
+       }
+       if (errno == ERANGE)
+       {
+               if (printErrors) HLTError("The specified value '%s' is out of range.", value);
+               return false;
+       }
+       num = tmpnum;
+       return true;
+}
+
+
+bool AliHLTCorruptorComponent::ConvertToBitPosition(
+               const char* value, AliHLTUInt64_t& pos, bool& relative, bool printErrors
+       ) const
+{
+       // Converts a string value to a bit position.
+       
+       if (strcmp(value, "min") == 0)
+       {
+               // Special case where the value is the special symbol "min".
+               pos = 0;
+               relative = false;
+               return true;
+       }
+       if (strcmp(value, "max") == 0)
+       {
+               // Special case where the value is the special symbol "max".
+               pos = 0xFFFFFFFFFFFFFFFFull;
+               relative = false;
+               return true;
+       }
+       
+       int valuelength = strlen(value);
+       const char* valstr = value;
+       relative = false;
+       // Check if the position is relative.
+       if (valuelength >= 3 and value[0] == 'm' and value[1] == 'i' and value[2] == 'n')
+       {
+               if (valuelength >= 4 and value[3] == '-')
+               {
+                       if (printErrors)
+                       {
+                               HLTError("Cannot use 'min-' in option '%s' since that would be outside the buffer."
+                                       " Should use 'min+' instead.",
+                                       value
+                               );
+                               return false;
+                       }
+               }
+               else if (valuelength >= 4 and value[3] == '+')
+               {
+                       // Value starting with min+ does not need anything special because
+                       // min is always == 0. Just adjust the value string pointer to
+                       // skip this part of the string.
+                       valstr = value + 4;
+               }
+       }
+       else if (valuelength >= 3 and value[0] == 'm' and value[1] == 'a' and value[2] == 'x')
+       {
+               if (valuelength >= 4 and value[3] == '+')
+               {
+                       if (printErrors)
+                       {
+                               HLTError("Cannot use 'max+' in option '%s' since that would be outside the buffer."
+                                       " Should use 'max-' instead.",
+                                       value
+                               );
+                               return false;
+                       }
+               }
+               else if (valuelength >= 4 and value[3] == '-')
+               {
+                       // Need to mark the result as a relative value and skip the
+                       // first part of the string.
+                       relative = true;
+                       valstr = value + 4;
+               }
+       }
+       
+       // Find the location of ':' if any, to mark the start of the byte and bit strings.
+       int bytestrlen = strlen(valstr);
+       const char* bitstr = valstr + bytestrlen;
+       for (int i = 0; valstr[i] != 0x0; ++i)
+       {
+               if (valstr[i] == ':')
+               {
+                       bytestrlen = i;
+                       bitstr = valstr + (i+1);
+                       break;
+               }
+       }
+       TString bytestr(valstr, bytestrlen);
+       
+       char* err = NULL;
+       errno = 0;
+       unsigned long long bytenum = strtoull(bytestr.Data(), &err, 0);
+       if (err == NULL or *err != '\0')
+       {
+               if (printErrors)
+               {
+                       HLTError("Cannot convert '%s' given in option '%s' to a positive integer.",
+                               bytestr.Data(), value
+                       );
+               }
+               return false;
+       }
+       if (errno == ERANGE or bytenum > 0x1FFFFFFFFFFFFFFFull)
+       {
+               if (printErrors)
+               {
+                       HLTError("The specified byte number '%s' given in option '%s' is out of range."
+                               " The value should be in the range [0..%lld].",
+                               bytestr.Data(), value, 0x1FFFFFFFFFFFFFFFull
+                       );
+               }
+               return false;
+       }
+       err = NULL;
+       unsigned long bitnum = strtoul(bitstr, &err, 0);
+       if (err == NULL or *err != '\0')
+       {
+               if (printErrors)
+               {
+                       HLTError("Cannot convert '%s' given in option '%s' to a positive integer.",
+                               bitstr, value
+                       );
+               }
+               return false;
+       }
+       if (errno == ERANGE or bitnum > 7)
+       {
+               if (printErrors)
+               {
+                       HLTError("The specified bit number '%s' given in option '%s' is out of range."
+                               " The value should be in the range [0..7].",
+                               bitstr, value
+                       );
+               }
+               return false;
+       }
+       pos = (bytenum << 3) | (bitnum & 0x7);
+       return true;
+}
+
+
+bool AliHLTCorruptorComponent::ConvertToPercentage(const char* value, double& num, bool printErrors) const
+{
+       // Converts a string value as a percentage to a floating point number in the range [0..1].
+       
+       TString str = value;
+       bool percent = false;
+       if (str.Length() > 0 and str[str.Length()-1] == '%')
+       {
+               percent = true;
+               str[str.Length()-1] = '\0';
+       }
+       char* err = NULL;
+       errno = 0;
+       double tmpnum = strtod(str.Data(), &err);
+       if (err == NULL or *err != '\0')
+       {
+               if (printErrors) HLTError("Cannot convert '%s' to a valid floating point value.", value);
+               return false;
+       }
+       if (errno == ERANGE or tmpnum < 0. or (tmpnum > 100. and percent) or (tmpnum > 1. and not percent))
+       {
+               if (printErrors)
+               {
+                       int range = percent ? 100 : 1;
+                       HLTError("The specified value '%s' is outside the range [0..%d]", value, range);
+               }
+               return false;
+       }
+       num = percent ? tmpnum / 100. : tmpnum;
+       return true;
+}
+
+
+bool AliHLTCorruptorComponent::ConvertToPattern(const char* value, AliPattern& pattern, bool printErrors) const
+{
+       // Coverts a string value into a pattern structure.
+       
+       if (strcmp(value, "removed") == 0)
+       {
+               // Special case where the pattern is the special symbol to used remove bits.
+               pattern.fPattern = 0;
+               pattern.fWidth = 0;
+               pattern.fUseRemoved = true;
+               return true;
+       }
+       
+       // Find the location of '/' if any, to mark the start of the pattern and width fields.
+       int patstrlen = strlen(value);
+       const char* widthstr = value + patstrlen;
+       for (int i = 0; value[i] != 0x0; ++i)
+       {
+               if (value[i] == '/')
+               {
+                       patstrlen = i;
+                       widthstr = value + (i+1);
+                       break;
+               }
+       }
+       TString patstr(value, patstrlen);
+       
+       char* err = NULL;
+       errno = 0;
+       AliHLTUInt64_t patnum = AliHLTUInt64_t( strtoull(patstr.Data(), &err, 0) );
+       if (err == NULL or *err != '\0')
+       {
+               if (printErrors)
+               {
+                       HLTError("Cannot convert '%s' given in pattern '%s' to a positive integer.",
+                               patstr.Data(), value
+                       );
+               }
+               return false;
+       }
+       if (errno == ERANGE)
+       {
+               if (printErrors)
+               {
+                       HLTError("The specified pattern '%s' is out of range."
+                               "Cannot be bigger than a 64 bit integer.",
+                                value
+                       );
+               }
+               return false;
+       }
+       unsigned long widthnum = 1;
+       if (*widthstr != '\0')  // check if widthstr string is not empty
+       {
+               err = NULL;
+               widthnum = strtoul(widthstr, &err, 0);
+               if (err == NULL or *err != '\0')
+               {
+                       if (printErrors)
+                       {
+                               HLTError("Cannot convert the width '%s' given in pattern '%s'"
+                                       " to a positive integer.",
+                                       widthstr, value
+                               );
+                       }
+                       return false;
+               }
+               if (errno == ERANGE or widthnum < 1 or 64 < widthnum)
+               {
+                       if (printErrors)
+                       {
+                               HLTError("The specified width '%s' given in pattern '%s' is out of range."
+                                       " The value should be in the range [1..64].",
+                                       widthstr, value
+                               );
+                       }
+                       return false;
+               }
+       }
+       else
+       {
+               // Find the width of the pattern if not explicitly given.
+               // This is done by finding the most significant set bit.
+               for (int i = 63; i >= 0; --i)
+               {
+                       if (((patnum >> i) & 0x1) == 0x1)
+                       {
+                               widthnum = i+1;
+                               break;
+                       }
+               }
+       }
+       pattern.fPattern = patnum;
+       pattern.fWidth = AliHLTUInt8_t(widthnum);
+       pattern.fUseRemoved = false;
+       return true;
+}
+
+
+bool AliHLTCorruptorComponent::AddBlockTypeId(const char* type)
+{
+       // Sets the block type ID to filter on.
+       
+       if (strlen(type) > (unsigned)kAliHLTComponentDataTypefIDsize)
+       {
+               HLTError("The specified block type '%s' must not be longer than %d characters.",
+                       type, kAliHLTComponentDataTypefIDsize
+               );
+               return false;
+       }
+       if (fBlockIdList.size() > 0 and not fBlockIdList[fBlockIdList.size()-1].fTypeSet)
+       {
+               fBlockIdList[fBlockIdList.size()-1].fType =
+                       AliHLTComponentDataTypeInitializer(
+                                       type,
+                                       fBlockIdList[fBlockIdList.size()-1].fType.fOrigin
+                               );
+               fBlockIdList[fBlockIdList.size()-1].fTypeSet = true;
+       }
+       else
+       {
+               AliBlockId id;
+               id.fType = AliHLTComponentDataTypeInitializer(type, kAliHLTDataOriginAny);
+               id.fSpec = kAliHLTVoidDataSpec;
+               id.fTypeSet = true;
+               id.fOriginSet = false;
+               id.fSpecSet = false;
+               fBlockIdList.push_back(id);
+       }
+       return true;
+}
+
+
+bool AliHLTCorruptorComponent::AddBlockOrigin(const char* origin)
+{
+       // Sets the block origin to filter on.
+       
+       if (strlen(origin) > (unsigned)kAliHLTComponentDataTypefOriginSize)
+       {
+               HLTError("The specified origin '%s' must not be longer than %d characters.",
+                       origin, kAliHLTComponentDataTypefOriginSize
+               );
+               return false;
+       }
+       if (fBlockIdList.size() > 0 and not fBlockIdList[fBlockIdList.size()-1].fOriginSet)
+       {
+               fBlockIdList[fBlockIdList.size()-1].fType =
+                       AliHLTComponentDataTypeInitializer(
+                                       fBlockIdList[fBlockIdList.size()-1].fType.fID,
+                                       origin
+                               );
+               fBlockIdList[fBlockIdList.size()-1].fOriginSet = true;
+       }
+       else
+       {
+               AliBlockId id;
+               id.fType = AliHLTComponentDataTypeInitializer(kAliHLTAnyDataTypeID, origin);
+               id.fSpec = kAliHLTVoidDataSpec;
+               id.fTypeSet = false;
+               id.fOriginSet = true;
+               id.fSpecSet = false;
+               fBlockIdList.push_back(id);
+       }
+       return true;
+}
+
+
+bool AliHLTCorruptorComponent::AddBlockSpec(const char* spec)
+{
+       // Sets the block specification to filter on.
+       
+       char* err = NULL;
+       errno = 0;
+       unsigned long long num = strtoull(spec, &err, 0);
+       if (err == NULL or *err != '\0')
+       {
+               HLTError("Cannot convert '%s' to a specification number.", spec);
+               return false;
+       }
+       if (num > 0xFFFFFFFF or errno == ERANGE)
+       {
+               HLTError("The specification number is not an unsigned 32-bit value or out of range.");
+               return false;
+       }
+       AliHLTUInt32_t specVal = AliHLTUInt32_t(num);
+       
+       if (fBlockIdList.size() > 0 and not fBlockIdList[fBlockIdList.size()-1].fSpecSet)
+       {
+               fBlockIdList[fBlockIdList.size()-1].fSpec = specVal;
+               fBlockIdList[fBlockIdList.size()-1].fSpecSet = true;
+       }
+       else
+       {
+               AliBlockId id;
+               id.fType = AliHLTComponentDataTypeInitializer(kAliHLTAnyDataTypeID, kAliHLTDataOriginAny);
+               id.fSpec = specVal;
+               id.fTypeSet = false;
+               id.fOriginSet = false;
+               id.fSpecSet = true;
+               fBlockIdList.push_back(id);
+       }
+       
+       return true;
+}
+
+
+void AliHLTCorruptorComponent::AddCorruptionCommand(
+               AliCorruptionType type,
+               AliHLTUInt64_t minrange,
+               AliHLTUInt64_t maxrange,
+               AliHLTUInt64_t alignment,
+               bool minRangeRelative,
+               bool maxRangeRelative,
+               bool userate,
+               double rate,
+               AliHLTUInt64_t minerrors,
+               AliHLTUInt64_t maxerrors,
+               AliHLTUInt64_t burstlength,
+               AliHLTUInt64_t burstcount,
+               AliHLTUInt64_t minbits,
+               AliHLTUInt64_t maxbits,
+               size_t firstpattern,
+               size_t lastpattern
+       )
+{
+       // Adds a new entry into the corruptions list to apply.
+       
+       AliCorruptionInfo info;
+       memset(&info, 0x0, sizeof(info));
+       info.fType = type;
+       info.fMinRange = minrange;
+       info.fMaxRange = maxrange;
+       info.fAlignment = alignment;
+       info.fMinRangeRelative = minRangeRelative;
+       info.fMaxRangeRelative = maxRangeRelative;
+       info.fUseRate = userate;
+       if (userate)
+       {
+               info.fRate = rate;
+       }
+       else
+       {
+               info.fMinErrors = minerrors;
+               info.fMaxErrors = maxerrors;
+       }
+       switch (type)
+       {
+       case kBurstErrors:
+               info.fBurstErrorLength = burstlength;
+               info.fBurstErrorCount = burstcount;
+               break;
+       case kReplace:
+               info.fFirstPattern = firstpattern;
+               info.fLastPattern = lastpattern;
+               break;
+       case kReplaceRandom:
+               info.fMinBits = minbits;
+               info.fMaxBits = maxbits;
+               break;
+       case kInsert:
+               info.fFirstPattern = firstpattern;
+               info.fLastPattern = lastpattern;
+               break;
+       case kInsertRandom:
+               info.fMinBits = minbits;
+               info.fMaxBits = maxbits;
+               break;
+       case kRemove:
+               info.fMinBits = minbits;
+               info.fMaxBits = maxbits;
+               break;
+       default:
+               // Nothing to do.
+               break;
+       }
+       fCorruptionInfoList.push_back(info);
+}
+
+
+int AliHLTCorruptorComponent::CheckForCommandWithPatterns(
+               const char* name, AliCorruptionType type,
+               int& i, int argc, const char** argv,
+               AliHLTUInt64_t minrange,
+               AliHLTUInt64_t maxrange,
+               AliHLTUInt64_t alignment,
+               bool minRangeRelative,
+               bool maxRangeRelative,
+               bool userate,
+               double errorrate,
+               AliHLTUInt64_t minerrors,
+               AliHLTUInt64_t maxerrors
+       )
+{
+       // Check for a particular command line option that has pattern parameters.
+       
+       AliPattern pattern = {0, 0, false};
+       if (strcmp(argv[i], name) == 0)
+       {
+               // Check for at least 1 pattern.
+               if (argc <= i+1)
+               {
+                       HLTError("At least one pattern must be specified for %s.", name);
+                       return -EINVAL;
+               }
+               if (not ConvertToPattern(argv[i+1], pattern)) return -EPROTO;
+               // Mark the pattern found as the first pattern and add it.
+               size_t firstpattern = fPatterns.size();
+               fPatterns.push_back(pattern);
+               ++i;
+               // Now check for more patterns. Do not print any error messages,
+               // since here we assume that if the string is not a pattern string
+               // then it might be another command.
+               while (i+1 < argc and ConvertToPattern(argv[i+1], pattern, false))
+               {
+                       fPatterns.push_back(pattern);
+                       ++i;
+               }
+               // Mark the last pattern and add corruption command.
+               size_t lastpattern = fPatterns.size();
+               AddCorruptionCommand(
+                       type, minrange, maxrange, alignment,
+                       minRangeRelative, maxRangeRelative, userate,
+                       errorrate, minerrors, maxerrors, 0, 0, 0, 0,
+                       firstpattern, lastpattern
+               );
+               return 1;
+       }
+       return 0;
+}
+
+
+int AliHLTCorruptorComponent::CheckForCommandWithMinMax(
+               const char* name, AliCorruptionType type,
+               int& i, int argc, const char** argv,
+               AliHLTUInt64_t minrange,
+               AliHLTUInt64_t maxrange,
+               AliHLTUInt64_t alignment,
+               bool minRangeRelative,
+               bool maxRangeRelative,
+               bool userate,
+               double errorrate,
+               AliHLTUInt64_t minerrors,
+               AliHLTUInt64_t maxerrors
+       )
+{
+       // Check for a particular command line option that has 2 (min/max) parameters.
+       
+       if (strcmp(argv[i], name) == 0)
+       {
+               if (argc <= i+1)
+               {
+                       HLTError("Minimum number of bits to replace not specified for %s.", name);
+                       return -EINVAL;
+               }
+               AliHLTUInt64_t minbits = 0;
+               if (strcmp(argv[i+1], "min") == 0)
+               {
+                       minbits = 0;
+               }
+               else if (strcmp(argv[i+1], "max") == 0)
+               {
+                       minbits = 0xFFFFFFFFFFFFFFFFull;
+               }
+               else
+               {
+                       if (not ConvertToPositiveInt(argv[i+1], minbits)) return -EPROTO;
+               }
+               if (argc <= i+2)
+               {
+                       HLTError("Maximum number of bits to replace not specified for %s.", name);
+                       return -EINVAL;
+               }
+               AliHLTUInt64_t maxbits = 0;
+               if (strcmp(argv[i+2], "min") == 0)
+               {
+                       maxbits = 0;
+               }
+               else if (strcmp(argv[i+2], "max") == 0)
+               {
+                       maxbits = 0xFFFFFFFFFFFFFFFFull;
+               }
+               else
+               {
+                       if (not ConvertToPositiveInt(argv[i+2], maxbits)) return -EPROTO;
+               }
+               if (maxbits < minbits)
+               {
+                       HLTError("Maximum value (%s) is smaller than minimum (%s).", argv[i+2], argv[i+1]);
+                       return -EPROTO;
+               }
+               AddCorruptionCommand(
+                       type, minrange, maxrange, alignment,
+                       minRangeRelative, maxRangeRelative, userate,
+                       errorrate, minerrors, maxerrors, 0, 0, minbits, maxbits
+               );
+               i += 2;
+               return 1;
+       }
+       return 0;
+}
+
+
+Int_t AliHLTCorruptorComponent::DoInit(int argc, const char** argv)
+{
+       // Initialises the corruptor component from the command line.
+       
+       int result = 0;
+       fBlockIdList.clear();
+       fCorruptionInfoList.clear();
+       fPatterns.clear();
+       AliHLTUInt64_t minpos = 0;
+       AliHLTUInt64_t maxpos = 0xFFFFFFFFFFFFFFFFull;
+       AliHLTUInt64_t alignment = 1;
+       bool minposrel = false;
+       bool maxposrel = false;
+       bool useErrorRate = true;
+       double errorrate = 0.001;
+       AliHLTUInt64_t minerrors = 1;
+       AliHLTUInt64_t maxerrors = 1;
+       bool seedSet = false;
+       UInt_t seed = 0;
+       
+       for (int i = 0; i < argc; ++i)
+       {
+               if (strcmp(argv[i], "-seed") == 0)
+               {
+                       if (seedSet)
+                       {
+                               HLTError("The option \"-seed\" has already been used with"
+                                       " the value %u. Can only use this option once",
+                                       seed
+                               );
+                               return -EINVAL;
+                       }
+                       if (argc <= i+1)
+                       {
+                               HLTError("The random number generator seed was not specified for -seed.");
+                               return -EINVAL;
+                       }
+                       AliHLTUInt64_t tmpseed = 0;
+                       if (not ConvertToPositiveInt(argv[i+1], tmpseed)) return -EPROTO;
+                       if (tmpseed > 0xFFFFFFFF)
+                       {
+                               HLTError("The random number generator seed value cannot be larger than %u.", 0xFFFFFFFF);
+                               return -EPROTO;
+                       }
+                       seed = UInt_t(tmpseed);
+                       seedSet = true;
+                       ++i;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-datatype") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("The data type identifier was not specified for -datatype.");
+                               return -EINVAL;
+                       }
+                       if (not AddBlockTypeId(argv[i+1])) return -EPROTO;
+                       if (argc <= i+2)
+                       {
+                               HLTError("The origin identifier was not specified for -datatype.");
+                               return -EINVAL;
+                       }
+                       if (not AddBlockOrigin(argv[i+2])) return -EPROTO;
+                       i += 2;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-origin") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("The origin identifier was not specified for -origin.");
+                               return -EINVAL;
+                       }
+                       if (not AddBlockOrigin(argv[i+1])) return -EPROTO;
+                       ++i;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-typeid") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("The data type identifier was not specified for -typeid.");
+                               return -EINVAL;
+                       }
+                       if (not AddBlockTypeId(argv[i+1])) return -EPROTO;
+                       ++i;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-dataspec") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("The data specification was not specified for -dataspec.");
+                               return -EINVAL;
+                       }
+                       if (not AddBlockSpec(argv[i+1])) return -EPROTO;
+                       ++i;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-range") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("Minimum byte/bit position not given for -range.");
+                               return -EINVAL;
+                       }
+                       if (not ConvertToBitPosition(argv[i+1], minpos, minposrel)) return -EPROTO;
+                       if (argc <= i+2)
+                       {
+                               HLTError("Maximum byte/bit position not given for -range.");
+                               return -EINVAL;
+                       }
+                       if (not ConvertToBitPosition(argv[i+2], maxpos, maxposrel)) return -EPROTO;
+                       if (minposrel == maxposrel and maxpos < minpos)
+                       {
+                               HLTError("Maximum position (%s) is smaller than minimum position (%s).",
+                                       argv[i+2], argv[i+1]
+                               );
+                               return -EPROTO;
+                       }
+                       i += 2;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-alignment") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("The alignment value was not specified for -errorrate.");
+                               return -EINVAL;
+                       }
+                       if (not ConvertToPositiveInt(argv[i+1], alignment)) return -EPROTO;
+                       if (alignment == 0)
+                       {
+                               HLTError("The alignment value cannot be zero.");
+                               return -EPROTO;
+                       }
+                       ++i;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-errorrate") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("The current error rate to use was not specified for -errorrate.");
+                               return -EINVAL;
+                       }
+                       if (not ConvertToPercentage(argv[i+1], errorrate)) return -EPROTO;
+                       useErrorRate = true;
+                       ++i;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-errorcount") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("Minimum number of errors not specified for -errorcount.");
+                               return -EINVAL;
+                       }
+                       if (not ConvertToPositiveInt(argv[i+1], minerrors)) return -EPROTO;
+                       if (argc <= i+2)
+                       {
+                               HLTError("Maximum number of errors not specified for -errorcount.");
+                               return -EINVAL;
+                       }
+                       if (not ConvertToPositiveInt(argv[i+2], maxerrors)) return -EPROTO;
+                       if (maxerrors < minerrors)
+                       {
+                               HLTError("Maximum error count (%s) is smaller than minimum (%s).",
+                                       argv[i+2], argv[i+1]
+                               );
+                               return -EPROTO;
+                       }
+                       useErrorRate = false;
+                       i += 2;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-singleflips") == 0)
+               {
+                       AddCorruptionCommand(
+                               kSingleFlips, minpos, maxpos, alignment,
+                               minposrel, maxposrel, useErrorRate,
+                               errorrate, minerrors, maxerrors
+                       );
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-bursterrors") == 0)
+               {
+                       if (argc <= i+1)
+                       {
+                               HLTError("Maximum burst error length not specified for -bursterrors.");
+                               return -EINVAL;
+                       }
+                       AliHLTUInt64_t burstLength;
+                       if (not ConvertToPositiveInt(argv[i+1], burstLength)) return -EPROTO;
+                       if (argc <= i+2)
+                       {
+                               HLTError("Number of bit flips in a burst error not specified for -bursterrors.");
+                               return -EINVAL;
+                       }
+                       AliHLTUInt64_t burstCount;
+                       if (not ConvertToPositiveInt(argv[i+2], burstCount)) return -EPROTO;
+                       AddCorruptionCommand(
+                               kBurstErrors, minpos, maxpos, alignment,
+                               minposrel, maxposrel, useErrorRate, errorrate,
+                               minerrors, maxerrors, burstLength, burstCount
+                       );
+                       i += 2;
+                       continue;
+               }
+               
+               result = CheckForCommandWithPatterns("-replace", kReplace,
+                               i, argc, argv, minpos, maxpos, alignment,
+                               minposrel, maxposrel, useErrorRate,
+                               errorrate, minerrors, maxerrors
+                       );
+               if (result == 1) continue;
+               if (result < 0) return result;
+               
+               result = CheckForCommandWithPatterns("-insert", kInsert,
+                               i, argc, argv, minpos, maxpos, alignment,
+                               minposrel, maxposrel, useErrorRate,
+                               errorrate, minerrors, maxerrors
+                       );
+               if (result == 1) continue;
+               if (result < 0) return result;
+               
+               result = CheckForCommandWithMinMax("-replace-random", kReplaceRandom,
+                               i, argc, argv, minpos, maxpos, alignment,
+                               minposrel, maxposrel, useErrorRate,
+                               errorrate, minerrors, maxerrors
+                       );
+               if (result == 1) continue;
+               if (result < 0) return result;
+               
+               result = CheckForCommandWithMinMax("-insert-random", kInsertRandom,
+                               i, argc, argv, minpos, maxpos, alignment,
+                               minposrel, maxposrel, useErrorRate,
+                               errorrate, minerrors, maxerrors
+                       );
+               if (result == 1) continue;
+               if (result < 0) return result;
+               
+               result = CheckForCommandWithMinMax("-remove", kRemove,
+                               i, argc, argv, minpos, maxpos, alignment,
+                               minposrel, maxposrel, useErrorRate,
+                               errorrate, minerrors, maxerrors
+                       );
+               if (result == 1) continue;
+               if (result < 0) return result;
+               
+               HLTError("Unknown option '%s'.", argv[i]);
+               return -EINVAL;
+       } // for loop
+       
+       // If no errors were specified then set to 1% single bit corruption.
+       if (fCorruptionInfoList.size() == 0)
+       {
+               minpos = 0;
+               maxpos = 0xFFFFFFFFFFFFFFFFull;
+               alignment = 1;
+               useErrorRate = true;
+               errorrate = 0.001;
+               AddCorruptionCommand(
+                       kSingleFlips, minpos, maxpos, alignment, useErrorRate, errorrate
+               );
+       }
+       
+       gRandom->SetSeed(0); // Use current time.
+       
+       HLTInfo("Starting Corruptor Component.");
+       return 0;
+}
+
+
+Int_t AliHLTCorruptorComponent::DoDeinit()
+{
+       // Cleans up the corruptor component.
+       fBlockIdList.clear();
+       return 0;
+}
+
+
+bool AliHLTCorruptorComponent::ShouldProcess(const AliHLTComponentBlockData* block) const
+{
+       if (fBlockIdList.size() == 0) return true;
+       for (size_t i = 0; i < fBlockIdList.size(); ++i)
+       {
+               AliBlockId id = fBlockIdList[i];
+               AliHLTComponentDataType type = AliHLTComponentDataTypeInitializer(
+                               id.fTypeSet ? id.fType : kAliHLTAnyDataType,
+                               id.fOriginSet ? id.fType.fOrigin : kAliHLTDataOriginAny
+                       );
+               if (type != block->fDataType) continue;
+               if (id.fSpecSet and id.fSpec != block->fSpecification) continue;
+               return true;
+       }
+       return false;
+}
+
+
+void AliHLTCorruptorComponent::ApplyCorruption(std::vector<bool>& bits) const
+{
+       // Applies corruption to the bit string.
+       
+       std::vector<bool> removed;
+       std::vector<bool> pattern;
+       for (size_t i = 0; i < fCorruptionInfoList.size(); ++i)
+       {
+               AliCorruptionInfo info = fCorruptionInfoList[i];
+#ifdef DEBUG
+               const char* cmdtype = NULL;
+               switch (info.fType)
+               {
+               case kSingleFlips:    cmdtype = "kSingleFlips"; break;
+               case kBurstErrors:    cmdtype = "kBurstErrors"; break;
+               case kReplace:        cmdtype = "kReplace"; break;
+               case kReplaceRandom:  cmdtype = "kReplaceRandom"; break;
+               case kInsert:         cmdtype = "kInsert"; break;
+               case kInsertRandom:   cmdtype = "kInsertRandom"; break;
+               case kRemove:         cmdtype = "kRemove"; break;
+               default:              cmdtype = "UNKNOWN"; break;
+               }
+               HLTDebug("Processing corruption command %u of %u, fType = %s,"
+                       " fMinRange = %llu, fMaxRange = %llu, fAlignment = %llu,"
+                       " fUseRate = %s, fRate = %.16f, fMinErrors = %llu, fMaxErrors = %llu"
+                       " fBurstErrorLength = %llu, fBurstErrorCount = %llu,"
+                       " fMinBits = %llu, fMaxBits = %llu, fFirstPattern = %llu, fLastPattern = %llu.",
+                       i, fCorruptionInfoList.size(), cmdtype,
+                       info.fMinRange, info.fMaxRange, info.fAlignment,
+                       (info.fUseRate ? "true" : "false"), info.fRate,
+                       info.fMinErrors, info.fMaxErrors,
+                       info.fBurstErrorLength, info.fBurstErrorCount,
+                       info.fMinBits, info.fMaxBits,
+                       AliHLTUInt64_t(info.fFirstPattern), AliHLTUInt64_t(info.fLastPattern)
+               );
+#endif // DEBUG
+               
+               // Calculate the range (and adjust for buffer size)
+               AliHLTUInt64_t minrange = info.fMinRangeRelative ? bits.size() - info.fMinRange : info.fMinRange;
+               AliHLTUInt64_t maxrange = info.fMaxRangeRelative ? bits.size() - info.fMaxRange : info.fMaxRange;
+               if (minrange == 0xFFFFFFFFFFFFFFFFull)
+               {
+                       if (info.fType == kInsert or info.fType == kInsertRandom or bits.size() == 0)
+                       {
+                               minrange = bits.size();
+                       }
+                       else
+                       {
+                               minrange = bits.size() - 1;
+                       }
+               }
+               if (maxrange == 0xFFFFFFFFFFFFFFFFull)
+               {
+                       if (info.fType == kInsert or info.fType == kInsertRandom or bits.size() == 0)
+                       {
+                               maxrange = bits.size();
+                       }
+                       else
+                       {
+                               maxrange = bits.size() - 1;
+                       }
+               }
+               if (maxrange < minrange) maxrange = minrange;
+               
+               // Select the correct number of errors to generate.
+               AliHLTUInt64_t errorcount = 0;
+               if (info.fUseRate)
+               {
+                       errorcount = AliHLTUInt64_t(bits.size() * info.fRate);
+               }
+               else
+               {
+                       AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                               | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                       errorcount = rnum % (info.fMaxErrors - info.fMinErrors + 1) + info.fMinErrors;
+               }
+               
+               // Build the pattern bits for a replace or insert command.
+               if (info.fType == kReplace or info.fType == kInsert)
+               {
+                       pattern.clear();
+                       for (size_t k = info.fFirstPattern; k < info.fLastPattern; ++k)
+                       {
+                               const AliPattern& pat = fPatterns[k];
+                               if (pat.fUseRemoved)
+                               {
+                                       pattern.insert(pattern.end(), removed.begin(), removed.end());
+                               }
+                               else
+                               {
+                                       for (AliHLTUInt8_t j = 0; j < pat.fWidth; ++j)
+                                       {
+                                               pattern.push_back( ((pat.fPattern >> j) & 0x1) == 0x1 );
+                                       }
+                               }
+                       }
+               }
+               
+               // Find a random value for the number of bits to use for the corresponding
+               // replace-random, insert-random and remove commands.
+               AliHLTUInt64_t bitcount = 0;
+               if (info.fType == kReplaceRandom or info.fType == kInsertRandom or info.fType == kRemove)
+               {
+                       AliHLTUInt64_t minbits = info.fMinBits;
+                       AliHLTUInt64_t maxbits = info.fMaxBits;
+                       if (minbits == 0xFFFFFFFFFFFFFFFFull) minbits = bits.size();
+                       if (maxbits == 0xFFFFFFFFFFFFFFFFull) maxbits = bits.size();
+                       if (maxbits < minbits) maxbits = minbits;
+                       AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                             | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                       bitcount = rnum % (maxbits - minbits + 1) + minbits;
+               }
+               
+               switch (info.fType)
+               {
+               case kSingleFlips:
+                       for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
+                       {
+                               AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                               AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
+                               pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
+                               if (not (pos < bits.size())) continue;
+                               bits[pos] = not bits[pos];
+                       }
+                       break;
+               case kBurstErrors:
+                       for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
+                       {
+                               AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                               AliHLTUInt64_t firstpos = rnum % (maxrange - minrange + 1) + minrange;
+                               firstpos = ((firstpos - minrange) / info.fAlignment) * info.fAlignment + minrange;
+                               AliHLTUInt64_t lastpos = firstpos + info.fBurstErrorLength;
+                               if (lastpos < firstpos)
+                               {
+                                       HLTWarning("Burst error length %llu is too large and caused an overflow.",
+                                               info.fBurstErrorLength
+                                       );
+                                       lastpos = firstpos;
+                               }
+                               if (lastpos == firstpos) continue;
+                               for (AliHLTUInt64_t j = 0; j < info.fBurstErrorCount; ++j)
+                               {
+                                       rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                                       AliHLTUInt64_t pos = rnum % (lastpos - firstpos) + firstpos;
+                                       if (not (pos < bits.size())) continue;
+                                       bits[pos] = not bits[pos];
+                               }
+                       }
+                       break;
+               case kReplace:
+                       for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
+                       {
+                               AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                               AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
+                               pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
+                               for (UInt_t j = pos; j < pos + pattern.size() and j < bits.size(); ++j)
+                               {
+                                       bits[j] = pattern[j-pos];
+                               }
+                       }
+                       break;
+               case kReplaceRandom:
+                       for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
+                       {
+                               AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                               AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
+                               pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
+                               for (UInt_t j = pos; j < pos + bitcount and j < bits.size(); ++j)
+                               {
+                                       bits[j] = gRandom->Integer(2) == 1;
+                               }
+                       }
+                       break;
+               case kInsert:
+                       for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
+                       {
+                               AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                               AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
+                               pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
+                               if (not (pos <= bits.size())) continue;
+                               bits.insert(bits.begin() + pos, pattern.begin(), pattern.end());
+                       }
+                       break;
+               case kInsertRandom:
+                       for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
+                       {
+                               AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                               AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
+                               pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
+                               if (not (pos <= bits.size())) continue;
+                               std::vector<bool> newbits;
+                               for (UInt_t j = 0; j < bitcount; ++j)
+                               {
+                                       newbits.push_back(gRandom->Integer(2) == 1);
+                               }
+                               bits.insert(bits.begin() + pos, newbits.begin(), newbits.end());
+                       }
+                       break;
+               case kRemove:
+                       removed.clear();
+                       for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
+                       {
+                               AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
+                                                       | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
+                               AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
+                               pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
+                               if (not (pos < bits.size())) continue;
+                               AliHLTUInt64_t end = pos + bitcount;
+                               if (end > bits.size()) end = bits.size();
+                               removed.insert(removed.begin(), bits.begin() + pos, bits.begin() + end);
+                               bits.erase(bits.begin() + pos, bits.begin() + end);
+                       }
+                       break;
+               default:
+                       HLTWarning("Received an unknown corruption type. There must be a program bug!");
+                       continue;
+               }
+       }
+}
+
+
+int AliHLTCorruptorComponent::DoEvent(
+               const AliHLTComponentEventData& evtData,
+               const AliHLTComponentBlockData* blocks, 
+               AliHLTComponentTriggerData& /*trigData*/,
+               AliHLTUInt8_t* outputPtr,
+               AliHLTUInt32_t& size,
+               AliHLTComponentBlockDataList& outputBlocks
+       )
+{
+       // Processes the input data blocks.
+       // The data blocks will be copied to the output and corrupted in some way.
+       
+       AliHLTUInt8_t* output = outputPtr;
+       AliHLTUInt32_t totalSize = 0;
+       
+       for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; ++n)
+       {
+               HLTDebug("Processing block %d, of type '%s' with specification 0x%8.8X.",
+                       n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
+               );
+               if (not ShouldProcess(blocks + n))
+               {
+                       Forward();
+                       continue;
+               }
+               
+               // Convert data block buffer to a bit string.
+               std::vector<bool> bits;
+               const AliHLTUInt8_t* buffer = reinterpret_cast<const AliHLTUInt8_t*>(blocks[n].fPtr);
+               for (AliHLTUInt32_t i = 0; i < blocks[n].fSize; ++i)
+               {
+                       for (AliHLTUInt8_t j = 0; j < 8; ++j)
+                       {
+                               bits.push_back( ((buffer[i] >> j) & 0x1) == 0x1 );
+                       }
+               }
+               
+               ApplyCorruption(bits);
+               
+               // Convert bit string back to a data buffer.
+               if (bits.size() > 0xFFFFFFFFull * 8)
+               {
+                       HLTWarning("The internal bit string representation is too large for the output buffer. Skipping block.");
+                       continue;
+               }
+               AliHLTUInt32_t blockSize = bits.size() / 8;
+               if (bits.size() % 8 > 0) ++blockSize;
+               
+               if (totalSize + blockSize > size)
+               {
+                       HLTError("Out of buffer space. Require %d bytes but have %d bytes of buffer space.",
+                               totalSize + blockSize, size
+                       );
+                       fBufferMultiplier *= 8;
+                       return -ENOSPC;
+               }
+               
+               memset(output, 0x0, blockSize);
+               for (size_t i = 0; i < bits.size(); ++i)
+               {
+                       AliHLTUInt32_t byte = i / 8;
+                       AliHLTUInt32_t bit = i % 8;
+                       output[byte] = output[byte] | (bits[i] << bit);
+               }
+               
+               AliHLTComponentBlockData bd;
+               FillBlockData(bd);
+               bd.fPtr = outputPtr;
+               bd.fOffset = totalSize;
+               bd.fSize = blockSize;
+               bd.fDataType = blocks[n].fDataType;
+               bd.fSpecification = blocks[n].fSpecification;
+               outputBlocks.push_back(bd);
+               
+               totalSize += blockSize;
+               output += blockSize;
+       }
+       
+       size = totalSize; // Set the correct output size.
+       return 0;
+}
diff --git a/HLT/BASE/util/AliHLTCorruptorComponent.h b/HLT/BASE/util/AliHLTCorruptorComponent.h
new file mode 100644 (file)
index 0000000..fd2918e
--- /dev/null
@@ -0,0 +1,392 @@
+//-*- Mode: C++ -*-
+// $Id: $
+#ifndef ALIHLTCORRUPTORCOMPONENT_H
+#define ALIHLTCORRUPTORCOMPONENT_H
+/* This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ * See cxx source for full Copyright notice                               */
+
+/// \file   AliHLTCorruptorComponent.h
+/// \author Artur Szostak <artursz@iafrica.com>
+/// \date   5 Aug 2010
+/// \brief  Declaration of the AliHLTCorruptorComponent component class.
+
+#include "AliHLTProcessor.h"
+#include <vector>
+
+/**
+ * \class AliHLTCorruptorComponent
+ * The corruptor component is used for testing purposes. It should be used to corrupt
+ * input data meant for a normal processing component to check the stable behaviour
+ * of such a component to data corruption.
+ * The component will copy all input data blocks that it will corrupt to the output
+ * and modify the data by corrupting it in some way. This includes removing parts of
+ * the data, adding garbage to it or flipping single bits.
+ * One can select which data block types to modify; then unmodified data blocks are
+ * just forwarded.
+ *
+ * <h2>General properties:</h2>
+ *
+ * Component ID: \b CorruptorComponent <br>
+ * Library: \b libAliHLTUtil.so   <br>
+ * Input Data Types:  ::kAliHLTAnyDataType <br>
+ * Output Data Types: ::kAliHLTAnyDataType <br>
+ *
+ * <h2>Mandatory arguments:</h2>
+ * None.
+ *
+ * <h2>Optional arguments:</h2>
+ * \li -seed <i>number</i> <br>
+ *      Sets the random number generator's seed value. The default value of zero
+ *      forces the generator to use the current time for the seed.
+ * \li -datatype <i>id</i> <i>origin</i> <br>
+ *      Data block type ID and origin to filter on. Only blocks with this type are
+ *      modified.
+ * \li -origin <i>origin</i> <br>
+ *      Data block origin to filter on. Only blocks with this origin are modified.
+ * \li -typeid <i>id</i> <br>
+ *      Data block type ID to filter on. Only blocks with this type ID are modified.
+ * \li -dataspec <i>specification</i> <br>
+ *      Data block specification to filter on. Only blocks with this specification
+ *      are modified.
+ * \li -range <i>min</i> <i>max</i> <br>
+ *      Sets the range that the current corruption settings will be applied to.
+ *      The current corruption settings are selected with "-singleflips",
+ *      "-bursterrors", "-replace", "-insert" and "-remove".
+ *      The min/max values specify the range in bytes. One can also specify it on
+ *      the bit level with the following syntax: "\<byte\>:\<bit\>",
+ *      where \<byte\> indicates the byte position counted from zero, \<bit\>
+ *      indicates the bit position inside the byte, which can be one of [0..7].
+ *      An example of using the "-range" option: "-range 3:2 4:7". This indicates
+ *      a range of 14 bits from the 4th byte, bit 3 to the 5th byte up to and
+ *      including bit 8.
+ *      The special tags "min" and "max" can be used as placeholders for <i>min</i>
+ *      and <i>max</i> respectively. These will automatically use the minimum and
+ *      maximum size for the data block.
+ *      One can also use the syntax: "max-\<byte\>:\<bit\>", which allows to select
+ *      positions relative to the end of the block.
+ * \li -alignment <i>value</i> <br>
+ *      Sets the alignment in bits to use for the applied errors.
+ *      For example if one wants to apply errors to locations aligned to 16 bit
+ *      words, then <i>value</i> should be 16. With the default value equal to 1.
+ *      The alignment is relative to the start of the range given by "-range".
+ *      Thus, the location <i>l</i> is calculated with:
+ *        <i>l</i> = floor((<i>r</i> - <i>m</i>) / <i>value</i>) * <i>value</i> + <i>m</i>
+ *      where <i>r</i> is a random number chosen in the current range, <i>m</i> is
+ *      the minimum bit position of the range and <i>value</i> is the alignment value.
+ * \li -errorrate <i>rate</i> <br>
+ *      Sets the rate of errors to apply to the current range as a percentage or
+ *      fraction of the current block size. If no range has been selected then the
+ *      rate is for the whole data block by default.
+ * \li -errorcount <i>min</i> <i>max</i> <br>
+ *      This is an alternative to "-errorrate", where a random number of errors is
+ *      generated within the range [<i>min</i>..<i>max</i>]. If <i>min</i> is set
+ *      to equal <i>max</i> then a fixed number of errors is always applied to the
+ *      current range.
+ * \li -singleflips <br>
+ *      Generates <i>n</i> single bit errors distributed evenly within the current
+ *      data range given by "-range". <i>n</i> is determined either from the rate
+ *      given by "-errorrate" or from the range given by "-errorcount".
+ * \li -bursterrors <i>length</i> <i>count</i> <br>
+ *      Generates burst errors in the current data range. Burst errors have <i>count</i>
+ *      number of bit flips within a <i>length</i> number of consecutive bits
+ *      closely spaced together. The total number of burst errors generated is
+ *      controlled by the "-errorrate" or "-errorcount" options.
+ * \li -replace <i>pattern</i> [<i>pattern</i> ...] <br>
+ *      Allows one to replace parts of the data with the given pattern or consecutive
+ *      patterns. The format of <i>pattern</i> should be "\<value\>/\<width\>",
+ *      where \<value\> is a number or hexadecimal value (interpreted in little
+ *      endian format) to be used as the replacement. \<width\> is an optional
+ *      field to indicate the width of the pattern in bits. The maximum valid value
+ *      for \<width\> is 64.
+ *      A special symbol "removed" can be used for the pattern, which will cause
+ *      the command to use the bits last removed by the "-remove" command. If no
+ *      bits were removed or no previous "-remove" command was issued then nothing
+ *      is replaced.
+ *      Note that the location of the replacement is controlled by the "-range"
+ *      option. Normally the position is randomly selected within this range.
+ *      For specific placement one can use "-range x x" where x is the exact
+ *      position of the replacement. The total number of replacements is
+ *      controlled by the "-errorrate" or "-errorcount" options.
+ * \li -replace-random <i>min</i> <i>max</i> <br>
+ *      Replaces a random number of bits within the range [<i>min</i>..<i>max</i>]
+ *      from locations selected within the current range and for a total number of
+ *      times controlled by the "-errorrate" or "-errorcount" options.
+ *      The placeholder symbols "min" and "max" can be used.
+ * \li -insert <i>pattern</i> [<i>pattern</i> ...] <br>
+ *      Allows one to insert a pattern or patterns into the data within the current
+ *      data range. The format of <i>pattern</i> is the same as for "-replace".
+ *      The total number of insertions is controlled by the "-errorrate" or
+ *      "-errorcount" options and the locations of the insertions by "-range".
+ * \li -insert-random <i>min</i> <i>max</i> <br>
+ *      Inserts a random number of bits within the range [<i>min</i>..<i>max</i>]
+ *      into locations selected within the current range and for a total number of
+ *      times controlled by the "-errorrate" or "-errorcount" options.
+ * \li -remove <i>min</i> <i>max</i> <br>
+ *      Removes a random number of bits within the range [<i>min</i>..<i>max</i>]
+ *      at locations selected within the current range and for a total number of
+ *      times controlled by the "-errorrate" or "-errorcount" options.
+ *      For removing bytes one needs to specify a multiple of 8. Also, to remove
+ *      a fixed number of bits one must set <i>min</i> equal <i>max</i>.
+ *
+ * \note All corruption operations are applied in the order they as specified on
+ *       the command line. So the first argument will be applied first, and the
+ *       last one last.
+ * \note The default corruption settings is to introduce only 1% single bit flips
+ *       if no other settings are set and for all data block types if none specified.
+ *
+ * <h2>Configuration:</h2>
+ * Can only be configured with the command line arguments.
+ *
+ * <h2>Default CDB entries:</h2>
+ * None.
+ *
+ * <h2>Performance:</h2>
+ * Depends on complexity of corruption, but typically should easily run with a
+ * 3kHz event rate.
+ *
+ * <h2>Memory consumption:</h2>
+ * The amount of memory is used as up to 8 times the size of the largest input
+ * data block.
+ *
+ * <h2>Output size:</h2>
+ * The same as the input data size, unless garbage insertion options are used.
+ * In that case the output size depends on the exact settings.
+ *
+ * \ingroup alihlt_util_components
+ */
+class AliHLTCorruptorComponent : public AliHLTProcessor
+{
+public:
+       
+       AliHLTCorruptorComponent();
+       virtual ~AliHLTCorruptorComponent();
+       
+       // Methods inherited from AliHLTComponent:
+       virtual const char* GetComponentID();
+       virtual void GetInputDataTypes(AliHLTComponentDataTypeList& list);
+       virtual AliHLTComponentDataType GetOutputDataType();
+       virtual int GetOutputDataTypes(AliHLTComponentDataTypeList& list);
+       virtual void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier);
+       virtual AliHLTComponent* Spawn();
+       virtual Int_t DoInit(int argc, const char** argv);
+       virtual Int_t DoDeinit();
+       
+protected:
+       
+       // Method inherited from AliHLTProcessor:
+       virtual int DoEvent(
+                       const AliHLTComponentEventData& evtData,
+                       const AliHLTComponentBlockData* blocks, 
+                       AliHLTComponentTriggerData& trigData,
+                       AliHLTUInt8_t* outputPtr, 
+                       AliHLTUInt32_t& size,
+                       AliHLTComponentBlockDataList& outputBlocks
+               );
+       
+       using AliHLTProcessor::DoEvent;
+       
+private:
+       
+       enum AliCorruptionType
+       {
+               kUnknownErrorType = 0,  // Unknown corruption type.
+               kSingleFlips,           // Single bit flip errors.
+               kBurstErrors,           // Burst errors.
+               kReplace,               // Replacement of data.
+               kReplaceRandom,         // Replacement of data with random bits.
+               kInsert,                // Insertion of data.
+               kInsertRandom,          // Insertion of random data.
+               kRemove,                // Removal of data.
+       };
+       
+       struct AliBlockId
+       {
+               AliHLTComponentDataType fType;  // Data type and origin.
+               AliHLTUInt32_t fSpec;           // Data block specification.
+               bool fTypeSet;    // Flag indicating if the fType.fID field was set.
+               bool fOriginSet;  // Flag indicating if the fType.fOrigin field was set.
+               bool fSpecSet;    // Flag indicating if the fSpec field was set.
+       };
+       
+       typedef std::vector<AliBlockId> AliBlockIdList;
+       
+       struct AliPattern
+       {
+               AliHLTUInt64_t fPattern;  // The bit pattern.
+               AliHLTUInt8_t fWidth;     // The width of the bit pattern in bits.
+               bool fUseRemoved;         // Indicates if the removed bits should be used.
+       };
+       
+       typedef std::vector<AliPattern> AliPatternList;
+       
+       struct AliCorruptionInfo
+       {
+               AliCorruptionType fType;  // The type of error/modification being applied.
+               AliHLTUInt64_t fMinRange;  // The minimum range to apply the errors in bits.
+               AliHLTUInt64_t fMaxRange;  // The maximum range to apply the errors in bits.
+               AliHLTUInt64_t fAlignment;  // The alignment to use for error location selection in bits.
+               bool fMinRangeRelative; // Indicates that the fMinRange value is relative to the end of the buffer.
+               bool fMaxRangeRelative; // Indicates that the fMaxRange value is relative to the end of the buffer.
+               bool fUseRate;  // Indicates if the rate or the range should be used.
+               union
+               {
+                       double fRate;  // The rate that should be used if fUseRate == true.
+                       struct
+                       {
+                               AliHLTUInt64_t fMinErrors;  // The minimum error count that should be used if fUseRate == false.
+                               AliHLTUInt64_t fMaxErrors;  // The maximum error count that should be used if fUseRate == false.
+                       };
+               };
+               union
+               {
+                       struct
+                       {
+                               AliHLTUInt64_t fBurstErrorLength;  // Maximum burst error length in bits.
+                               AliHLTUInt64_t fBurstErrorCount;   // Number of bit flips in a burst error.
+                       };
+                       struct
+                       {
+                               AliHLTUInt64_t fMinBits;  // Minimum number of bits to replace/insert/remove.
+                               AliHLTUInt64_t fMaxBits;  // Maximum number of bits to replace/insert/remove.
+                       };
+                       struct
+                       {
+                               size_t fFirstPattern;  // First pattern to use for replacement or insertion.
+                               size_t fLastPattern;   // Last pattern to use for replacement or insertion.
+                       };
+               };
+       };
+       
+       typedef std::vector<AliCorruptionInfo> AliCorruptionInfoList;
+       
+       /**
+        * Converts the value to a positive 64 bit integer.
+        * [in]  \param value  The command line parameter to convert.
+        * [out] \param num  The result is stored in this variable.
+        * [in]  \param printErrors Indicates if error messages should be generated.
+        * \returns true if the convertion was successful.
+        */
+       bool ConvertToPositiveInt(const char* value, AliHLTUInt64_t& num, bool printErrors = true) const;
+       
+       /**
+        * Converts the value to a bit position.
+        * [in]  \param value  The command line parameter to convert.
+        * [out] \param pos  The result is stored in this variable.
+        * [out] \param relative  Flag filled to indicate if the resulting position
+        *                        is relative to the end of the data block buffer.
+        * [in]  \param printErrors Indicates if error messages should be generated.
+        * \returns true if the convertion was successful.
+        */
+       bool ConvertToBitPosition(const char* value, AliHLTUInt64_t& pos, bool& relative, bool printErrors = true) const;
+       
+       /**
+        * Converts the value to a percentage fraction in the range [0..1].
+        * [in]  \param value  The command line parameter to convert.
+        * [out] \param num  The result is stored in this variable.
+        * [in]  \param printErrors Indicates if error messages should be generated.
+        * \returns true if the convertion was successful.
+        */
+       bool ConvertToPercentage(const char* value, double& num, bool printErrors = true) const;
+       
+       /**
+        * Converts a string to a pattern for the -replace and -insert command line options.
+        * [in]  \param value  The command line parameter to convert.
+        * [out] \param pattern  The resulting pattern structure.
+        * [in]  \param printErrors Indicates if error messages should be generated.
+        * \returns true if the convertion was successful.
+        */
+       bool ConvertToPattern(const char* value, AliPattern& pattern, bool printErrors = true) const;
+       
+       /**
+        * Adds a data block type to the current data block filter rule.
+        * A new filter rule is created if the type is already set.
+        * \param type  The type of the data block.
+        * \returns true if the type string was valid.
+        */
+       bool AddBlockTypeId(const char* type);
+       
+       /**
+        * Adds a data block origin to the current data block filter rule.
+        * A new filter rule is created if the origin is already set.
+        * \param origin  The origin of the data block.
+        * \returns true if the origin string was valid.
+        */
+       bool AddBlockOrigin(const char* origin);
+       
+       /**
+        * Adds a data block specification to the current data block filter rule.
+        * A new filter rule is created if the specification is already set.
+        * \param spec  The specification of the data block.
+        * \returns true if the specification string was a valid string.
+        */
+       bool AddBlockSpec(const char* spec);
+       
+       /**
+        * Adds a corruption command as a AliCorruptionInfo structure to the list
+        * of commands to apply to the input data blocks.
+        */
+       void AddCorruptionCommand(
+                       AliCorruptionType type,
+                       AliHLTUInt64_t minrange,
+                       AliHLTUInt64_t maxrange,
+                       AliHLTUInt64_t alignment,
+                       bool minRangeRelative,
+                       bool maxRangeRelative,
+                       bool userate = true,
+                       double rate = 0,
+                       AliHLTUInt64_t minerrors = 0,
+                       AliHLTUInt64_t maxerrors = 0,
+                       AliHLTUInt64_t burstlength = 0,
+                       AliHLTUInt64_t burstcount = 0,
+                       AliHLTUInt64_t minbits = 0,
+                       AliHLTUInt64_t maxbits = 0,
+                       size_t firstpattern = 0,
+                       size_t lastpattern = 0
+               );
+       
+       /// Parses command line parameters for a command with pattern fields.
+       int CheckForCommandWithPatterns(
+                       const char* name, AliCorruptionType type,
+                       int& i, int argc, const char** argv,
+                       AliHLTUInt64_t minrange,
+                       AliHLTUInt64_t maxrange,
+                       AliHLTUInt64_t alignment,
+                       bool minRangeRelative,
+                       bool maxRangeRelative,
+                       bool userate,
+                       double errorrate,
+                       AliHLTUInt64_t minerrors,
+                       AliHLTUInt64_t maxerrors
+               );
+       
+       /// Parses command line parameters for a command with min and max fields.
+       int CheckForCommandWithMinMax(
+                       const char* name, AliCorruptionType type,
+                       int& i, int argc, const char** argv,
+                       AliHLTUInt64_t minrange,
+                       AliHLTUInt64_t maxrange,
+                       AliHLTUInt64_t alignment,
+                       bool minRangeRelative,
+                       bool maxRangeRelative,
+                       bool userate,
+                       double errorrate,
+                       AliHLTUInt64_t minerrors,
+                       AliHLTUInt64_t maxerrors
+               );
+       
+       /// Checks to see if a data block should be processed or not.
+       bool ShouldProcess(const AliHLTComponentBlockData* block) const;
+       
+       /// Applies the corruption commands to a bit string.
+       void ApplyCorruption(std::vector<bool>& bits) const;
+       
+       double fBufferMultiplier;  // The multiplier used by GetOutputDataSize.
+       AliBlockIdList fBlockIdList;  // The list of data block filters.
+       AliCorruptionInfoList fCorruptionInfoList;  // The list of corruptions to be applied.
+       AliPatternList fPatterns;  // Patterns to use for replacements or insertions.
+       
+       ClassDef(AliHLTCorruptorComponent, 0)  // Data corruption component for testing.
+};
+
+#endif // ALIHLTCORRUPTORCOMPONENT_H
diff --git a/HLT/BASE/util/test/testAliHLTCorruptorComponent.C b/HLT/BASE/util/test/testAliHLTCorruptorComponent.C
new file mode 100644 (file)
index 0000000..ef50181
--- /dev/null
@@ -0,0 +1,976 @@
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ *                                                                        *
+ * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
+ *                  for The ALICE HLT Project.                            *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/**
+ * @file   testCorruptorComponent.C
+ * @author Artur Szostak <artursz@iafrica.com>
+ * @date   5 Aug 2010
+ *
+ * This macro is used to test the basic functionality of the AliHLTCorruptorComponent
+ * class.
+ */
+
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include "Riostream.h"
+#include "TSystem.h"
+#include "TClassTable.h"
+#include "TBits.h"
+#include "AliLog.h"
+#include "AliHLTSystem.h"
+#include "AliHLTConfiguration.h"
+#include <fstream>
+#include <cstdlib>
+#endif
+
+/**
+ * Creates the input data for the test.
+ * It is just a file of 256 bytes with all zeros.
+ */
+void GenerateInputData(bool debug = false)
+{
+       using namespace std;
+       const char* filename = "corruptorInputTestFile.dat";
+       fstream file(filename, ios::trunc | ios::out | ios::binary);
+       if (! file)
+       {
+               if (debug) cerr << "ERROR: Could not create file " << filename << endl;
+               return;
+       }
+       char buffer[256];
+       memset(buffer, 0x0, sizeof(buffer));
+       file.write(buffer, sizeof(buffer));
+       if (! file)
+       {
+               if (debug) cerr << "ERROR: I/O error when writing to file " << filename << endl;
+               return;
+       }
+       file.close();
+}
+
+/**
+ * Routine to check that the filtering of the data blocks works with the corruptor
+ * component. Only filtered blocks should be modified.
+ */
+void RunChainToCheckFiltering(bool debug = false)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       if (debug)
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       else
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogError);
+       }
+       
+       const int numSources = 4;
+       const char* fileTypeNames[numSources] = {
+               "-datatype SOMEDATA HLT -dataspec 0x0",
+               "-datatype MOREDATA HLT -dataspec 0x0",
+               "-datatype SOMEDATA TPC -dataspec 0x0",
+               "-datatype SOMEDATA HLT -dataspec 0xFF"
+       };
+       TString allSources = "";
+       for (int i = 0; i < numSources; ++i)
+       {
+               TString sourceName = Form("source%d", i+1);
+               if (allSources.Length() > 0) allSources += " ";
+               allSources += sourceName;
+               AliHLTConfiguration src(
+                       sourceName.Data(),
+                       "FilePublisher",
+                       "",
+                       Form("%s -datafile corruptorInputTestFile.dat", fileTypeNames[i])
+               );
+       }
+       
+       const int numProcessors = 4;
+       const char* commandLine[numProcessors] = {
+               "-datatype MOREDATA HLT -dataspec 0x0",
+               "-datatype SOMEDATA TPC -dataspec 0x0",
+               "-datatype SOMEDATA HLT -dataspec 0xFF",
+               "-dataspec 0xFF -typeid '*******' -typeid MOREDATA -dataspec 0x0"
+       };
+       for (int i = 0; i < numProcessors; ++i)
+       {
+               TString processorName = Form("processor%d", i+1);
+               AliHLTConfiguration prc(
+                       processorName.Data(),
+                       "CorruptorComponent",
+                       allSources.Data(),
+                       commandLine[i]
+               );
+               TString sinkName = Form("sink%d", i+1);
+               AliHLTConfiguration snk(
+                       sinkName.Data(),
+                       "FileWriter",
+                       processorName.Data(),
+                       Form("-specfmt -datafile corruptorOutputTestFile_sink%d.dat", i+1)
+               );
+               sys.BuildTaskList(sinkName.Data());
+       }
+       
+       sys.Run(1); // Run for 1 event.
+}
+
+/**
+ * Reads a file into a buffer.
+ * [in]  \param filename  The name of the file to read.
+ * [out] \param buffer  The buffer which is created to store the contents.
+ *                      Must be deleted with 'delete [] buffer' by caller if not NULL.
+ * [out] \param size  The size of the buffer created in bytes.
+ * [in]  \param debug  Indicates if debug messages should be printed.
+ * \returns true if the file was read, the buffer created and filled; false otherwise.
+ * \note The caller becomes the owner of the allocated buffer.
+ */
+bool ReadFile(const char* filename, char*& buffer, size_t& size, bool debug = false)
+{
+       buffer = NULL;
+       size = 0;
+       using namespace std;
+       fstream file(filename, ios::in | ios::binary);
+       if (! file)
+       {
+               if (debug) cerr << "ERROR: Could not open file " << filename << endl;
+               return false;
+       }
+       file.seekg(0, std::ios::end);
+       size_t filesize = file.tellg();
+       file.seekg(0, std::ios::beg);
+       if (! file)
+       {
+               if (debug) cerr << "ERROR: Could not get file size for " << filename << endl;
+               return false;
+       }
+       buffer = new char[filesize];
+       if (buffer == NULL)
+       {
+               if (debug) cerr << "ERROR: Cannot allocate more memory for buffers." << endl;
+               return false;
+       }
+       size = filesize;
+       file.read(buffer, size);
+       if (! file)
+       {
+               if (debug) cerr << "ERROR: I/O error when reading from file " << filename << endl;
+               return false;
+       }
+       return true;
+}
+
+/**
+ * Checks if the output data is as expected for the filtering.
+ * Only the output data blocks that were filtered should be modified.
+ */
+bool CheckFilteringOutput(bool debug = false)
+{
+       const int numBuffers = 5;
+       int sinknum[numBuffers] = {1, 2, 3, 4, 4};
+       const char* blocknum[numBuffers] = {
+               "0x00",
+               "0x00",
+               "0x00",
+               "0x00",
+               "0x01"
+       };
+       const char* blocktype[numBuffers] = {
+               "HLT:MOREDATA",
+               "TPC:SOMEDATA",
+               "HLT:SOMEDATA",
+               "HLT:SOMEDATA",
+               "HLT:MOREDATA"
+       };
+       const char* blockspec[numBuffers] = {
+               "0x00000000",
+               "0x00000000",
+               "0x000000ff",
+               "0x000000ff",
+               "0x00000000"
+       };
+       char* buffer[numBuffers];
+       size_t size[numBuffers];
+       for (int i = 0; i < numBuffers; ++i)
+       {
+               const char* filename = Form("corruptorOutputTestFile_sink%d_0x00000000_%s_%s_%s.dat",
+                                           sinknum[i], blocknum[i], blocktype[i], blockspec[i]
+                                          );
+               if (! ReadFile(filename, buffer[i], size[i], debug))
+               {
+                       if (! debug)
+                       {
+                               cerr << "ERROR: Filtering chain test did not generate correct output files."
+                                       << " Run with 'debug = true' for more details." << endl;
+                       }
+                       return false;
+               }
+               delete [] buffer[i];
+       }
+       
+       return true;
+}
+
+/**
+ * Routine to check the single bit flip option.
+ */
+void RunChainToCheckSingleFlips(bool debug = false)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       if (debug)
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       else
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogError);
+       }
+       
+       AliHLTConfiguration src(
+               "source",
+               "FilePublisher",
+               "",
+               "-datatype SOMEDATA HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc(
+               "processor",
+               "CorruptorComponent",
+               "source",
+               "-seed 123 -datatype SOMEDATA HLT -range 128 max -alignment 4 -errorcount 5 5 -singleflips"
+       );
+       AliHLTConfiguration snk(
+               "sink",
+               "FileWriter",
+               "processor",
+               "-datafile corruptorOutputTestFile_single.dat"
+       );
+       
+       sys.BuildTaskList("sink");
+       sys.Run(1); // Run for 1 event.
+}
+
+/**
+ * Checks if the output data is as expected for the single bit flip option.
+ */
+bool CheckSingleFlipOutput(bool debug = false)
+{
+       char* buffer = NULL;
+       size_t size = 0;
+       if (! ReadFile("corruptorOutputTestFile_single_0x00000000_0x00_HLT:SOMEDATA.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Single flips chain test did not generate correct"
+                               << " output files. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 256)
+       {
+               cerr << "ERROR: The output file is not the expected 256 bytes in size"
+                       << " when testing the -singleflips option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that the first 128 bytes are zero.
+       for (int i = 0; i < 128; ++i)
+       {
+               if (buffer[i] != 0x0)
+               {
+                       cerr << "ERROR: The first 128 bytes were not left as zeros when testing"
+                               << " the -singleflips option." << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       // Check that the correct number of bit flips happened in the last 128 bytes.
+       TBits bits(128*8);
+       bits.Set(128*8, buffer+128);
+       UInt_t bitcount = bits.CountBits();
+       if (bitcount != 5)
+       {
+               cerr << "ERROR: When testing the -singleflips option,"
+                       << " the number of bits flipped in the output buffer was "
+                       << bitcount << ", but we expect exactly 5 bit flips."
+                       << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that the bit flips are only on 4 bit aligned addresses.
+       for (UInt_t j = 128*8; j < 256*8; ++j)
+       {
+               if (bits[j] && (j & 0x7) != 0)
+               {
+                       cerr << "ERROR: When testing the -singleflips option, bit " << j
+                               << " was flipped in the output buffer,"
+                               << " but it is not aligned to a 4 bit word boundary."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       
+       delete [] buffer;
+       return true;
+}
+
+/**
+ * Routine to check the burst error option.
+ */
+void RunChainToCheckBurstErrors(bool debug = false)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       if (debug)
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       else
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogError);
+       }
+       
+       AliHLTConfiguration src(
+               "source",
+               "FilePublisher",
+               "",
+               "-datatype SOMEDATA HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc(
+               "processor",
+               "CorruptorComponent",
+               "source",
+               "-seed 123 -datatype SOMEDATA HLT -range 0 256 -alignment 32 -errorcount 3 3 -bursterrors 16 8"
+       );
+       AliHLTConfiguration snk(
+               "sink",
+               "FileWriter",
+               "processor",
+               "-datafile corruptorOutputTestFile_burst.dat"
+       );
+       
+       sys.BuildTaskList("sink");
+       sys.Run(1); // Run for 1 event.
+}
+
+/**
+ * Checks if the output data is as expected for the burst errors.
+ */
+bool CheckBurstErrorOutput(bool debug = false)
+{
+       char* buffer = NULL;
+       size_t size = 0;
+       if (! ReadFile("corruptorOutputTestFile_burst_0x00000000_0x00_HLT:SOMEDATA.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Burst error chain test did not generate correct"
+                               << " output files. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 256)
+       {
+               cerr << "ERROR: The output file is not the expected 256 bytes in size"
+                       << " when testing the -bursterrors option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       TBits bits(256*8);
+       bits.Set(256*8, buffer);
+       // Check that the bit flips are only on the lower part of the 32 bit words.
+       for (UInt_t j = 0; j < 256*8; ++j)
+       {
+               if (bits[j] && (j % 32) >= 16)
+               {
+                       cerr << "ERROR: When testing the -bursterrors option, bit " << j
+                               << " was flipped in the output buffer, but only the lower"
+                               << " part of any 32 bit word is supposed to be corrupted."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       
+       delete [] buffer;
+       return true;
+}
+
+/**
+ * Routine to check the replacement options.
+ */
+void RunChainToCheckReplaceErrors(bool debug = false)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       if (debug)
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       else
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogError);
+       }
+       
+       AliHLTConfiguration src1(
+               "source1",
+               "FilePublisher",
+               "",
+               "-datatype DATAAAAA HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc1(
+               "processor1",
+               "CorruptorComponent",
+               "source1",
+               "-datatype DATAAAAA HLT -range 128:4 128:4 -replace 0x1/1 0xF 0xF/3 -seed 1"
+       );
+       AliHLTConfiguration src2(
+               "source2",
+               "FilePublisher",
+               "",
+               "-datatype DATABBBB HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc2(
+               "processor2",
+               "CorruptorComponent",
+               "source2",
+               "-datatype DATABBBB HLT -seed 123 -range 8 8 -errorcount 1 1 -replace-random 64 64"
+       );
+       AliHLTConfiguration snk(
+               "sink",
+               "FileWriter",
+               "processor1 processor2",
+               "-datafile corruptorOutputTestFile_replace.dat"
+       );
+       
+       sys.BuildTaskList("sink");
+       sys.Run(1); // Run for 1 event.
+}
+
+/**
+ * Checks if the output data is as expected for the replacement commands.
+ */
+bool CheckReplaceErrorsOutput(bool debug = false)
+{
+       char* buffer = NULL;
+       size_t size = 0;
+       if (! ReadFile("corruptorOutputTestFile_replace_0x00000000_0x01_HLT:DATAAAAA.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Replace errors chain test did not generate correct"
+                               << " output files. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 256)
+       {
+               cerr << "ERROR: The output file is not the expected 256 bytes in size"
+                       << " when testing the -replace option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that the correct bits were set. All bits zero except 128:4 to 129:4
+       for (UInt_t j = 0; j < 128; ++j)
+       {
+               if (buffer[j] != 0)
+               {
+                       cerr << "ERROR: When testing the -replace option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       if (AliHLTUInt8_t(buffer[128]) != 0xF0 || AliHLTUInt8_t(buffer[129]) != 0x0F)
+       {
+               cerr << "ERROR: When testing the -replace option we found a value of "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[128]))) << " for byte 128 and "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[129]))) << " for byte 129,"
+                       << " but we expected values of 0xF0 and 0x0F respectively."
+                       << endl;
+               delete [] buffer;
+               return false;
+       }
+       for (UInt_t j = 130; j < 256; ++j)
+       {
+               if (buffer[j] != 0)
+               {
+                       cerr << "ERROR: When testing the -replace option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       delete [] buffer;
+       buffer = NULL;
+       size = 0;
+       // Now test the next buffer...
+       if (! ReadFile("corruptorOutputTestFile_replace_0x00000000_0x00_HLT:DATABBBB.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Replace errors chain test did not generate correct"
+                               << " output files. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 256)
+       {
+               cerr << "ERROR: The output file is not the expected 256 bytes in size"
+                       << " when testing the -replace-random option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that only bits in the second 64 bit word were set.
+       for (UInt_t j = 0; j < 8; ++j)
+       {
+               if (buffer[j] != 0x0)
+               {
+                       cerr << "ERROR: When testing the -replace-random option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       if ((reinterpret_cast<AliHLTUInt64_t*>(buffer))[1] == 0x0)
+       {
+               cerr << "ERROR: When testing the -replace-random option we found no bits set in bytes 8 to 15." << endl;
+               delete [] buffer;
+               return false;
+       }
+       for (UInt_t j = 16; j < 256; ++j)
+       {
+               if (buffer[j] != 0x0)
+               {
+                       cerr << "ERROR: When testing the -replace-random option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       delete [] buffer;
+       return true;
+}
+
+/**
+ * Routine to check the insertion options.
+ */
+void RunChainToCheckInsertErrors(bool debug = false)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       if (debug)
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       else
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogError);
+       }
+       
+       AliHLTConfiguration src1(
+               "source1",
+               "FilePublisher",
+               "",
+               "-datatype DATAAAAA HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc1(
+               "processor1",
+               "CorruptorComponent",
+               "source1",
+               "-datatype DATAAAAA HLT -range 128 128 -errorcount 1 1 -insert 0xCBA/12"
+       );
+       AliHLTConfiguration src2(
+               "source2",
+               "FilePublisher",
+               "",
+               "-datatype DATABBBB HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc2(
+               "processor2",
+               "CorruptorComponent",
+               "source2",
+               "-datatype DATABBBB HLT -seed 123 -range max max -errorcount 1 1 -insert-random 64 64"
+       );
+       AliHLTConfiguration snk(
+               "sink",
+               "FileWriter",
+               "processor1 processor2",
+               "-datafile corruptorOutputTestFile_insert.dat"
+       );
+       
+       sys.BuildTaskList("sink");
+       sys.Run(1); // Run for 1 event.
+}
+
+/**
+ * Checks if the output data is as expected for the insertion commands.
+ */
+bool CheckInsertErrorsOutput(bool debug = false)
+{
+       char* buffer = NULL;
+       size_t size = 0;
+       if (! ReadFile("corruptorOutputTestFile_insert_0x00000000_0x01_HLT:DATAAAAA.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Insert errors chain test did not generate correct"
+                               << " output files. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 258)
+       {
+               cerr << "ERROR: The output file is not the expected 258 bytes in size"
+                       << " when testing the -insert option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that the correct bits were set. All bits zero except 128 to 129
+       for (UInt_t j = 0; j < 128; ++j)
+       {
+               if (buffer[j] != 0)
+               {
+                       cerr << "ERROR: When testing the -insert option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       if (AliHLTUInt8_t(buffer[128]) != 0xBA || AliHLTUInt8_t(buffer[129]) != 0x0C)
+       {
+               cerr << "ERROR: When testing the -insert option we found a value of "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[128]))) << " for byte 128 and "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[129]))) << " for byte 129,"
+                       << " but we expected values of 0xBA and 0x0C respectively."
+                       << endl;
+               delete [] buffer;
+               return false;
+       }
+       for (UInt_t j = 130; j < 258; ++j)
+       {
+               if (buffer[j] != 0)
+               {
+                       cerr << "ERROR: When testing the -insert option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       delete [] buffer;
+       buffer = NULL;
+       size = 0;
+       // Now test the next buffer...
+       if (! ReadFile("corruptorOutputTestFile_insert_0x00000000_0x00_HLT:DATABBBB.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Insert errors chain test did not generate correct"
+                               << " output files. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 264)
+       {
+               cerr << "ERROR: The output file is not the expected 264 bytes in size"
+                       << " when testing the -insert-random option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that only bits in the last 64 bit word were set.
+       for (UInt_t j = 0; j < 256; ++j)
+       {
+               if (buffer[j] != 0x0)
+               {
+                       cerr << "ERROR: When testing the -insert-random option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       if ((reinterpret_cast<AliHLTUInt64_t*>(buffer))[32] == 0x0)
+       {
+               cerr << "ERROR: When testing the -insert-random option we found no bits set in bytes 256 to 263." << endl;
+               delete [] buffer;
+               return false;
+       }
+       delete [] buffer;
+       return true;
+}
+
+/**
+ * Routine to check the remove option.
+ */
+void RunChainToCheckRemoveErrors(bool debug = false)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       if (debug)
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       else
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogError);
+       }
+       
+       AliHLTConfiguration src(
+               "source",
+               "FilePublisher",
+               "",
+               "-datatype SOMEDATA HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc(
+               "processor",
+               "CorruptorComponent",
+               "source",
+               "-datatype SOMEDATA HLT -range 128 128 -errorcount 1 1 -replace 0x78563412/32 -remove 16 16 -range max max -insert removed"
+       );
+       AliHLTConfiguration snk(
+               "sink",
+               "FileWriter",
+               "processor",
+               "-datafile corruptorOutputTestFile_remove.dat"
+       );
+       
+       sys.BuildTaskList("sink");
+       sys.Run(1); // Run for 1 event.
+}
+
+/**
+ * Checks if the output data is as expected for the remove command.
+ */
+bool CheckRemoveErrorsOutput(bool debug = false)
+{
+       char* buffer = NULL;
+       size_t size = 0;
+       if (! ReadFile("corruptorOutputTestFile_remove_0x00000000_0x00_HLT:SOMEDATA.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Remove errors chain test did not generate correct"
+                               << " output file. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 256)
+       {
+               cerr << "ERROR: The output file is not the expected 256 bytes in size"
+                       << " when testing the -remove option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that the correct bits were removed and set.
+       for (UInt_t j = 0; j < 128; ++j)
+       {
+               if (buffer[j] != 0)
+               {
+                       cerr << "ERROR: When testing the -remove option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       if (AliHLTUInt8_t(buffer[128]) != 0x56 || AliHLTUInt8_t(buffer[129]) != 0x78)
+       {
+               cerr << "ERROR: When testing the -remove option we found a value of "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[128]))) << " for byte 128 and "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[129]))) << " for byte 129,"
+                       << " but we expected values of 0x56 and 0x78 respectively."
+                       << endl;
+               delete [] buffer;
+               return false;
+       }
+       for (UInt_t j = 130; j < 254; ++j)
+       {
+               if (buffer[j] != 0)
+               {
+                       cerr << "ERROR: When testing the -remove option we found bits set in byte"
+                               << j << " but the byte should be zero."
+                               << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       if (AliHLTUInt8_t(buffer[254]) != 0x12 || AliHLTUInt8_t(buffer[255]) != 0x34)
+       {
+               cerr << "ERROR: When testing the -remove option we found a value of "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[254]))) << " for byte 128 and "
+                       << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[255]))) << " for byte 129,"
+                       << " but we expected values of 0x12 and 0x34 respectively."
+                       << endl;
+               delete [] buffer;
+               return false;
+       }
+       delete [] buffer;
+       return true;
+}
+
+/**
+ * Routine to check the relative address option for "-range".
+ */
+void RunChainToCheckRelativeAddress(bool debug = false)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       if (debug)
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       else
+       {
+               sys.SetGlobalLoggingLevel(kHLTLogError);
+       }
+       
+       AliHLTConfiguration src(
+               "source",
+               "FilePublisher",
+               "",
+               "-datatype SOMEDATA HLT -dataspec 0x0 -datafile corruptorInputTestFile.dat"
+       );
+       AliHLTConfiguration prc(
+               "processor",
+               "CorruptorComponent",
+               "source",
+               "-datatype SOMEDATA HLT -errorcount 1 1 -range max-4 max-4 -replace 0xFF/8 -range min+0:4 min+0:4 -replace 0xBA/8"
+       );
+       AliHLTConfiguration snk(
+               "sink",
+               "FileWriter",
+               "processor",
+               "-datafile corruptorOutputTestFile_reladdr.dat"
+       );
+       
+       sys.BuildTaskList("sink");
+       sys.Run(1); // Run for 1 event.
+}
+
+/**
+ * Checks if the output data is as expected for the remove command.
+ */
+bool CheckRelativeAddressOutput(bool debug = false)
+{
+       char* buffer = NULL;
+       size_t size = 0;
+       if (! ReadFile("corruptorOutputTestFile_reladdr_0x00000000_0x00_HLT:SOMEDATA.dat", buffer, size, debug))
+       {
+               if (! debug)
+               {
+                       cerr << "ERROR: Relative address chain test did not generate correct"
+                               << " output file. Run with 'debug = true' for more details."
+                               << endl;
+               }
+               return false;
+       }
+       if (size != 256)
+       {
+               cerr << "ERROR: The output file is not the expected 256 bytes in size"
+                       << " when testing the relative address option." << endl;
+               delete [] buffer;
+               return false;
+       }
+       // Check that the correct bits were set.
+       char refBuf[256];
+       memset(refBuf, 0x0, sizeof(refBuf));
+       refBuf[0] = 0xA0;
+       refBuf[1] = 0x0B;
+       refBuf[252] = 0xFF;
+       for (UInt_t j = 0; j < 256; ++j)
+       {
+               if (buffer[j] != refBuf[j])
+               {
+                       cerr << "ERROR: When testing the relative address option we find byte "
+                               << j << " has a value of "
+                               << Form("0x%2.2X", int(AliHLTUInt8_t(buffer[j])))
+                               << ", but we expected a value of "
+                               << Form("0x%2.2X", int(AliHLTUInt8_t(refBuf[j])))
+                               << "." << endl;
+                       delete [] buffer;
+                       return false;
+               }
+       }
+       delete [] buffer;
+       return true;
+}
+
+/**
+ * This is the top level testing method which calls individual tests.
+ * \returns true if all tests succeeded and false otherwise.
+ */
+bool testAliHLTCorruptorComponent(bool debug = false)
+{
+       if (debug)
+       {
+               AliLog::SetGlobalLogLevel(AliLog::kMaxType);
+       }
+       else
+       {
+               // Done here to prevent output from AliHLTSystem.
+               AliLog::SetGlobalLogLevel(AliLog::kError);
+       }
+       
+       if (gClassTable->GetID("AliHLTCorruptorComponent") < 0)
+       {
+               gSystem->Load("libAliHLTUtil.so");
+       }
+       
+       GenerateInputData(debug);
+       RunChainToCheckFiltering(debug);
+       if (! CheckFilteringOutput(debug)) return false;
+       RunChainToCheckSingleFlips(debug);
+       if (! CheckSingleFlipOutput(debug)) return false;
+       RunChainToCheckBurstErrors(debug);
+       if (! CheckBurstErrorOutput(debug)) return false;
+       RunChainToCheckReplaceErrors(debug);
+       if (! CheckReplaceErrorsOutput(debug)) return false;
+       RunChainToCheckInsertErrors(debug);
+       if (! CheckInsertErrorsOutput(debug)) return false;
+       RunChainToCheckRemoveErrors(debug);
+       if (! CheckRemoveErrorsOutput(debug)) return false;
+       RunChainToCheckRelativeAddress(debug);
+       if (! CheckRelativeAddressOutput(debug)) return false;
+       
+       // Cleanup all temporary files generated.
+       gSystem->Exec("rm -f corruptorInputTestFile.dat corruptorOutputTestFile*.dat");
+       return true;
+}
+
+#ifndef __MAKECINT__
+
+int main(int /*argc*/, const char** /*argv*/)
+{
+       bool resultOk = testAliHLTCorruptorComponent();
+       if (not resultOk) return 1;
+       return 0;
+}
+
+#endif // __MAKECINT__
+
index fb830a7..b6961b7 100644 (file)
@@ -23,7 +23,8 @@ CLASS_HDRS:=          AliHLTFilePublisher.h \
                AliHLTAgentUtil.h \
                AliHLTESDCaloClusterMaker.h \
                AliHLTCaloClusterReader.h  \
-                AliHLTComponentBenchmark.h \
+               AliHLTComponentBenchmark.h \
+               AliHLTCorruptorComponent.h \
                AliHLTESDTrackCuts.h
 
 #              AliHLTMCGeneratorComponent.h