diff options
Diffstat (limited to 'src/piklab-test/base')
-rw-r--r-- | src/piklab-test/base/Makefile.am | 5 | ||||
-rw-r--r-- | src/piklab-test/base/device_test.cpp | 54 | ||||
-rw-r--r-- | src/piklab-test/base/device_test.h | 32 | ||||
-rw-r--r-- | src/piklab-test/base/generator_check.cpp | 288 | ||||
-rw-r--r-- | src/piklab-test/base/generator_check.h | 102 | ||||
-rw-r--r-- | src/piklab-test/base/main_test.cpp | 32 | ||||
-rw-r--r-- | src/piklab-test/base/main_test.h | 51 |
7 files changed, 564 insertions, 0 deletions
diff --git a/src/piklab-test/base/Makefile.am b/src/piklab-test/base/Makefile.am new file mode 100644 index 0000000..da6c4ba --- /dev/null +++ b/src/piklab-test/base/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES = -I$(top_srcdir)/src $(all_includes) +METASOURCES = AUTO + +noinst_LTLIBRARIES = libtest.la +libtest_la_SOURCES = main_test.cpp device_test.cpp generator_check.cpp diff --git a/src/piklab-test/base/device_test.cpp b/src/piklab-test/base/device_test.cpp new file mode 100644 index 0000000..9346a13 --- /dev/null +++ b/src/piklab-test/base/device_test.cpp @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * 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. * + ***************************************************************************/ +#include "device_test.h" + +#include "devices/base/device_group.h" +#include "devices/list/device_list.h" + +void DeviceTest::checkArguments() +{ + if ( _args->count()==1 ) { + _device = QString(_args->arg(0)).upper(); + if ( !Device::lister().isSupported(_device) ) qFatal("Specified device \"%s\" not supported.", _device.latin1()); + printf("Testing only %s\n", _device.latin1()); + } +} + +bool DeviceTest::execute() +{ + Device::Lister::ConstIterator it; + for (it=Device::lister().begin(); it!=Device::lister().end(); ++it) { + Group::Base::ConstIterator git; + for (git=it.data()->begin(); git!=it.data()->end(); ++git) { + const Device::Data &data = *git.data().data; + if ( !_device.isEmpty() && data.name()!=_device ) continue; + _message = data.name(); + if ( skip(data) ) { + skipped(); + printf("S"); + } else { + if ( init(data) ) { + printf("*"); + execute(data); + } else printf("S"); + cleanup(data); + } + fflush(stdout); + } + } + return true; +} + +Piklab::OptionList DeviceTest::optionList() const +{ + Piklab::OptionList optionList; + const KCmdLineOptions OPTION = { "+[device]", "Only check the specified device", 0 }; + optionList.append(OPTION); + return optionList; +} diff --git a/src/piklab-test/base/device_test.h b/src/piklab-test/base/device_test.h new file mode 100644 index 0000000..24447ed --- /dev/null +++ b/src/piklab-test/base/device_test.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * 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. * + ***************************************************************************/ +#ifndef DEVICE_TEST_H +#define DEVICE_TEST_H + +#include "piklab-test/base/main_test.h" +namespace Device { class Data; } + +class DeviceTest : public Test +{ +public: + virtual Piklab::OptionList optionList() const; + +protected: + virtual bool execute(); + virtual bool skip(const Device::Data &) const { return false; } + virtual bool init(const Device::Data &) { return true; } // returns false if skipped or failed + virtual bool execute(const Device::Data &data) = 0; // returns false if skipped or failed + virtual void cleanup(const Device::Data &) {} + virtual void checkArguments(); + +private: + QString _device; +}; + +#endif diff --git a/src/piklab-test/base/generator_check.cpp b/src/piklab-test/base/generator_check.cpp new file mode 100644 index 0000000..68ad2c5 --- /dev/null +++ b/src/piklab-test/base/generator_check.cpp @@ -0,0 +1,288 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * 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. * + ***************************************************************************/ +#include "generator_check.h" + +#include "devices/base/device_group.h" +#include "devices/pic/pic/pic_memory.h" +#include "tools/gputils/gputils.h" +#include "tools/gputils/gputils_generator.h" +#include "tools/sdcc/sdcc.h" +#include "tools/sdcc/sdcc_generator.h" +#include "devices/list/device_list.h" + +//---------------------------------------------------------------------------- +GeneratorCheckHelper::GeneratorCheckHelper() + : _cprocess(0), _lprocess(0), _generator(0) +{} + +GeneratorCheckHelper::~GeneratorCheckHelper() +{ + delete _generator; +} + +void GeneratorCheckHelper::cleanup() +{ + delete _lprocess; + _lprocess = 0; + delete _cprocess; + _cprocess = 0; +} + +//---------------------------------------------------------------------------- +GeneratorCheck::GeneratorCheck(GeneratorCheckHelper *helper) + : _helper(helper), _fdest(0), _fhex(0), _memory1(0) +{ + _view = new CLI::View; +} + +GeneratorCheck::~GeneratorCheck() +{ + delete _view; + delete _helper; +} + +void GeneratorCheck::runTest() +{ + _helper->initSupported(); + DeviceTest::runTest(); +} + +bool GeneratorCheck::init(const Device::Data &data) +{ + PURL::Url dest(PURL::Directory::current(), "test.xxx"); + dest = dest.toFileType(_helper->sourceFileType()); + _fdest = new PURL::File(dest, *_view); + _helper->init(data); + PURL::Url hex(PURL::Directory::current(), "test.hex"); + _fhex = new PURL::File(hex, *_view); + _memory1 = static_cast<Pic::Memory *>(data.group().createMemory(data)); + return true; +} + +bool GeneratorCheck::skip(const Device::Data &data) const +{ + return !_helper->isSupported(data); +} + +void GeneratorCheck::cleanup(const Device::Data &) +{ + delete _memory1; + _memory1 = 0; + delete _fhex; + _fhex = 0; +// _fdest->remove(); + delete _fdest; + _fdest = 0; + _helper->cleanup(); +} + +bool GeneratorCheck::execute(const Device::Data &data) +{ + // create asm file from template source code + if ( !_fdest->openForWrite() ) TEST_FAILED_RETURN(""); + _fdest->appendText(_source); + _fdest->close(); + + // run compiler + Process::State state = Process::runSynchronously(*_helper->_cprocess, Process::Start, 2000); // 2s timeout + if ( state!=Process::Exited ) TEST_FAILED_RETURN("Error while running compilation") + if ( _helper->_cprocess->exitCode()!=0 ) TEST_FAILED_RETURN(QString("Error in compilation for %1:\n%2%3").arg(data.name()).arg(_helper->_cprocess->sout()+_helper->_cprocess->serr()).arg(QString::null)) + + // run linker + if (_helper->_lprocess) { + state = Process::runSynchronously(*_helper->_lprocess, Process::Start, 2000); // 2s timeout + if ( state!=Process::Exited ) TEST_FAILED_RETURN("Error while running linking") + if ( _helper->_lprocess->exitCode()!=0 ) TEST_FAILED_RETURN(QString("Error in linking for %1:\n%2%3").arg(data.name()).arg(_helper->_lprocess->sout()+_helper->_lprocess->serr()).arg(QString::null)) + } + + // load hex file + if ( !_fhex->openForRead() ) TEST_FAILED_RETURN("") + QStringList errors, warnings; + Device::Memory::WarningTypes warningTypes; + if ( !_memory1->load(_fhex->stream(), errors, warningTypes, warnings) ) TEST_FAILED_RETURN(QString("Error loading hex into memory: %1").arg(errors.join(" "))) + //if ( warningTypes!=Device::Memory::NoWarning ) TEST_FAILED(QString("Warning loading hex into memory: %1").arg(warnings.join(" "))) + + TEST_PASSED + return true; +} + +//---------------------------------------------------------------------------- +bool ConfigGeneratorCheck::init(const Device::Data &data) +{ + if ( !GeneratorCheck::init(data) ) return false; + _memory2 = static_cast<Pic::Memory *>(data.group().createMemory(data)); + return true; +} + +bool ConfigGeneratorCheck::execute(const Device::Data &data) +{ + // create configuration + const Pic::Config &config = static_cast<const Pic::Data &>(data).config(); + for (uint l=0; ; l++) { + // set config bits + bool ok = false; + for (uint i=0; i<config._words.count(); i++) { + const Pic::Config::Word &cword = config._words[i]; + for (uint k=0; k<cword.masks.count(); k++) { + const Pic::Config::Mask &cmask = cword.masks[k]; + if ( l<cmask.values.count() ) { + ok = true; + if ( !cmask.values[l].name.isEmpty() ) _memory2->setConfigValue(cmask.name, cmask.values[l].name); + } + } + } + if ( !ok ) break; + + // create source code + PURL::SourceFamily sfamily = _helper->sourceFileType().data().sourceFamily; + PURL::ToolType ttype = sfamily.data().toolType; + SourceLine::List lines = _helper->generator()->includeLines(ttype, data); + lines += _helper->generator()->configLines(ttype, *_memory2, ok); + lines += _helper->configEndLines(); + _source = SourceLine::text(sfamily, lines, 2); + if (!ok) TEST_FAILED_RETURN("Config lines generation incomplete") + + if ( !GeneratorCheck::execute(data) ) return false; + + // check that config bits are the same + uint nbChars = static_cast<const Pic::Data &>(data).nbCharsWord(Pic::MemoryRangeType::Config); + for (uint i=0; i<config._words.count(); i++) { + const Pic::Config::Word &cword = config._words[i]; + BitValue word1 = _memory1->word(Pic::MemoryRangeType::Config, i); + BitValue word2 = _memory2->word(Pic::MemoryRangeType::Config, i); + if ( word1==word2 ) continue; + for (uint k=0; k<cword.masks.count(); k++) { + const Pic::Config::Mask &cmask = cword.masks[k]; + if ( cmask.value.isInside(cword.pmask) ) continue; + BitValue value1 = word1.maskWith(cmask.value); + BitValue value2 = word2.maskWith(cmask.value); + if ( value1==value2 ) continue; + QString name1, name2; + uint l1, l2; + for (uint l=0; l<cmask.values.count(); l++) { + const Pic::Config::Value &value = cmask.values[l]; + if ( value.value==value1 ) { name1 = value.name; l1 = l; } + if ( value.value==value2 ) { name2 = value.name; l2 = l; } + } + if ( name1==name2 ) continue; + TEST_FAILED_RETURN(QString("Config bits are different in %1: set\"%2\"=(%3) != compiled=%4)") + .arg(cmask.name).arg(cmask.values[l2].name) + .arg(toHexLabel(word2.maskWith(cmask.value), nbChars)).arg(toHexLabel(word1.maskWith(cmask.value), nbChars))) + } + } + } + + TEST_PASSED + return true; +} + +void ConfigGeneratorCheck::cleanup(const Device::Data &data) +{ + GeneratorCheck::cleanup(data); + delete _memory2; + _memory2 = 0; +} + +//---------------------------------------------------------------------------- +bool TemplateGeneratorCheck::init(const Device::Data &data) +{ + if ( !GeneratorCheck::init(data) ) return false; + bool ok; + PURL::SourceFamily sfamily = _helper->sourceFileType().data().sourceFamily; + PURL::ToolType ttype = sfamily.data().toolType; + SourceLine::List lines = _helper->generator()->templateSourceFile(ttype, data, ok); + _source = SourceLine::text(sfamily, lines, 2); + if (!ok) TEST_FAILED_RETURN(QString("Incomplete template generator for %1").arg(data.name())) + return true; +} + +//---------------------------------------------------------------------------- +GPUtilsGeneratorCheckHelper::GPUtilsGeneratorCheckHelper() +{ + _generator = new GPUtils::SourceGenerator; +} + +void GPUtilsGeneratorCheckHelper::initSupported() +{ + Process::StringOutput p; + QStringList options; + options += "-l"; + p.setup("gpasm", options, false); + Process::runSynchronously(p, Process::Start, 2000); // 2s timeout + _supported = GPUtils::getSupportedDevices(p.sout()); +} + +bool GPUtilsGeneratorCheckHelper::init(const Device::Data &data) +{ + _cprocess = new Process::StringOutput; + QStringList options; + options = "-c"; + options += "-p" + GPUtils::toDeviceName(data.name()); + options += "test.asm"; + _cprocess->setup("gpasm", options, false); + _lprocess = new Process::StringOutput; + options = "-o"; + options += "test.hex"; + options += "test.o"; + _lprocess->setup("gplink", options, false); + return true; +} + +SourceLine::List GPUtilsGeneratorCheckHelper::configEndLines() const +{ + SourceLine::List lines; + lines.appendIndentedCode("end"); + return lines; +} + +//---------------------------------------------------------------------------- +SDCCGeneratorCheckHelper::SDCCGeneratorCheckHelper() +{ + _generator = new SDCC::SourceGenerator; +} + +void SDCCGeneratorCheckHelper::initSupported() +{ + PURL::Url url(PURL::Directory::current(), "test.c"); + Log::StringView view; + PURL::File file(url, view); + if ( file.openForWrite() ) file.appendText("void main(void) {}\n"); + file.close(); + _supported.clear(); + for (uint i=0; i<SDCC::Nb_Families; i++) { + Process::StringOutput p; + QStringList options; + options += QString("-m") + SDCC::FAMILY_DATA[i].name; + options += "-phelp"; + options += "test.c"; + p.setup("sdcc", options, false); + Process::runSynchronously(p, Process::Start, 2000); // 2s timeout + _supported += SDCC::getSupportedDevices(p.serr()); + } +} + +bool SDCCGeneratorCheckHelper::init(const Device::Data &data) +{ + _cprocess = new Process::StringOutput; + QStringList options; + options += QString("-m") + SDCC::FAMILY_DATA[SDCC::family(data.name())].name; + options += "-" + SDCC::toDeviceName(data.name()); + options += "test.c"; + options += "-I/usr/share/gputils/header"; + options += "-Wl-otext.hex"; + _cprocess->setup("sdcc", options, false); + return true; +} + +SourceLine::List SDCCGeneratorCheckHelper::configEndLines() const +{ + SourceLine::List lines; + lines.appendIndentedCode("void main() {}"); + return lines; +} diff --git a/src/piklab-test/base/generator_check.h b/src/piklab-test/base/generator_check.h new file mode 100644 index 0000000..9ad426a --- /dev/null +++ b/src/piklab-test/base/generator_check.h @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * 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. * + ***************************************************************************/ +#ifndef GPUTILS_GENERATOR_CHECK_H +#define GPUTILS_GENERATOR_CHECK_H + +#include "device_test.h" +#include "common/cli/cli_log.h" +#include "common/global/pfile.h" +#include "coff/base/disassembler.h" +#include "common/global/process.h" +namespace Pic { class Memory; } + +//---------------------------------------------------------------------------- +class GeneratorCheckHelper +{ +public: + GeneratorCheckHelper(); + virtual ~GeneratorCheckHelper(); + virtual void initSupported() = 0; + virtual bool init(const Device::Data &data) = 0; + void cleanup(); + bool isSupported(const Device::Data &data) const { return _supported.contains(&data); } + virtual PURL::FileType sourceFileType() const = 0; + const Tool::SourceGenerator *generator() const { return _generator; } + virtual SourceLine::List configEndLines() const = 0; + +protected: + QValueList<const Device::Data *> _supported; + Process::StringOutput *_cprocess, *_lprocess; + Tool::SourceGenerator *_generator; + + friend class GeneratorCheck; +}; + +class GeneratorCheck : public DeviceTest +{ +public: + GeneratorCheck(GeneratorCheckHelper *helper); + virtual ~GeneratorCheck(); + virtual bool skip(const Device::Data &data) const; + virtual void runTest(); + virtual bool init(const Device::Data &data); + virtual bool execute(const Device::Data &data); + virtual void cleanup(const Device::Data &data); + +protected: + GeneratorCheckHelper *_helper; + CLI::View *_view; + PURL::File *_fdest, *_fhex; + Pic::Memory *_memory1; + QString _source; +}; + +//---------------------------------------------------------------------------- +class ConfigGeneratorCheck : public GeneratorCheck +{ +public: + ConfigGeneratorCheck(GeneratorCheckHelper *helper) : GeneratorCheck(helper), _memory2(0) {} + virtual bool init(const Device::Data &data); + virtual bool execute(const Device::Data &data); + virtual void cleanup(const Device::Data &data); + +private: + Pic::Memory *_memory2; +}; + +//---------------------------------------------------------------------------- +class TemplateGeneratorCheck : public GeneratorCheck +{ +public: + TemplateGeneratorCheck(GeneratorCheckHelper *helper) : GeneratorCheck(helper) {} + virtual bool init(const Device::Data &data); +}; + +//---------------------------------------------------------------------------- +class GPUtilsGeneratorCheckHelper : public GeneratorCheckHelper +{ +public: + GPUtilsGeneratorCheckHelper(); + virtual void initSupported(); + virtual bool init(const Device::Data &data); + virtual PURL::FileType sourceFileType() const { return PURL::AsmGPAsm; } + virtual SourceLine::List configEndLines() const; +}; + +//---------------------------------------------------------------------------- +class SDCCGeneratorCheckHelper : public GeneratorCheckHelper +{ +public: + SDCCGeneratorCheckHelper(); + virtual void initSupported(); + virtual bool init(const Device::Data &data); + virtual PURL::FileType sourceFileType() const { return PURL::CSource; } + virtual SourceLine::List configEndLines() const; +}; +#endif diff --git a/src/piklab-test/base/main_test.cpp b/src/piklab-test/base/main_test.cpp new file mode 100644 index 0000000..10d0414 --- /dev/null +++ b/src/piklab-test/base/main_test.cpp @@ -0,0 +1,32 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * 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. * + ***************************************************************************/ +#include "main_test.h" + +//---------------------------------------------------------------------------- +Test::Test() + : _nbPassed(0), _nbFailed(0), _nbSkipped(0) +{} + +void Test::runTest() +{ + _args = KCmdLineArgs::parsedArgs(); + checkArguments(); + fflush(stdout); + execute(); + printf("\n"); + printf("RESULTS: %i PASSED / %i FAILED / %i SKIPPED \n", _nbPassed, _nbFailed, _nbSkipped); +} + +void Test::failed(const QString &message, const char *file, int line) +{ + _nbFailed++; + printf("\n"); + if ( !_message.isEmpty() ) printf("[%s]", _message.latin1()); + printf("FAILED in \"%s\" line #%i: %s\n", file, line, message.latin1()); +} diff --git a/src/piklab-test/base/main_test.h b/src/piklab-test/base/main_test.h new file mode 100644 index 0000000..601b779 --- /dev/null +++ b/src/piklab-test/base/main_test.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * 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. * + ***************************************************************************/ +#ifndef MAIN_TEST_H +#define MAIN_TEST_H + +#include "common/global/about.h" + +//---------------------------------------------------------------------------- +#define TEST_SKIPPED_RETURN { skipped(); return false; } +#define TEST_FAILED_RETURN(message) { failed(message, __FILE__, __LINE__); return false; } +#define TEST_FAILED(message) { failed(message, __FILE__, __LINE__); } +#define TEST_PASSED { printf("."); fflush(stdout); passed(); } +#define TEST_MAIN(Type) \ + int main(int argc, char **argv) \ + { \ + Type *check = new Type; \ + Piklab::OptionList opt = check->optionList(); \ + Piklab::init(new Piklab::AboutData("test", 0, 0), argc, argv, false, opt.ptr()); \ + check->runTest(); \ + return 0; \ + } + +//---------------------------------------------------------------------------- +class Test +{ +public: + Test(); + virtual Piklab::OptionList optionList() const { return Piklab::OptionList(); } + virtual void runTest(); + +protected: + KCmdLineArgs *_args; + QString _message; + + void passed() { _nbPassed++; } + void failed(const QString &message, const char *file, int line); + void skipped() { _nbSkipped++; } + virtual bool execute() = 0; // returns false if failed or skipped + virtual void checkArguments() {} + +private: + uint _nbPassed, _nbFailed, _nbSkipped; +}; + +#endif |