[Clam-devel] PATCH: revised ControlTrace{Reader,Writer} classes

Zach Welch zach-clam-devel at splitstring.com
Wed Apr 18 01:01:15 PDT 2007


David García Garzón wrote:
> Zach, finally we took a look at this patch.
> 
> As discussed on the irc, those changes will need a refactor in order to remove 
> the ConfigurableFile. So we propose you the following changes to the patch 
> before committing it:
> 
> * Remove dependencies on ConfigurableFile
> * Write new Filename subclasses and use them for configuration
> * Move the XML Restore and Dump, now at  ControlTraceFiles to the 
> ControlTraceReader::ConcreteStart and ControlTraceWriter::ConcreteStop.
> * Drop ControlTraceFileTarget/Source classes

I have attached a new patch that accomplishes almost everything you ask;
I think the Load is better performed in the Configure step, since errors
can be detected at that point and reported as a misconfiguration.  Other
than that, I think it's all there... and then some. I added a "repeats"
storage optimization that gives run length encoding of the value sets,
which can help shrink (and annotate) traces whose inputs change
relatively infrequently (e.g. GUI controls).

Old traces (v0) produced by the last version of this patch can not be
read by this final version (v1), but I added provisions to support the
new trace format through further revisions. This means all trace files
created with the forthcoming ControlTracerWriter should be playable by
future versions of the ControlTraceReader. Since I foresee creating a
small library of traces, I have tried to allow for forward portability
of such data sets.

Cheers,

Zach

-------------- next part --------------
Index: CLAM/src/Processing/Controls/ControlTrace.cxx
===================================================================
--- CLAM/src/Processing/Controls/ControlTrace.cxx	(revision 0)
+++ CLAM/src/Processing/Controls/ControlTrace.cxx	(revision 0)
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
+ *                         UNIVERSITAT POMPEU FABRA
+ * Copyright (c) 2007 Superlucidity Services, LLC and Zachary T Welch
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "ControlTrace.hxx"
+#include "Factory.hxx"
+#include "XMLAdapter.hxx"
+#include "XMLStorage.hxx"
+#include "XMLIterableAdapter.hxx"
+#include "XMLAdapter.hxx"
+#include "XmlStorageErr.hxx"
+#include <sstream>
+
+namespace CLAM
+{
+
+ControlTraceEvent::ControlTraceEvent()
+	: mSteps(1)
+{
+}
+ControlTraceEvent::ControlTraceEvent(const ControlTraceEvent &obj)
+	: mSteps(obj.mSteps)
+	, mValues(obj.mValues)
+{
+}
+ControlTraceEvent::ControlTraceEvent(const InControlArray &inputs)
+	: mSteps(1)
+{
+	mValues.resize(inputs.Size());
+	for (int i = 0; i < inputs.Size(); i++)
+		mValues[i] = inputs[i].GetLastValue();
+}
+
+void ControlTraceEvent::UpdateControls(OutControlArray &outputs) const
+{
+	for (int i = 0; i < outputs.Size(); i++)
+		outputs[i].SendControl(mValues[i]);
+}
+
+void ControlTraceEvent::LoadFrom( Storage& storage )
+{
+	XMLIterableAdapter<ValueArray> vAdapter(mValues, "x", "controls", true);
+	storage.Load(vAdapter);
+
+	XMLAdapter<unsigned int> sAdapter(mSteps, "repeats", true);
+	storage.Load(sAdapter);
+}
+
+void ControlTraceEvent::StoreOn( Storage& storage ) const
+{
+	XMLIterableAdapter<ValueArray> vAdapter(mValues, "x", "controls", true);
+	storage.Store(vAdapter);
+
+	if (mSteps > 1)
+	{
+		XMLAdapter<unsigned int> sAdapter(mSteps, "repeats", true);
+		storage.Store(sAdapter);
+	}
+}
+
+const ControlTraceEvent& ControlTraceEvent::operator=(const ControlTraceEvent& rhs)
+{
+	mValues = rhs.mValues;
+	return *this;
+}
+
+bool ControlTraceEvent::ValuesEqual(const ControlTraceEvent &rhs) const
+{
+	if (mValues.size() != rhs.mValues.size())
+		return false;
+
+	for (size_t i = 0; i < mValues.size(); i++)
+	{
+		if (mValues[i] != rhs.mValues[i])
+			return false;
+	}
+
+	return true;
+}
+
+/* ================================================================== */
+
+const unsigned int ControlTraceData::DumpVersion = 1;
+
+ControlTraceData::ControlTraceData()
+	: mVersion(DumpVersion)
+{
+}
+ControlTraceData::ControlTraceData(const ControlTraceData &obj)
+	: mVersion(DumpVersion), mEvents(obj.mEvents)
+{
+}
+
+void ControlTraceData::LoadFrom( Storage& storage )
+{
+	mVersion = 0;
+	XMLAdapter<unsigned int> versionAdapter(mVersion, "version");
+	storage.Load(versionAdapter);
+	if (!mVersion || mVersion > DumpVersion)
+	{
+		std::stringstream err;
+		err << "Unknown CLAM Control Trace file version: " << mVersion;
+		throw XmlStorageErr(err.str());
+	}
+
+	XMLIterableAdapter<EventList> adapter(mEvents, "event", "events", true);
+	storage.Load(adapter);
+}
+void ControlTraceData::StoreOn( Storage& storage ) const
+{
+	XMLAdapter<unsigned int> versionAdapter(mVersion, "version");
+	storage.Store(versionAdapter);
+
+	XMLIterableAdapter<EventList> adapter(mEvents, "event", "events", true);
+	storage.Store(adapter);
+}
+
+void ControlTraceData::Append(const ControlTraceEvent &data)
+{
+	ControlTraceEvent &prev = mEvents.back();
+	if (prev.ValuesEqual(data))
+		prev.AddStep();
+	else
+		mEvents.push_back(data);
+}
+
+/* ================================================================== */
+
+static const char clamControlTraceFileTypeFamily[] = "CLAM Control Trace";
+static const Filename::Filter clamControlTraceFileFilters[] = {
+		{ "CLAM Control Traces (v1)", "*.clamtrace" },
+	};
+
+const char* ControlTraceInFilename::TypeFamily() const
+{
+	return clamControlTraceFileTypeFamily;
+}
+const Filename::Filter * ControlTraceInFilename::Filters() const
+{
+	return clamControlTraceFileFilters;
+}
+
+const char* ControlTraceOutFilename::TypeFamily() const
+{
+	return clamControlTraceFileTypeFamily;
+}
+const Filename::Filter * ControlTraceOutFilename::Filters() const
+{
+	return clamControlTraceFileFilters;
+}
+
+/* ================================================================= */
+
+void ControlTraceWriterConfig::DefaultInit()
+{
+	AddAll();
+	UpdateData();
+	SetNumberOfInputs(1.);
+}
+
+ControlTraceWriter::ControlTraceWriter()
+{
+	Configure(mConfig);
+}
+
+ControlTraceWriter::ControlTraceWriter( const ProcessingConfig& cfg )
+{
+	Configure( cfg );
+}
+
+ControlTraceWriter::~ControlTraceWriter()
+{
+	RemoveOldControls();
+}
+
+bool ControlTraceWriter::ConcreteConfigure( const ProcessingConfig& cfgObj )
+{
+	RemoveOldControls();
+	CopyAsConcreteConfig( mConfig, cfgObj );
+	if ( !mConfig.HasTraceFile() )
+	{
+		AddConfigErrorMessage("No 'trace file' was specified in the configuration!");
+		return false;
+	}
+
+	ControlTraceOutFilename &file = mConfig.GetTraceFile();
+	if ( file == "" )
+	{
+		AddConfigErrorMessage("No trace file selected");
+		return false;
+	}
+
+	if (!mConfig.HasNumberOfInputs() || mConfig.GetNumberOfInputs() < 1.)
+	{
+		AddConfigErrorMessage("The number of inputs has not been configured.");
+		return false;
+	}
+
+	mInputs.Resize(int(mConfig.GetNumberOfInputs()), "Input", this);
+	return true;
+}
+
+bool ControlTraceWriter::ConcreteStop()
+{
+	XMLStorage::Dump(mTrace, "trace", mConfig.GetTraceFile().c_str());
+	mTrace.Clear();
+	return true;
+}
+
+bool ControlTraceWriter::Do()
+{
+	mTrace.Append(ControlTraceEvent(mInputs));
+	return true;
+}
+
+
+void ControlTraceWriter::RemoveOldControls()
+{
+	mInputs.Clear();
+	GetInControls().Clear();
+}
+
+/* ================================================================= */
+
+void ControlTraceReaderConfig::DefaultInit()
+{
+	AddAll();
+	UpdateData();
+}
+
+ControlTraceReader::ControlTraceReader()
+{
+	Configure(mConfig);
+}
+
+ControlTraceReader::ControlTraceReader( const ProcessingConfig& cfg )
+{
+	Configure( cfg );
+}
+
+ControlTraceReader::~ControlTraceReader()
+{
+	RemoveOldControls();
+}
+
+bool ControlTraceReader::ConcreteConfigure( const ProcessingConfig& cfgObj )
+{
+	RemoveOldControls();
+	CopyAsConcreteConfig( mConfig, cfgObj );
+	if ( !mConfig.HasTraceFile() )
+	{
+		AddConfigErrorMessage("No 'trace file' was specified in the configuration!");
+		return false;
+	}
+
+	ControlTraceInFilename &file = mConfig.GetTraceFile();
+	if ( file == "" )
+	{
+		AddConfigErrorMessage("No trace file selected");
+		return false;
+	}
+
+	try {
+		XMLStorage::Restore(mTrace, mConfig.GetTraceFile().c_str());
+	}
+	catch (XmlStorageErr &e)
+	{
+		AddConfigErrorMessage(e.what());
+		return false;
+	}
+
+	if (mTrace.GetNumberOfControls() < 1)
+	{
+		AddConfigErrorMessage("The specified file does not contain any control events.");
+		return false;
+	}
+
+	mOutputs.Resize(mTrace.GetNumberOfControls(), "Output", this);
+	return true;
+}
+
+bool ControlTraceReader::ConcreteStart()
+{
+	mIterator = mTrace.Begin();
+	mStepCounter = 0;
+	return true;
+}
+
+bool ControlTraceReader::Do()
+{
+	if (mIterator == mTrace.End())
+		return false;
+
+	const ControlTraceEvent &event = *mIterator;
+
+	// if this is the zeroth (first) step, update the controls
+	if (!mStepCounter)
+		event.UpdateControls(mOutputs);
+
+	// if this step completes the current event, advance and reset counter
+	if (++mStepCounter == event.Steps()) {
+		mIterator++;
+		mStepCounter = 0;
+	}
+	return true;
+}
+
+void ControlTraceReader::RemoveOldControls()
+{
+	mOutputs.Clear();
+	GetOutControls().Clear();
+}
+
+/* ================================================================== */
+
+namespace detail
+{
+typedef CLAM::Factory<CLAM::Processing> ProcessingFactory;
+static ProcessingFactory::Registrator<CLAM::ControlTraceReader>
+		regtControlTraceReader("ControlTraceReader");
+static ProcessingFactory::Registrator<CLAM::ControlTraceWriter>
+		regtControlTraceWriter("ControlTraceWriter");
+}
+
+
+} // CLAM namespace
+
Index: CLAM/src/Processing/Controls/ControlTrace.hxx
===================================================================
--- CLAM/src/Processing/Controls/ControlTrace.hxx	(revision 0)
+++ CLAM/src/Processing/Controls/ControlTrace.hxx	(revision 0)
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
+ *                         UNIVERSITAT POMPEU FABRA
+ * Copyright (c) 2007 Superlucidity Services, LLC and Zachary T Welch
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef CONTROL_TRACE_HXX
+#define CONTROL_TRACE_HXX
+
+#include <CLAM/Processing.hxx>
+#include <CLAM/ProcessingConfig.hxx>
+#include <CLAM/InControlArray.hxx>
+#include <CLAM/OutControlArray.hxx>
+#include <CLAM/Filename.hxx>
+#include <vector>
+
+class Network;
+
+struct fann;
+
+namespace CLAM
+{
+
+class ControlTraceEvent : public Component {
+public:
+	typedef std::vector<TControlData> ValueArray;
+
+	ControlTraceEvent();
+	ControlTraceEvent(const InControlArray &inputs);
+	ControlTraceEvent(const ControlTraceEvent &event);
+	const ControlTraceEvent& operator=( const ControlTraceEvent& );
+	virtual ~ControlTraceEvent() { }
+
+	const char *GetClassName() const { return "ControlTraceEvent"; }
+
+	void LoadFrom( Storage& storage);
+	void StoreOn( Storage& storage ) const;
+
+	void AddStep() { mSteps++; }
+	unsigned int Steps() const { return mSteps; }
+	size_t Size() const { return mValues.size(); }
+
+	void UpdateControls(OutControlArray &array) const;
+
+	bool ValuesEqual(const ControlTraceEvent &rhs) const;
+
+private:
+	unsigned int mSteps;
+	ValueArray mValues;
+};
+
+class ControlTraceData : public Component {
+	static const unsigned int DumpVersion;
+public:
+	typedef std::list<ControlTraceEvent> EventList;
+	virtual ~ControlTraceData() { }
+
+	ControlTraceData();
+	ControlTraceData(const ControlTraceData &obj);
+
+	const char *GetClassName() const { return "ControlTraceData"; }
+
+	unsigned int GetVersion() const { return mVersion; }
+
+	void LoadFrom( Storage& storage);
+	void StoreOn( Storage& storage ) const;
+
+	size_t GetNumberOfControls() const { return mEvents.front().Size(); }
+
+	void Append(const ControlTraceEvent &data);
+
+	EventList::iterator Begin() { return mEvents.begin(); }
+	EventList::iterator End() { return mEvents.end(); }
+
+	void Clear() { mEvents.clear(); }
+
+private:
+	unsigned int mVersion;
+	EventList mEvents;
+};
+
+
+class ControlTraceInFilename : public InFilename
+{
+public:
+	ControlTraceInFilename(const std::string & s="") : InFilename(s) {}
+	ControlTraceInFilename(const char * s) : InFilename(s) {}
+	const char* TypeFamily() const;
+	const Filter * Filters() const;
+};
+CLAM_TYPEINFOGROUP(BasicCTypeInfo, ControlTraceInFilename);
+
+class ControlTraceReaderConfig  : public ProcessingConfig {
+	DYNAMIC_TYPE_USING_INTERFACE
+	( ControlTraceReaderConfig, 1, ProcessingConfig );
+
+	DYN_ATTRIBUTE( 0, public, ControlTraceInFilename, TraceFile );
+
+protected:
+	void DefaultInit();
+};
+
+class ControlTraceReader : public Processing
+{
+public:
+	ControlTraceReader();
+	ControlTraceReader( const ProcessingConfig& cfg );
+	virtual ~ControlTraceReader();
+
+	const char* GetClassName() const { return "ControlTraceReader"; }
+	const ProcessingConfig& GetConfig() const { return mConfig; }
+
+	bool Do();
+
+protected: // methods
+	bool ConcreteConfigure( const ProcessingConfig& cfgObject );
+	bool ConcreteStart();
+	void RemoveOldControls();
+	
+protected: // attributes
+	ControlTraceReaderConfig mConfig;
+	ControlTraceData mTrace;
+	ControlTraceData::EventList::iterator mIterator;
+	unsigned int mStepCounter;
+	OutControlArray mOutputs;
+};
+
+
+class ControlTraceOutFilename : public OutFilename
+{
+public:
+	ControlTraceOutFilename(const std::string & s="") : OutFilename(s) {}
+	ControlTraceOutFilename(const char * s) : OutFilename(s) {}
+	const char* TypeFamily() const;
+	const Filter * Filters() const;
+};
+CLAM_TYPEINFOGROUP(BasicCTypeInfo, ControlTraceOutFilename);
+
+class ControlTraceWriterConfig  : public ProcessingConfig {
+	DYNAMIC_TYPE_USING_INTERFACE
+	( ControlTraceWriterConfig, 2, ProcessingConfig );
+
+	DYN_ATTRIBUTE( 0, public, ControlTraceOutFilename, TraceFile );
+	DYN_ATTRIBUTE( 1, public, TData, NumberOfInputs );
+
+protected:
+	void DefaultInit();
+};
+
+class ControlTraceWriter : public Processing
+{
+public:
+	ControlTraceWriter();
+	ControlTraceWriter( const ProcessingConfig& cfg );
+	virtual ~ControlTraceWriter();
+
+	const char* GetClassName() const { return "ControlTraceWriter"; }
+	const ProcessingConfig& GetConfig() const { return mConfig; }
+
+	bool Do();
+
+protected: // methods
+	bool ConcreteConfigure( const ProcessingConfig& cfgObject );
+	bool ConcreteStop();
+	void RemoveOldControls();
+	
+protected: // attributes
+	ControlTraceWriterConfig mConfig;
+	ControlTraceData mTrace;
+	InControlArray mInputs;
+};
+
+} // CLAM namespace
+
+#endif
Index: NetworkEditor/src/ProcessingTree.cxx
===================================================================
--- NetworkEditor/src/ProcessingTree.cxx	(revision 10016)
+++ NetworkEditor/src/ProcessingTree.cxx	(working copy)
@@ -67,6 +67,8 @@
 	"ControlSource",
 	"ControlSink",
 	"ControlPrinter",
+	"ControlTraceReader",
+	"ControlTraceWriter",
 	"ControlScaler", 
 	"AutoPanner",
 	"FlagControl",
Index: NetworkEditor/src/ProcessingBox.cxx
===================================================================
--- NetworkEditor/src/ProcessingBox.cxx	(revision 10016)
+++ NetworkEditor/src/ProcessingBox.cxx	(working copy)
@@ -85,7 +85,7 @@
 	if (className=="ControlSurface")
 		return new ControlSurfaceWidget(processing);
 
-	if (className=="ControlPrinter")
+	if (className=="ControlPrinter" || className=="ControlTraceWriter")
 		return new ControlPrinterWidget(processing);
 
 	if (className=="Vumeter")
Index: NetworkEditor/src/RegisterConfiguratorLaunchers.cxx
===================================================================
--- NetworkEditor/src/RegisterConfiguratorLaunchers.cxx	(revision 10016)
+++ NetworkEditor/src/RegisterConfiguratorLaunchers.cxx	(working copy)
@@ -66,6 +66,7 @@
 #include <CLAM/ControlScaler.hxx>
 #include "ControlSurface.hxx"
 #include <CLAM/ControlSource.hxx>
+#include <CLAM/ControlTrace.hxx>
 #include <CLAM/OutControlSender.hxx>
 
 //MIDI
@@ -132,6 +133,8 @@
 STANDARD_PROCESSING_CONFIG_REGISTER(ControlScalerConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(ControlSourceConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(ControlSurfaceConfig);
+STANDARD_PROCESSING_CONFIG_REGISTER(ControlTraceReaderConfig);
+STANDARD_PROCESSING_CONFIG_REGISTER(ControlTraceWriterConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(FlagControlConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(Fundamental2ControlConfig);
 STANDARD_PROCESSING_CONFIG_REGISTER(OneOverFConfig);
Index: CLAM/test/FunctionalTests/ProcessingTests/TestControlTraces.cxx
===================================================================
--- CLAM/test/FunctionalTests/ProcessingTests/TestControlTraces.cxx	(revision 0)
+++ CLAM/test/FunctionalTests/ProcessingTests/TestControlTraces.cxx	(revision 0)
@@ -0,0 +1,251 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include "cppUnitHelper.hxx"
+#include <CLAM/ControlTrace.hxx>
+#include "similarityHelper.hxx"
+#include <algorithm>
+#include <cstdio>
+
+namespace CLAMTest
+{
+
+class ControlTraceReaderFunctionalTest;
+CPPUNIT_TEST_SUITE_REGISTRATION( ControlTraceReaderFunctionalTest );
+
+class ControlTraceReaderFunctionalTest : public CppUnit::TestFixture
+{
+	CPPUNIT_TEST_SUITE( ControlTraceReaderFunctionalTest );
+
+	// Configuration values checking tests
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWithJustFilename );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWithoutTraceFileInConfig );
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWhenFileExists );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWhenFileDoesNotExist );
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWhenTraceEventsExist );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWhenTraceFileIsEmpty );
+
+	CPPUNIT_TEST_SUITE_END();
+
+protected: // Attributes
+
+	std::string mPathToTestData;
+	std::string mInputFileName;
+	std::string mEmptyFileName;
+
+protected: // Auxiliary methods
+
+public: // TestFixture interface
+
+	void setUp()
+	{
+		mPathToTestData = GetTestDataDirectory() + "ControlTraceReader";
+		mInputFileName = mPathToTestData + "Input.clamtrace";
+		mEmptyFileName = mPathToTestData + "Empty.clamtrace";
+	}
+
+	void tearDown()
+	{
+	}
+
+private: // tests cases
+
+	void testConfigure_ReturnsTrueWithJustFilename()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mInputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWithoutTraceFileInConfig()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+		cfg.RemoveTraceFile();
+		cfg.UpdateData();
+		
+		CLAM::ControlTraceReader proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+	}
+	
+	void testConfigure_ReturnsTrueWhenFileExists()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mInputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWhenFileDoesNotExist()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mPathToTestData + 
+				std::string( "missing-file.clamtrace" ) );
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+	}
+	
+	void testConfigure_ReturnsTrueWhenTraceEventsExist()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mInputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWhenTraceFileIsEmpty()
+	{
+		CLAM::ControlTraceReaderConfig cfg;
+
+		CLAM::ControlTraceInFilename file(mEmptyFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceReader proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+		
+	}
+
+};
+
+class ControlTraceWriterFunctionalTest;
+CPPUNIT_TEST_SUITE_REGISTRATION( ControlTraceWriterFunctionalTest );
+
+class ControlTraceWriterFunctionalTest : public CppUnit::TestFixture
+{
+	CPPUNIT_TEST_SUITE( ControlTraceWriterFunctionalTest );
+
+	// Configuration values checking tests
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWithJustFilename );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWithoutTraceFileInConfig );
+	CPPUNIT_TEST( testConfigure_ReturnsTrueWhenFileExists );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWithoutInputsInConfig );
+	CPPUNIT_TEST( testConfigure_ReturnsFalseWhenConfiguredWithNoInputs );
+
+	CPPUNIT_TEST_SUITE_END();
+
+protected: // Attributes
+
+	std::string mPathToTestData;
+	std::string mOutputFileName;
+
+protected: // Auxiliary methods
+
+public: // TestFixture interface
+
+	void setUp()
+	{
+		mPathToTestData = GetTestDataDirectory() + "ControlTraceWriter";
+		mOutputFileName = mPathToTestData + "Output.clamtrace";
+	}
+
+	void tearDown()
+	{
+	}
+
+private: // tests cases
+
+	void testConfigure_ReturnsTrueWithJustFilename()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceWriter proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWithoutTraceFileInConfig()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+		cfg.RemoveTraceFile();
+		cfg.UpdateData();
+		
+		CLAM::ControlTraceWriter proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+	}
+	
+	void testConfigure_ReturnsTrueWhenFileExists()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceWriter proc;
+		
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( true, configResult );
+	}
+
+	void testConfigure_ReturnsFalseWithoutInputsInConfig()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+		cfg.RemoveNumberOfInputs();
+		cfg.UpdateData();
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+
+		CLAM::ControlTraceWriter proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+		
+	}
+
+	void testConfigure_ReturnsFalseWhenConfiguredWithNoInputs()
+	{
+		CLAM::ControlTraceWriterConfig cfg;
+
+		CLAM::ControlTraceOutFilename file(mOutputFileName);
+		cfg.SetTraceFile( file );
+		cfg.SetNumberOfInputs( 0 );
+
+		CLAM::ControlTraceWriter proc;
+
+		bool configResult = proc.Configure( cfg );
+
+		CPPUNIT_ASSERT_EQUAL( false, configResult );
+		
+	}
+};
+
+}
+


More information about the clam-devel mailing list