<commit_before>/***********************************************************************
 test/string.cpp - Tests the behavior of mysqlpp::String, particularly
	its data conversion methods.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>

// Does an equality comparison on the value, forcing the string to
// convert itself to T on the way.  Note that we do this test in terms
// of greater and less than to avoid pedantic GCC warnings for the
// floating point type tests.
template <typename T>
static bool
test_equality(const mysqlpp::String& s, T value)
{
	T converted = s.conv(value);
	if ((value < converted) || (value > converted)) {
		std::cerr << "Type conversion to " << typeid(T).name() <<
				" failed: \"" << s << "\" != \"" << value << "\"." <<
				std::endl;
		return false;
	}
	else {
		return true;
	}
}

// Check that we can convert strings with decimals in them to native
// floating-point values, regardless of locale.
static bool
test_float_conversion()
{
	// This stuff should just work
	if (!test_equality(mysqlpp::String("123.00"), 123)) return false;
	if (!test_equality(mysqlpp::String("123."), 123)) return false;

	// This is trickier: MySQL ignores the system locale when it comes
	// to decimal separators, always using '.', so ensure the conversion
	// stuff in MySQL++ does the right thing regardless.  Test against
	// this system's current locale, an arbitrary European one where ','
	// is the decimal separator, and the "C" locale where it's '.'.
	if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	std::locale old_locale = std::locale::global(std::locale::classic());
	if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	try {
		std::locale::global(std::locale("de_DE"));
		if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	}
	catch (std::runtime_error& e) {
		std::cerr << "WARNING: skipping European locale string "
				"conversion test:" << std::endl;
		std::cerr << "\t" << e.what() << std::endl;
	}
	std::locale::global(old_locale);

	// Check that we choke on silly float-like values
	try {
		if (test_equality(mysqlpp::String("621.20.0"), 621.2)) {
			std::cerr << "Quasi-FP with two decimal points "
					"converting without error!" << std::endl;
		}
		return false;
	}
	catch (const mysqlpp::BadConversion&) {
		return true;
	}
}

// Tries to convert the given string to an int.  Returns false if we got
// a BadConversion exception and didn't expect it, or didn't get one we
// expected.  Returns false on all other exceptions regardless.
static bool
test_int_conversion(const mysqlpp::String& s, bool throw_expected)
{
	// Try the conversion
	bool conv_threw = false;
	try {
		int converted = s;
		(void)converted;	// pedantic warning squisher
	}
	catch (const mysqlpp::BadConversion&) {
		conv_threw = true;
	}
	catch (const std::exception& e) {
		std::cerr << "Unexpected " << typeid(e).name() <<
				" exception in test_int_conv: " << e.what() << std::endl;
		return false;
	}
	catch (...) {
		std::cerr << "Like, totally bogus exception in test_int_conv, "
				"man!" << std::endl;
		return false;
	}

	// Did it do what we expected?
	if (throw_expected == conv_threw) {
		return true;
	}
	else {
		std::cerr << "Conversion of \"" << s << "\" to int " <<
				(conv_threw ? "did not throw" : "threw") << "; " <<
				(throw_expected ? "did not expect" : "expected") <<
				" it to." << std::endl;
		return false;
	}
}

// Checks that String's null comparison methods work right
static bool
test_null()
{
	mysqlpp::String not_null("", mysqlpp::mysql_type_info::string_type, false);
	mysqlpp::String is_null("", mysqlpp::mysql_type_info::string_type, true);
	if (not_null.is_null() == true) {
		std::cerr << "not_null.is_null() == true!" << std::endl;
		return false;
	}
	else if (not_null == mysqlpp::null) {
		std::cerr << "not_null == mysqlpp:null!" << std::endl;
		return false;
	}
	else if (is_null.is_null() == false) {
		std::cerr << "is_null.is_null() == false!" << std::endl;
		return false;
	}
	else if (is_null != mysqlpp::null) {
		std::cerr << "is_null != mysqlpp:null!" << std::endl;
		return false;
	}
	else {
		return true;
	}
}

// Ensures numeric conversions of many different types get handled
// correctly.
static bool
test_numeric(const mysqlpp::String& s, int value)
{
	return	test_equality(s, static_cast<signed char>(value)) &&
			test_equality(s, static_cast<unsigned char>(value)) &&
			test_equality(s, static_cast<signed short>(value)) &&
			test_equality(s, static_cast<unsigned short>(value)) &&
			test_equality(s, static_cast<signed int>(value)) &&
			test_equality(s, static_cast<unsigned int>(value)) &&
			test_equality(s, static_cast<signed long>(value)) &&
			test_equality(s, static_cast<unsigned long>(value)) &&
#if !defined(NO_LONG_LONGS)
			test_equality(s, static_cast<mysqlpp::longlong>(value)) &&
			test_equality(s, static_cast<mysqlpp::ulonglong>(value)) &&
#endif
			test_equality(s, static_cast<float>(value)) &&
			test_equality(s, static_cast<double>(value));
}

static bool
test_quote_q(const mysqlpp::String& s, bool expected)
{
	if (s.quote_q() == expected) {
		return true;
	}
	else {
		std::cerr << s.type().name() << " should" <<
				(expected ? "" : " NOT") << " be quoted." << std::endl;
		return false;
	}
}

// Similar to test_equality, but only works with std::string
// comparisons, which uses String::operator ==()
static bool
test_string_equality(const mysqlpp::String& s, std::string value)
{
	if (s == value) {
		if (s != value) {
			std::cerr << "String(\"" << s << "\") != std::string(\"" <<
					value << "\"), case 2!" << std::endl;
			return false;
		}
		else {
			return true;
		}
	}
	else {
		std::cerr << "String(\"" << s << "\") != std::string(\"" <<
				value << "\"), case 1!" << std::endl;
		return false;
	}
}

int
main(int, char* argv[])
{
	try {
		int failures = 0;
		mysqlpp::String empty;
		mysqlpp::String zero("0");
		mysqlpp::String nonzero("42");
		mysqlpp::String intable1("42.");
		mysqlpp::String intable2("42.0");
		mysqlpp::String nonint("42.1");

		failures += test_equality(empty, mysqlpp::Date()) == false;
		failures += test_equality(empty,
				mysqlpp::DateTime(0, 0, 0, 0, 0, 0)) == false;
		failures += test_equality(empty, mysqlpp::Time()) == false;
		failures += test_equality(empty, false) == false;
		failures += test_equality(nonzero, true) == false;
		failures += test_numeric(empty, 0) == false;
		failures += test_numeric(zero, 0) == false;
		failures += test_numeric(nonzero, 42) == false;
		failures += test_quote_q(empty, true) == false;
		failures += test_quote_q(mysqlpp::String("1", typeid(int)),
				false) == false;
		failures += test_float_conversion() == false;
		failures += test_float_conversion() == false;
		failures += test_int_conversion(empty, false) == false;
		failures += test_int_conversion(zero, false) == false;
		failures += test_int_conversion(nonzero, false) == false;
		failures += test_int_conversion(intable1, false) == false;
		failures += test_int_conversion(intable2, false) == false;
		failures += test_int_conversion(nonint, true) == false;
		failures += test_null() == false;
		failures += test_string_equality(empty, "") == false;
		failures += test_string_equality(zero, "0") == false;

		return failures;
	}
	catch (mysqlpp::Exception& e) {
		std::cerr << "Unexpected MySQL++ exception caught in " <<
				argv[0] << ": " << e.what() << std::endl;
		return 1;
	}
	catch (std::exception& e) {
		std::cerr << "Unexpected C++ exception caught in " <<
				argv[0] << ": " << e.what() << std::endl;
		return 1;
	}

}

<commit_msg>Added several more test cases for string equality<commit_after>/***********************************************************************
 test/string.cpp - Tests the behavior of mysqlpp::String, particularly
	its data conversion methods.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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 Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>

// Does an equality comparison on the value, forcing the string to
// convert itself to T on the way.  Note that we do this test in terms
// of greater and less than to avoid pedantic GCC warnings for the
// floating point type tests.
template <typename T>
static bool
test_equality(const mysqlpp::String& s, T value)
{
	T converted = s.conv(value);
	if ((value < converted) || (value > converted)) {
		std::cerr << "Type conversion to " << typeid(T).name() <<
				" failed: \"" << s << "\" != \"" << value << "\"." <<
				std::endl;
		return false;
	}
	else {
		return true;
	}
}

// Check that we can convert strings with decimals in them to native
// floating-point values, regardless of locale.
static bool
test_float_conversion()
{
	// This stuff should just work
	if (!test_equality(mysqlpp::String("123.00"), 123)) return false;
	if (!test_equality(mysqlpp::String("123."), 123)) return false;

	// This is trickier: MySQL ignores the system locale when it comes
	// to decimal separators, always using '.', so ensure the conversion
	// stuff in MySQL++ does the right thing regardless.  Test against
	// this system's current locale, an arbitrary European one where ','
	// is the decimal separator, and the "C" locale where it's '.'.
	if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	std::locale old_locale = std::locale::global(std::locale::classic());
	if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	try {
		std::locale::global(std::locale("de_DE"));
		if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	}
	catch (std::runtime_error& e) {
		std::cerr << "WARNING: skipping European locale string "
				"conversion test:" << std::endl;
		std::cerr << "\t" << e.what() << std::endl;
	}
	std::locale::global(old_locale);

	// Check that we choke on silly float-like values
	try {
		if (test_equality(mysqlpp::String("621.20.0"), 621.2)) {
			std::cerr << "Quasi-FP with two decimal points "
					"converting without error!" << std::endl;
		}
		return false;
	}
	catch (const mysqlpp::BadConversion&) {
		return true;
	}
}

// Tries to convert the given string to an int.  Returns false if we got
// a BadConversion exception and didn't expect it, or didn't get one we
// expected.  Returns false on all other exceptions regardless.
static bool
test_int_conversion(const mysqlpp::String& s, bool throw_expected)
{
	// Try the conversion
	bool conv_threw = false;
	try {
		int converted = s;
		(void)converted;	// pedantic warning squisher
	}
	catch (const mysqlpp::BadConversion&) {
		conv_threw = true;
	}
	catch (const std::exception& e) {
		std::cerr << "Unexpected " << typeid(e).name() <<
				" exception in test_int_conv: " << e.what() << std::endl;
		return false;
	}
	catch (...) {
		std::cerr << "Like, totally bogus exception in test_int_conv, "
				"man!" << std::endl;
		return false;
	}

	// Did it do what we expected?
	if (throw_expected == conv_threw) {
		return true;
	}
	else {
		std::cerr << "Conversion of \"" << s << "\" to int " <<
				(conv_threw ? "did not throw" : "threw") << "; " <<
				(throw_expected ? "did not expect" : "expected") <<
				" it to." << std::endl;
		return false;
	}
}

// Checks that String's null comparison methods work right
static bool
test_null()
{
	mysqlpp::String not_null("", mysqlpp::mysql_type_info::string_type, false);
	mysqlpp::String is_null("", mysqlpp::mysql_type_info::string_type, true);
	if (not_null.is_null() == true) {
		std::cerr << "not_null.is_null() == true!" << std::endl;
		return false;
	}
	else if (not_null == mysqlpp::null) {
		std::cerr << "not_null == mysqlpp:null!" << std::endl;
		return false;
	}
	else if (is_null.is_null() == false) {
		std::cerr << "is_null.is_null() == false!" << std::endl;
		return false;
	}
	else if (is_null != mysqlpp::null) {
		std::cerr << "is_null != mysqlpp:null!" << std::endl;
		return false;
	}
	else {
		return true;
	}
}

// Ensures numeric conversions of many different types get handled
// correctly.
static bool
test_numeric(const mysqlpp::String& s, int value)
{
	return	test_equality(s, static_cast<signed char>(value)) &&
			test_equality(s, static_cast<unsigned char>(value)) &&
			test_equality(s, static_cast<signed short>(value)) &&
			test_equality(s, static_cast<unsigned short>(value)) &&
			test_equality(s, static_cast<signed int>(value)) &&
			test_equality(s, static_cast<unsigned int>(value)) &&
			test_equality(s, static_cast<signed long>(value)) &&
			test_equality(s, static_cast<unsigned long>(value)) &&
#if !defined(NO_LONG_LONGS)
			test_equality(s, static_cast<mysqlpp::longlong>(value)) &&
			test_equality(s, static_cast<mysqlpp::ulonglong>(value)) &&
#endif
			test_equality(s, static_cast<float>(value)) &&
			test_equality(s, static_cast<double>(value));
}

static bool
test_quote_q(const mysqlpp::String& s, bool expected)
{
	if (s.quote_q() == expected) {
		return true;
	}
	else {
		std::cerr << s.type().name() << " should" <<
				(expected ? "" : " NOT") << " be quoted." << std::endl;
		return false;
	}
}

// Similar to test_equality, but only works with std::string
// comparisons, which uses String::operator ==()
static bool
test_string_equality(const mysqlpp::String& s, std::string value)
{
	if (s == value) {
		if (s != value) {
			std::cerr << "String(\"" << s << "\") != std::string(\"" <<
					value << "\"), case 2!" << std::endl;
			return false;
		}
		else {
			return true;
		}
	}
	else {
		std::cerr << "String(\"" << s << "\") != std::string(\"" <<
				value << "\"), case 1!" << std::endl;
		return false;
	}
}

// Same as above, but for two String objects
static bool
test_string_equality(const mysqlpp::String& s1,
		const mysqlpp::String s2)
{
	if (s1 == s2) {
		return true;
	}
	else {
		std::cerr << "String(\"" << s1 << "\") != String(\"" <<
				s2 << "\"), but should be equal!" << std::endl;
		return false;
	}
}

// Inverse of above.
static bool
test_string_inequality(const mysqlpp::String& s1,
		const mysqlpp::String& s2)
{
	if (s1 != s2) {
		return true;
	}
	else {
		std::cerr << "String(\"" << s1 << "\") == String(\"" <<
				s2 << "\") but shouldn't be!" << std::endl;
		return false;
	}
}

int
main(int, char* argv[])
{
	try {
		int failures = 0;
		mysqlpp::String definit;
		mysqlpp::String empty("");
		mysqlpp::String zero("0");
		mysqlpp::String nonzero("42");
		mysqlpp::String intable1("42.");
		mysqlpp::String intable2("42.0");
		mysqlpp::String nonint("42.1");

		failures += test_equality(definit, mysqlpp::Date()) == false;
		failures += test_equality(definit,
				mysqlpp::DateTime(0, 0, 0, 0, 0, 0)) == false;
		failures += test_equality(definit, mysqlpp::Time()) == false;
		failures += test_equality(definit, false) == false;
		failures += test_equality(nonzero, true) == false;
		failures += test_numeric(definit, 0) == false;
		failures += test_numeric(zero, 0) == false;
		failures += test_numeric(nonzero, 42) == false;
		failures += test_quote_q(definit, true) == false;
		failures += test_quote_q(mysqlpp::String("1", typeid(int)),
				false) == false;
		failures += test_float_conversion() == false;
		failures += test_float_conversion() == false;
		failures += test_int_conversion(definit, false) == false;
		failures += test_int_conversion(zero, false) == false;
		failures += test_int_conversion(nonzero, false) == false;
		failures += test_int_conversion(intable1, false) == false;
		failures += test_int_conversion(intable2, false) == false;
		failures += test_int_conversion(nonint, true) == false;
		failures += test_null() == false;
		failures += test_string_equality(definit, empty) == false;
		failures += test_string_equality(empty, definit) == false;
		failures += test_string_equality(definit, "") == false;
		failures += test_string_equality(zero, "0") == false;
		failures += test_string_inequality(definit, zero) == false;
		failures += test_string_inequality(zero, definit) == false;

		return failures;
	}
	catch (mysqlpp::Exception& e) {
		std::cerr << "Unexpected MySQL++ exception caught in " <<
				argv[0] << ": " << e.what() << std::endl;
		return 1;
	}
	catch (std::exception& e) {
		std::cerr << "Unexpected C++ exception caught in " <<
				argv[0] << ": " << e.what() << std::endl;
		return 1;
	}

}

<|endoftext|>


<commit_before>#include <common/defaults.h>
#include <common/list.h>
#include <common/map.h>
#include <common/log.h>
#include <common/string.h>
#include <gui/gui.h>
#include <gdb/gdb.h>
#include <gdb/result.h>
#include <gdb/memory.h>
#include <gdb/variable.h>
#include <user_cmd/cmd.h>
#include <user_cmd/subcmd.hash.h>
#include <user_cmd/pertypes.h>
#include <user_cmd/per.tab.h>
#include <user_cmd/per.lex.h>
#include <map>
#include <string>

using namespace std;

/* macros */
#define CTOI(c) (unsigned int)((c) - ((c) >= 'a' ? 87 : 48))
#define ALIGN(val, base) ((val) & (~(base - 1)))

/* static variables */
static char* per_file = 0;
static per_range_t* range_lst = 0;
static map<unsigned int, per_range_t*> line_map;
static map<string, per_register_t*> reg_map;

/* global functions */
int cmd_per_exec(int argc, char** argv){
	int r;
	const struct user_subcmd_t* scmd;
	FILE* fp;
	per_range_t* range;
	per_register_t* reg;
	per_bits_t* bits;
	map<unsigned int, per_range_t*>::iterator it_range;
	map<string, per_register_t*>::iterator it_reg;

	if(argc < 2){
		USER("invalid number of arguments to command \"%s\"\n", argv[0]);
		cmd_per_help(1, argv);
		return 0;
	}

	scmd = user_subcmd::lookup(argv[1], strlen(argv[1]));

	if((scmd == 0 && argc < 2) || (scmd != 0 && ((scmd->id == FOLD && argc < 3) || ((scmd->id == SET || scmd->id == COMPLETE || scmd->id == EXPORT) && argc < 4)))){
		USER("invalid number of arguments to command \"%s\"\n", argv[0]);
		cmd_per_help(2, argv);
		return 0;
	}

	if(scmd == 0){
		/* de-initialise */
		cmd_per_cleanup();

		/* parser peripheral file */
		fp = fopen(argv[1], "r");

		if(fp == 0){
			USER("cannot open file \"%s\"\n", argv[1]);
			return -1;
		}

		r = perparse(fp, &range_lst);
		perlex_destroy();

		fclose(fp);

		if(r != 0){
			USER("error parsing peripheral file \"%s\"\n", argv[1]);
			return -1;
		}

		/* initialise memory segments */
		list_for_each(range_lst, range){
			// read respective memory
			range->mem = gdb_memory_t::acquire(range->base, range->size);

			if(range->mem == 0){
				USER("unable to create memory segment for range \"%s\" (%p, %u)\n", range->name, range->base, range->size);

				cmd_per_cleanup();
				cmd_per_update();

				return -1;
			}

			list_for_each(range->regs, reg){
				if(reg->name)
					strdeescape(reg->name);

				if(reg->nbytes == 0)
					continue;

				// check integrity of register to range
				if(reg->offset + reg->nbytes >  range->size){
					USER("error: offset/size of register \"%s\" exceeds size of range \"%s\"\n", reg->name, range->name);

					cmd_per_cleanup();
					cmd_per_update();

					return -1;
				}

				// check integrity of bits to register
				list_for_each(reg->bits, bits){
					if(bits->idx + bits->nbits > reg->nbytes * 8){
						USER("error: index/size of bits \"%s\" exceeds size of register \"%s\"\n", bits->name, reg->name);

						cmd_per_cleanup();
						cmd_per_update();

						return -1;
					}
				}

				// update list of registers
				reg->parent = range;
				reg_map[reg->name] = reg;
			}

			USER("add memory segment for range \"%s\" (%p, %u)\n", range->name, range->base, range->size);
		}

		delete [] per_file;
		per_file = stralloc(argv[1], strlen(argv[1]));

		cmd_per_update();
	}
	else{
		switch(scmd->id){
		case SET:
			reg = MAP_LOOKUP(reg_map, argv[2]);

			if(reg == 0){
				USER("unknown register name \"%s\"\n", argv[2]);
				return 0;
			}

			if(gdb_memory_t::set((void*)((unsigned long long)reg->parent->base + reg->offset), argv[3], reg->nbytes) != 0)
				return -1;

			gdb->memory_update();
			break;

		case FOLD:
			range = MAP_LOOKUP(line_map, atoi(argv[2]));

			if(range == 0){
				USER("no peripheral segment at line %s\n", argv[2]);
				return 0;
			}

			range->expanded = range->expanded ? false : true;

			cmd_per_update();
			break;

		case COMPLETE:
			fp = fopen(argv[2], "w");

			if(fp == 0)
				return -1;

			for(it_range=line_map.begin(); it_range!=line_map.end(); it_range++)
				fprintf(fp, "%d\\n", it_range->first);

			fprintf(fp, "<regs>");

			for(it_reg=reg_map.begin(); it_reg!=reg_map.end(); it_reg++)
				fprintf(fp, "%s\\n", it_reg->second->name);

			fclose(fp);

			/* signal data availability */
			fp = fopen(argv[3], "w");

			if(fp == 0)
				return -1;

			fprintf(fp, "1\n");
			fclose(fp);
			break;

		case EXPORT:
			fp = fopen(argv[2], "w");

			if(fp == 0)
				return 0;

			if(per_file)		fprintf(fp, "Per %s\n\n", per_file);

			fclose(fp);

			USER("export peripheral commands to \"%s\"\n", argv[2]);

			/* signal data availability */
			fp = fopen(argv[3], "w");

			if(fp == 0)
				return -1;

			fprintf(fp, "1\n");
			fclose(fp);
			break;

		case VIEW:
			cmd_per_update();
			break;

		default:
			USER("unhandled sub command \"%s\" to \"%s\"\n", argv[1], argv[0]);
		};
	}

	return 0;
}

void cmd_per_cleanup(){
	per_range_t* range;

	delete [] per_file;
	per_file = 0;

	reg_map.clear();
	line_map.clear();

	list_for_each(range_lst, range){
		list_rm(&range_lst, range);
		delete range;
	}
}

void cmd_per_help(int argc, char** argv){
	int i;
	const struct user_subcmd_t* scmd;

	ui->atomic(true);

	if(argc == 1){
		USER("usage: %s [sub-command] <args>...\n", argv[0]);
		USER("   sub-commands:\n");
		USER("      <file>                          set peripheral file\n");
		USER("      set <register> <value> [<cnt>]  set register\n");
		USER("      fold <line>                     fold/unfold peripheral segment\n");
		USER("      complete <file> <sync>          get list of peripheral segments and addresses\n");
		USER("      export <file> <sync>            export used peripheral file to vim script\n");
		USER("      view                            update per window\n");
		USER("\n");
	}
	else{
		for(i=1; i<argc; i++){
			scmd = user_subcmd::lookup(argv[i], strlen(argv[i]));

			if(scmd == 0){
				USER("invalid sub-command \"%s\" to command \"%s\"\n", argv[i], argv[0]);
				continue;
			}

			switch(scmd->id){
			case SET:
				USER("usage %s %s <register> <value> [<count>]\n", argv[0], argv[i]);
				USER("   set register <register> to <value>\n");
				USER("\n");
				break;

			case FOLD:
				USER("usage %s %s <line>\n", argv[0], argv[i]);
				USER("   fold/unfold peripheral segment at line <line>\n");
				USER("\n");
				break;

			case COMPLETE:
				USER("usage %s %s <file> <sync>\n", argv[0], argv[i]);
				USER("   print list of line numbers and addresses to file <file>, using file <sync> to sync with vim\n");
				USER("   both lists are separated by '<addr>'\n");
				USER("   the items of each list are '\\n' separated\n");
				USER("\n");
				break;

			case EXPORT:
				USER("usage %s %s <file> <sync>\n", argv[0], argv[1]);
				USER("   export peripheral file to vim script <file>, using file <sync> to sync with vim\n");
				USER("\n");
				break;

			case VIEW:
				break;

			default:
				USER("invalid sub-command \"%s\" to command \"%s\"\n", argv[i], argv[0]);
			};
		}
	}

	ui->win_cursor_set(ui->win_getid(USERLOG_NAME), -1);
	ui->atomic(false);
}

int cmd_per_update(){
	char c;
	int win_id;
	unsigned int line;
	unsigned long long reg_val, bit_val;
	bool changed;
	gdb_memory_t *mem;
	per_range_t* range;
	per_register_t* reg;
	per_bits_t* bits;

	win_id = ui->win_getid(PER_NAME);

	if(win_id < 0)
		return 0;

	line_map.clear();
	line = 1;

	ui->atomic(true);
	ui->win_clear(win_id);

	list_for_each(range_lst, range){
		/* print header */
		ui->win_print(win_id, "[%c] %s\n", (range->expanded ? '-' : '+'), range->name);
		line_map[line++] = range;

		if(!range->expanded){
			ui->win_print(win_id, "\n");
			line++;
			continue;
		}

		/* get memory content */
		mem = range->mem;

		if(mem->update() != 0){
			ui->atomic(false);
			return -1;
		}

		/* print register values */
		list_for_each(range->regs, reg){
			if(reg->nbytes == 0){
				ui->win_print(win_id, "%s\n", reg->name ? reg->name : "");
				line_map[line] = range;
				line++;

				continue;
			}

			changed = memcmp(mem->content + reg->offset * 2, mem->content_old + reg->offset * 2, reg->nbytes * 2);

			ui->win_print(win_id, " %s = %s%.*s\n", reg->name, (changed ? "`" : ""), reg->nbytes * 2, mem->content + reg->offset * 2);

			line_map[line] = range;
			line++;

			// print bits
			if(reg->bits){
				c = mem->content[reg->offset * 2 + reg->nbytes * 2];
				mem->content[reg->offset * 2 + reg->nbytes * 2] = 0;

				reg_val = strtoll(mem->content + reg->offset * 2, 0, 16);
				mem->content[reg->offset * 2 + reg->nbytes * 2] = c;

				list_for_each(reg->bits, bits){
					bit_val = (reg_val & (bits->mask << bits->idx)) >> bits->idx;

					changed = (bit_val == bits->value) ? false : true;
					bits->value = bit_val;

					ui->win_print(win_id, "  %s %s%0*.*x", bits->name, (changed ? "`" : ""), bits->nbits / 4, bits->nbits / 4, bit_val);
				}

				line_map[line] = range;
				ui->win_print(win_id, "\n\n");
				line += 2;
			}
		}
	}

	ui->atomic(false);

	return 0;
}
<commit_msg>[user-cmd: per]<commit_after>#include <common/defaults.h>
#include <common/list.h>
#include <common/map.h>
#include <common/log.h>
#include <common/string.h>
#include <gui/gui.h>
#include <gdb/gdb.h>
#include <gdb/result.h>
#include <gdb/memory.h>
#include <gdb/variable.h>
#include <user_cmd/cmd.h>
#include <user_cmd/subcmd.hash.h>
#include <user_cmd/pertypes.h>
#include <user_cmd/per.tab.h>
#include <user_cmd/per.lex.h>
#include <map>
#include <string>

using namespace std;

/* macros */
#define CTOI(c) (unsigned int)((c) - ((c) >= 'a' ? 87 : 48))
#define ALIGN(val, base) ((val) & (~(base - 1)))

/* static variables */
static char* per_file = 0;
static per_range_t* range_lst = 0;
static map<unsigned int, per_range_t*> line_map;
static map<string, per_register_t*> reg_map;

/* global functions */
int cmd_per_exec(int argc, char** argv){
	int r;
	const struct user_subcmd_t* scmd;
	FILE* fp;
	per_range_t* range;
	per_register_t* reg;
	per_bits_t* bits;
	map<unsigned int, per_range_t*>::iterator it_range;
	map<string, per_register_t*>::iterator it_reg;

	if(argc < 2){
		USER("invalid number of arguments to command \"%s\"\n", argv[0]);
		cmd_per_help(1, argv);
		return 0;
	}

	scmd = user_subcmd::lookup(argv[1], strlen(argv[1]));

	if((scmd == 0 && argc < 2) || (scmd != 0 && ((scmd->id == FOLD && argc < 3) || ((scmd->id == SET || scmd->id == COMPLETE || scmd->id == EXPORT) && argc < 4)))){
		USER("invalid number of arguments to command \"%s\"\n", argv[0]);
		cmd_per_help(2, argv);
		return 0;
	}

	if(scmd == 0){
		/* de-initialise */
		cmd_per_cleanup();

		/* parser peripheral file */
		fp = fopen(argv[1], "r");

		if(fp == 0){
			USER("cannot open file \"%s\"\n", argv[1]);
			return -1;
		}

		r = perparse(fp, &range_lst);
		perlex_destroy();

		fclose(fp);

		if(r != 0){
			USER("error parsing peripheral file \"%s\"\n", argv[1]);
			return -1;
		}

		/* initialise memory segments */
		list_for_each(range_lst, range){
			// read respective memory
			range->mem = gdb_memory_t::acquire(range->base, range->size);

			if(range->mem == 0){
				USER("unable to create memory segment for range \"%s\" (%p, %u)\n", range->name, range->base, range->size);

				cmd_per_cleanup();
				cmd_per_update();

				return -1;
			}

			list_for_each(range->regs, reg){
				if(reg->name)
					strdeescape(reg->name);

				if(reg->nbytes == 0)
					continue;

				// check integrity of register to range
				if(reg->offset + reg->nbytes >  range->size){
					USER("error: offset/size of register \"%s\" exceeds size of range \"%s\"\n", reg->name, range->name);

					cmd_per_cleanup();
					cmd_per_update();

					return -1;
				}

				// check integrity of bits to register
				list_for_each(reg->bits, bits){
					if(bits->idx + bits->nbits > reg->nbytes * 8){
						USER("error: index/size of bits \"%s\" exceeds size of register \"%s\"\n", bits->name, reg->name);

						cmd_per_cleanup();
						cmd_per_update();

						return -1;
					}
				}

				// update list of registers
				reg->parent = range;
				reg_map[reg->name] = reg;
			}

			USER("add memory segment for range \"%s\" (%p, %u)\n", range->name, range->base, range->size);
		}

		delete [] per_file;
		per_file = stralloc(argv[1], strlen(argv[1]));

		cmd_per_update();
	}
	else{
		switch(scmd->id){
		case SET:
			reg = MAP_LOOKUP(reg_map, argv[2]);

			if(reg == 0){
				USER("unknown register name \"%s\"\n", argv[2]);
				return 0;
			}

			if(gdb_memory_t::set((void*)((unsigned long long)reg->parent->base + reg->offset), argv[3], reg->nbytes) != 0)
				return -1;

			gdb->memory_update();
			break;

		case FOLD:
			range = MAP_LOOKUP(line_map, atoi(argv[2]));

			if(range == 0){
				USER("no peripheral segment at line %s\n", argv[2]);
				return 0;
			}

			range->expanded = range->expanded ? false : true;

			cmd_per_update();
			break;

		case COMPLETE:
			fp = fopen(argv[2], "w");

			if(fp == 0)
				return -1;

			for(it_range=line_map.begin(); it_range!=line_map.end(); it_range++)
				fprintf(fp, "%d\\n", it_range->first);

			fprintf(fp, "<regs>");

			for(it_reg=reg_map.begin(); it_reg!=reg_map.end(); it_reg++)
				fprintf(fp, "%s\\n", it_reg->second->name);

			fclose(fp);

			/* signal data availability */
			fp = fopen(argv[3], "w");

			if(fp == 0)
				return -1;

			fprintf(fp, "1\n");
			fclose(fp);
			break;

		case EXPORT:
			fp = fopen(argv[2], "w");

			if(fp == 0)
				return 0;

			if(per_file)		fprintf(fp, "Per %s\n\n", per_file);

			fclose(fp);

			USER("export peripheral commands to \"%s\"\n", argv[2]);

			/* signal data availability */
			fp = fopen(argv[3], "w");

			if(fp == 0)
				return -1;

			fprintf(fp, "1\n");
			fclose(fp);
			break;

		case VIEW:
			cmd_per_update();
			break;

		default:
			USER("unhandled sub command \"%s\" to \"%s\"\n", argv[1], argv[0]);
		};
	}

	return 0;
}

void cmd_per_cleanup(){
	per_range_t* range;

	delete [] per_file;
	per_file = 0;

	reg_map.clear();
	line_map.clear();

	list_for_each(range_lst, range){
		list_rm(&range_lst, range);
		delete range;
	}
}

void cmd_per_help(int argc, char** argv){
	int i;
	const struct user_subcmd_t* scmd;

	ui->atomic(true);

	if(argc == 1){
		USER("usage: %s [sub-command] <args>...\n", argv[0]);
		USER("   sub-commands:\n");
		USER("      <file>                          set peripheral file\n");
		USER("      set <register> <value> [<cnt>]  set register\n");
		USER("      fold <line>                     fold/unfold peripheral segment\n");
		USER("      complete <file> <sync>          get list of peripheral segments and addresses\n");
		USER("      export <file> <sync>            export used peripheral file to vim script\n");
		USER("      view                            update per window\n");
		USER("\n");
	}
	else{
		for(i=1; i<argc; i++){
			scmd = user_subcmd::lookup(argv[i], strlen(argv[i]));

			if(scmd == 0){
				USER("invalid sub-command \"%s\" to command \"%s\"\n", argv[i], argv[0]);
				continue;
			}

			switch(scmd->id){
			case SET:
				USER("usage %s %s <register> <value> [<count>]\n", argv[0], argv[i]);
				USER("   set register <register> to <value>\n");
				USER("\n");
				break;

			case FOLD:
				USER("usage %s %s <line>\n", argv[0], argv[i]);
				USER("   fold/unfold peripheral segment at line <line>\n");
				USER("\n");
				break;

			case COMPLETE:
				USER("usage %s %s <file> <sync>\n", argv[0], argv[i]);
				USER("   print list of line numbers and addresses to file <file>, using file <sync> to sync with vim\n");
				USER("   both lists are separated by '<addr>'\n");
				USER("   the items of each list are '\\n' separated\n");
				USER("\n");
				break;

			case EXPORT:
				USER("usage %s %s <file> <sync>\n", argv[0], argv[1]);
				USER("   export peripheral file to vim script <file>, using file <sync> to sync with vim\n");
				USER("\n");
				break;

			case VIEW:
				break;

			default:
				USER("invalid sub-command \"%s\" to command \"%s\"\n", argv[i], argv[0]);
			};
		}
	}

	ui->win_cursor_set(ui->win_getid(USERLOG_NAME), -1);
	ui->atomic(false);
}

int cmd_per_update(){
	char c;
	int win_id;
	unsigned int line, i;
	unsigned long long reg_val, bit_val;
	bool changed;
	gdb_memory_t *mem;
	per_range_t* range;
	per_register_t* reg;
	per_bits_t* bits;

	win_id = ui->win_getid(PER_NAME);

	if(win_id < 0)
		return 0;

	line_map.clear();
	line = 1;

	ui->atomic(true);
	ui->win_clear(win_id);

	list_for_each(range_lst, range){
		/* print header */
		ui->win_print(win_id, "[%c] %s\n", (range->expanded ? '-' : '+'), range->name);
		line_map[line++] = range;

		if(!range->expanded){
			ui->win_print(win_id, "\n");
			line++;
			continue;
		}

		/* get memory content */
		mem = range->mem;

		if(mem->update() != 0){
			ui->atomic(false);
			return -1;
		}

		/* print register values */
		list_for_each(range->regs, reg){
			if(reg->nbytes == 0){
				ui->win_print(win_id, "%s\n", reg->name ? reg->name : "");
				line_map[line] = range;
				line++;

				continue;
			}

			changed = memcmp(mem->content + reg->offset * 2, mem->content_old + reg->offset * 2, reg->nbytes * 2);

			ui->win_print(win_id, " %s = %s%.*s\n", reg->name, (changed ? "`" : ""), reg->nbytes * 2, mem->content + reg->offset * 2);

			line_map[line] = range;
			line++;

			// print bits
			if(reg->bits){
				c = mem->content[reg->offset * 2 + reg->nbytes * 2];
				mem->content[reg->offset * 2 + reg->nbytes * 2] = 0;

				reg_val = strtoll(mem->content + reg->offset * 2, 0, 16);
				mem->content[reg->offset * 2 + reg->nbytes * 2] = c;

				i = 0;
				list_for_each(reg->bits, bits){
					if(i && i % 4 == 0){
						line_map[line] = range;
						ui->win_print(win_id, "\n");
						line++;
					}

					bit_val = (reg_val & (bits->mask << bits->idx)) >> bits->idx;

					changed = (bit_val == bits->value) ? false : true;
					bits->value = bit_val;

					ui->win_print(win_id, "  %s %s%0*.*x", bits->name, (changed ? "`" : ""), bits->nbits / 4, bits->nbits / 4, bit_val);
					i++;
				}

				line_map[line] = range;
				ui->win_print(win_id, "\n\n");
				line += 2;
			}
		}
	}

	ui->atomic(false);

	return 0;
}
<|endoftext|>


<commit_before>
#include "do_sort.h"

#define DATA_SIZE 20
#define DUMP_DATA 0

using namespace std;

// Check whether the list is correctly sorted.
bool is_sorted(do_sort::sort* ss) {
  for (int i = 0; i < ss->size() - 1; ++i)
    if ((*ss)[i] > (*ss)[i + 1])
      return false;

  return true;
}

// Report the testing results.
void report_test_result(do_sort::sort* ss, string sorting_method) {
  string test_result = (is_sorted(ss)) ? "\033[32mPASSED" : "\033[31mFAILED";
  cout << sorting_method << " test --> " << "[" << test_result << "\033[39m]" << endl;;
}

int main() {
  string test_result = "";

  cout << endl << endl << "-------------------- \033[34mTesting Results\033[39m --------------------" << endl;

  // Unit test for the bubble sort.
  do_sort::bubble_sort *bs = new do_sort::bubble_sort();
  bs->init(DATA_SIZE);
  bs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(bs), "Bubble sort");
#if DUMP_DATA
  bs->dump("Bubble Sort");
#endif
  delete bs;

  // Unit test for the selection sort.
  do_sort::selection_sort *ss = new do_sort::selection_sort();
  ss->init(DATA_SIZE);
  ss->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ss), "Selection sort");
#if DUMP_DATA
  ss->dump("Selection Sort");
#endif
  delete ss;

  // Unit test for the insertion sort.
  do_sort::insertion_sort *is = new do_sort::insertion_sort();
  is->init(DATA_SIZE);
  is->do_sort();
  report_test_result(static_cast<do_sort::sort*>(is), "Insertion sort");
#if DUMP_DATA
  is->dump("Insertion Sort");
#endif
  delete is;

  // Unit test for the merge sort.
  do_sort::merge_sort *ms = new do_sort::merge_sort();
  ms->init(DATA_SIZE);
  ms->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ms), "Merge sort");
#if DUMP_DATA
  ms->dump("Merge Sort");
#endif
  delete ms;

  // Unit test for the quick sort.
  do_sort::quick_sort *qs = new do_sort::quick_sort();
  qs->init(DATA_SIZE);
  qs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(qs), "Quick sort");
#if DUMP_DATA
  qs->dump("Quick Sort");
#endif
  delete qs;

  cout << "---------------------------------------------------------" << endl << endl;

  return 0;
}

<commit_msg>Added some corner cases to the test cases and made the report nicer.<commit_after>
#include "do_sort.h"

#define DATA_SIZE 20
#define DUMP_DATA 0

using namespace std;

// Check whether the list is correctly sorted.
bool is_sorted(do_sort::sort* ss) {
  if (ss->size() == 0)
    return true;

  for (int i = 0; i < ss->size() - 1; ++i)
    if ((*ss)[i] > (*ss)[i + 1])
      return false;

  return true;
}

// Report the testing results.
void report_test_result(do_sort::sort* ss, string sorting_method) {
  string test_result = (is_sorted(ss)) ? "\033[32mPASSED" : "\033[31mFAILED";
  cout << sorting_method << " test --> " << "[" << test_result << "\033[39m]" << endl;;
}

int main() {
  string test_result = "";

  cout << endl << endl << "-------------------- \033[34mTesting Results\033[39m --------------------" << endl;

  // Unit test for the bubble sort.
  do_sort::bubble_sort *bs = new do_sort::bubble_sort();

  bs->init(DATA_SIZE);
  bs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(bs), "Bubble sort");

  bs->clear_data();
  bs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(bs), "Bubble sort [corner case #1]");

  bs->init(1);
  bs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(bs), "Bubble sort [corner case #2]");

  cout << "\033[36m---------------------------------------------------------\033[39m" << endl;

#if DUMP_DATA
  bs->dump("Bubble Sort");
#endif
  delete bs;

  // Unit test for the selection sort.
  do_sort::selection_sort *ss = new do_sort::selection_sort();
  ss->init(DATA_SIZE);
  ss->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ss), "Selection sort");

  ss->clear_data();
  ss->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ss), "Selection sort [corner case #1]");

  ss->init(1);
  ss->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ss), "Selection sort [corner case #2]");

  cout << "\033[36m---------------------------------------------------------\033[39m" << endl;

#if DUMP_DATA
  ss->dump("Selection Sort");
#endif
  delete ss;

  // Unit test for the insertion sort.
  do_sort::insertion_sort *is = new do_sort::insertion_sort();
  is->init(DATA_SIZE);
  is->do_sort();
  report_test_result(static_cast<do_sort::sort*>(is), "Insertion sort");

  is->clear_data();
  is->do_sort();
  report_test_result(static_cast<do_sort::sort*>(is), "Insertion sort [corner case #1]");

  is->init(1);
  is->do_sort();
  report_test_result(static_cast<do_sort::sort*>(is), "Insertion sort [corner case #2]");

  cout << "\033[36m---------------------------------------------------------\033[39m" << endl;

#if DUMP_DATA
  is->dump("Insertion Sort");
#endif
  delete is;

  // Unit test for the merge sort.
  do_sort::merge_sort *ms = new do_sort::merge_sort();
  ms->init(DATA_SIZE);
  ms->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ms), "Merge sort");

  ms->clear_data();
  ms->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ms), "Merge sort [corner case #1]");

  ms->init(1);
  ms->do_sort();
  report_test_result(static_cast<do_sort::sort*>(ms), "Merge sort [corner case #2]");

  cout << "\033[36m---------------------------------------------------------\033[39m" << endl;

#if DUMP_DATA
  ms->dump("Merge Sort");
#endif
  delete ms;

  // Unit test for the quick sort.
  do_sort::quick_sort *qs = new do_sort::quick_sort();
  qs->init(DATA_SIZE);
  qs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(qs), "Quick sort");

  qs->clear_data();
  qs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(qs), "Quick sort [corner case #1]");

  qs->init(1);
  qs->do_sort();
  report_test_result(static_cast<do_sort::sort*>(qs), "Quick sort [corner case #2]");

#if DUMP_DATA
  qs->dump("Quick Sort");
#endif
  delete qs;

  cout << "---------------------------------------------------------" << endl << endl;

  return 0;
}

<|endoftext|>


<commit_before>#include <ctre.hpp>
#include <iostream>

static constexpr auto pattern = ctll::fixed_string("(?<first>[0-9])[0-9]++");

int main() {
	using namespace std::string_view_literals;
	auto input = "123,456,768"sv;

	#if __cpp_nontype_template_parameter_class
	    for (auto match: ctre::range<"(?<first>[0-9])[0-9]++">(input)) {
	#else
		using namespace ctre::literals;

		for (auto match: ctre::range<pattern>(input)) {
	#endif

	#if __cpp_nontype_template_parameter_class
			std::cout << std::string_view(match.get<"firs2t">()) << "\n";
	#else
			std::cout << std::string_view(match.get<1>()) << "\n";
	#endif
		}
}
<commit_msg>remove intentional (and forget) typo<commit_after>#include <ctre.hpp>
#include <iostream>

static constexpr auto pattern = ctll::fixed_string("(?<first>[0-9])[0-9]++");

int main() {
	using namespace std::string_view_literals;
	auto input = "123,456,768"sv;

	#if __cpp_nontype_template_parameter_class
	    for (auto match: ctre::range<"(?<first>[0-9])[0-9]++">(input)) {
	#else
		using namespace ctre::literals;

		for (auto match: ctre::range<pattern>(input)) {
	#endif

	#if __cpp_nontype_template_parameter_class
			std::cout << std::string_view(match.get<"first">()) << "\n";
	#else
			std::cout << std::string_view(match.get<1>()) << "\n";
	#endif
		}
}
<|endoftext|>


<commit_before>//
// Created by kanairen on 2016/06/14.
//

#include "TestLayer.h"
#include "TestSoftMaxLayer.h"
#include "TestGridLayer.h"
#include "TestConvLayer.h"
#include "TestMaxPoolLayer.h"

#include "TestModel.h"

int main() {

    // test Softmax Layer
    sm_layer::test_init();
    sm_layer::test_forward();
    sm_layer::test_backward();

    // test Grid Layer
    grid_layer::test_init();
    grid_layer::test_filter_outsize();

    // test Convolution Layer
    conv_layer::test_init();
    conv_layer::test_backward();

    // test MaxPooling Layer
    max_pool_layer::test_init();
    max_pool_layer::test_forward();
    max_pool_layer::test_backward();

    // test Model
    model::test_init();
    model::test_forward();
    model::test_backward();

    return RUN_ALL_TESTS();

}
<commit_msg>fix GoogleTestのフラグ初期化を追加<commit_after>//
// Created by kanairen on 2016/06/14.
//

#include "TestLayer.h"
#include "TestSoftMaxLayer.h"
#include "TestGridLayer.h"
#include "TestConvLayer.h"
#include "TestMaxPoolLayer.h"

#include "TestModel.h"

int main(int argc, char **argv) {

    // Google Test
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();

}
<|endoftext|>


<commit_before>// SPDX-FileCopyrightText: 2014 Félix Robles <felrobelv@gmail.com>
// SPDX-FileCopyrightText: 2021 Eduardo Robles <edulix@nvotes.com>
//
// SPDX-License-Identifier: AGPL-3.0-only

#include <agora-airgap/ElGamal.h>
#include <agora-airgap/encrypt.h>
#include <agora-airgap/sha256.h>
#include <cryptopp/cryptlib.h>
#include <cryptopp/elgamal.h>
#include <cryptopp/files.h>
#include <cryptopp/osrng.h>
#include <cryptopp/secblock.h>
#include <gmock/gmock.h>
#include <gmpxx.h>
#include <gtest/gtest.h>
#include <memory.h>

#include <cstring>
#include <iostream>
#include <string>
#include <vector>

using namespace AgoraAirgap::sha256;
using namespace CryptoPP;
using std::function;
using std::string;
using std::stringstream;
using ::testing::HasSubstr;
using ::testing::ThrowsMessage;

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(Sha256Test, StringOne)
{
    BYTE text1[] = {"abc"};
    BYTE hash1[SHA256_BLOCK_SIZE] = {
        0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40,
        0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17,
        0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad};
    BYTE buf[SHA256_BLOCK_SIZE];
    SHA256_CTX ctx;
    sha256_init(&ctx);
    sha256_update(&ctx, text1, sizeof(text1) - 1);
    sha256_final(&ctx, buf);
    EXPECT_EQ(0, memcmp(hash1, buf, SHA256_BLOCK_SIZE));
}

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(Sha256Test, StringTwo)
{
    BYTE text2[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
    BYTE hash2[SHA256_BLOCK_SIZE] = {
        0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26,
        0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff,
        0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1};
    BYTE buf[SHA256_BLOCK_SIZE];
    SHA256_CTX ctx;
    sha256_init(&ctx);
    sha256_update(&ctx, text2, sizeof(text2) - 1);
    sha256_final(&ctx, buf);
    EXPECT_EQ(0, memcmp(hash2, buf, SHA256_BLOCK_SIZE));
}

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(Sha256Test, StringLoopTest)
{
    BYTE text3[] = {"aaaaaaaaaa"};
    BYTE hash3[SHA256_BLOCK_SIZE] = {
        0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7,
        0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97,
        0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0};
    BYTE buf[SHA256_BLOCK_SIZE];
    SHA256_CTX ctx;
    sha256_init(&ctx);
    for (int idx = 0; idx < 100000; ++idx)
    {
        sha256_update(&ctx, text3, sizeof(text3) - 1);
    }
    sha256_final(&ctx, buf);
    EXPECT_EQ(0, memcmp(hash3, buf, SHA256_BLOCK_SIZE));
}

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(AgoraUnitTest, SmallMessageEncryption)
{
    mpz_t p, q, g, y, x, m, rand;

    mpz_init_set_str(p, "1019", 10);
    mpz_init_set_str(q, "509", 10);  // q = (p-1)/2 = 509
    mpz_init_set_str(g, "3", 10);
    mpz_init_set_str(y, "770", 10);  // y = (g^x) mod p
    mpz_init_set_str(x, "66", 10);
    mpz_init_set_str(m, "133", 10);
    mpz_init_set_str(rand, "4", 10);

    mpz_class p_c(p), q_c(q), g_c(g), x_c(x), y_c(y), rand_c(rand), m_c(m);

    AgoraAirgap::ElGamal::PublicKey pk(p_c, q_c, g_c, y_c);
    AgoraAirgap::ElGamal::Plaintext plaintext(m_c, pk, true);
    AgoraAirgap::ElGamal::Ciphertext ciphertext =
        AgoraAirgap::ElGamal::encrypt(pk, plaintext, rand_c);
    // alpha = (g^random) mod p  = (3^4) mod 1019 = 81
    // U = (y^random) mod p = (770^4) mod 1019 = 508
    // M = m+1 = 134
    // beta = ( U M  ) mod p = ( 508 * 134) mod 1019 = 818

    EXPECT_EQ(0, ciphertext.alpha.get_str().compare("81"));
    EXPECT_EQ(0, ciphertext.beta.get_str().compare("818"));
}

/**
 * Groups examples that should not fail
 */
class ExampleDirsTest : public ::testing::Test
{
    protected:
    void SetUp() override
    {
        this->exampleDirs = std::vector<std::string>({"example_1"});
    }
    std::vector<string> exampleDirs;
};

/**
 * Executes download_audit with correct data
 */
// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST_F(ExampleDirsTest, MockDownloadAudit)
{
    for (string & examplePath: exampleDirs)
    {
        string ballotPath = examplePath + "/ballot.json";
        auto getConfig = [&examplePath](stringstream & out, const string &) {
            return AgoraAirgap::read_file(out, examplePath + "/config");
        };
        stringstream out;
        EXPECT_NO_THROW(
            { AgoraAirgap::download_audit(out, ballotPath, getConfig); });
        EXPECT_EQ(out.str().find("Error"), string::npos)
            << "Error found in output: " << out.str() << std::endl;
    }
}

/**
 * Executes download_audit with invalid data (/config-bad will yield nothing)
 */
// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST_F(ExampleDirsTest, MockBadDownloadAudit)
{
    for (string & examplePath: exampleDirs)
    {
        string ballotPath = examplePath + "/ballot.json";
        auto getConfig = [&examplePath](stringstream & out, const string &) {
            return AgoraAirgap::read_file(out, examplePath + "/config-bad");
        };
        stringstream out;
        EXPECT_THAT(
            [&]() { AgoraAirgap::download_audit(out, ballotPath, getConfig); },
            ThrowsMessage<std::runtime_error>(
                HasSubstr("!!! Error [read-file]")))
            << std::endl
            << "Error found in output: " << out.str() << std::endl;
    }
}
<commit_msg>adding some more unit tests<commit_after>// SPDX-FileCopyrightText: 2014 Félix Robles <felrobelv@gmail.com>
// SPDX-FileCopyrightText: 2021 Eduardo Robles <edulix@nvotes.com>
//
// SPDX-License-Identifier: AGPL-3.0-only

#include <agora-airgap/ElGamal.h>
#include <agora-airgap/encrypt.h>
#include <agora-airgap/sha256.h>
#include <cryptopp/cryptlib.h>
#include <cryptopp/elgamal.h>
#include <cryptopp/files.h>
#include <cryptopp/osrng.h>
#include <cryptopp/secblock.h>
#include <gmock/gmock.h>
#include <gmpxx.h>
#include <gtest/gtest.h>
#include <memory.h>

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>

using namespace AgoraAirgap::sha256;
using namespace CryptoPP;
using std::function;
using std::string;
using std::stringstream;
using ::testing::HasSubstr;
using ::testing::Not;
using ::testing::ThrowsMessage;

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(Sha256Test, StringOne)
{
    BYTE text1[] = {"abc"};
    BYTE hash1[SHA256_BLOCK_SIZE] = {
        0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40,
        0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17,
        0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad};
    BYTE buf[SHA256_BLOCK_SIZE];
    SHA256_CTX ctx;
    sha256_init(&ctx);
    sha256_update(&ctx, text1, sizeof(text1) - 1);
    sha256_final(&ctx, buf);
    EXPECT_EQ(0, memcmp(hash1, buf, SHA256_BLOCK_SIZE));
}

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(Sha256Test, StringTwo)
{
    BYTE text2[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
    BYTE hash2[SHA256_BLOCK_SIZE] = {
        0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26,
        0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff,
        0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1};
    BYTE buf[SHA256_BLOCK_SIZE];
    SHA256_CTX ctx;
    sha256_init(&ctx);
    sha256_update(&ctx, text2, sizeof(text2) - 1);
    sha256_final(&ctx, buf);
    EXPECT_EQ(0, memcmp(hash2, buf, SHA256_BLOCK_SIZE));
}

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(Sha256Test, StringLoopTest)
{
    BYTE text3[] = {"aaaaaaaaaa"};
    BYTE hash3[SHA256_BLOCK_SIZE] = {
        0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7,
        0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97,
        0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0};
    BYTE buf[SHA256_BLOCK_SIZE];
    SHA256_CTX ctx;
    sha256_init(&ctx);
    for (int idx = 0; idx < 100000; ++idx)
    {
        sha256_update(&ctx, text3, sizeof(text3) - 1);
    }
    sha256_final(&ctx, buf);
    EXPECT_EQ(0, memcmp(hash3, buf, SHA256_BLOCK_SIZE));
}

// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST(AgoraUnitTest, SmallMessageEncryption)
{
    mpz_t p, q, g, y, x, m, rand;

    mpz_init_set_str(p, "1019", 10);
    mpz_init_set_str(q, "509", 10);  // q = (p-1)/2 = 509
    mpz_init_set_str(g, "3", 10);
    mpz_init_set_str(y, "770", 10);  // y = (g^x) mod p
    mpz_init_set_str(x, "66", 10);
    mpz_init_set_str(m, "133", 10);
    mpz_init_set_str(rand, "4", 10);

    mpz_class p_c(p), q_c(q), g_c(g), x_c(x), y_c(y), rand_c(rand), m_c(m);

    AgoraAirgap::ElGamal::PublicKey pk(p_c, q_c, g_c, y_c);
    AgoraAirgap::ElGamal::Plaintext plaintext(m_c, pk, true);
    AgoraAirgap::ElGamal::Ciphertext ciphertext =
        AgoraAirgap::ElGamal::encrypt(pk, plaintext, rand_c);
    // alpha = (g^random) mod p  = (3^4) mod 1019 = 81
    // U = (y^random) mod p = (770^4) mod 1019 = 508
    // M = m+1 = 134
    // beta = ( U M  ) mod p = ( 508 * 134) mod 1019 = 818

    EXPECT_EQ(0, ciphertext.alpha.get_str().compare("81"));
    EXPECT_EQ(0, ciphertext.beta.get_str().compare("818"));
}

/**
 * Groups examples that should not fail
 */
class ExampleDirsTest : public ::testing::Test
{
    protected:
    void SetUp() override
    {
        this->exampleDirs = std::vector<std::string>({"example_1"});
    }
    std::vector<string> exampleDirs;
};

/**
 * Executes download_audit with correct data
 */
// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST_F(ExampleDirsTest, MockDownloadAudit)
{
    for (string & examplePath: exampleDirs)
    {
        string ballotPath = examplePath + "/ballot.json";
        auto getConfig = [&examplePath](stringstream & out, const string &) {
            return AgoraAirgap::read_file(out, examplePath + "/config");
        };
        stringstream out;
        EXPECT_NO_THROW(
            { AgoraAirgap::download_audit(out, ballotPath, getConfig); });
        EXPECT_EQ(out.str().find("Error"), string::npos)
            << "Error found in output: " << out.str() << std::endl;

        EXPECT_THAT(out.str(), HasSubstr("\n> Audit PASSED\n"))
            << std::endl
            << "Error found in output: " << out.str() << std::endl;
    }
}

/**
 * Executes download_audit with invalid data (/config-bad will yield nothing)
 */
// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST_F(ExampleDirsTest, MockBadDownloadAudit)
{
    for (string & examplePath: exampleDirs)
    {
        string ballotPath = examplePath + "/ballot.json";
        auto getConfig = [&examplePath](stringstream & out, const string &) {
            return AgoraAirgap::read_file(out, examplePath + "/config-bad");
        };
        stringstream out;
        EXPECT_THAT(
            [&]() { AgoraAirgap::download_audit(out, ballotPath, getConfig); },
            ThrowsMessage<std::runtime_error>(
                HasSubstr("!!! Error [read-file]")))
            << std::endl
            << "Error found in output: " << out.str() << std::endl;
    }
}

/**
 * Executes download only and compares downloaded file with original
 */
// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST_F(ExampleDirsTest, MockDownload)
{
    for (string & examplePath: exampleDirs)
    {
        string ballotPath = examplePath + "/ballot.json";
        auto getConfig = [&examplePath](stringstream & out, const string &) {
            return AgoraAirgap::read_file(out, examplePath + "/config");
        };
        stringstream out;
        string election_path = std::tmpnam(nullptr);
        AgoraAirgap::download(out, ballotPath, election_path, getConfig);

        EXPECT_THAT(out.str(), Not(HasSubstr("!!! Error")))
            << std::endl
            << "Error found in output: " << out.str() << std::endl;

        stringstream out2;
        string read_election_str = AgoraAirgap::read_file(out, election_path);
        string orig_election_str =
            AgoraAirgap::read_file(out, examplePath + "/config");

        EXPECT_THAT(out2.str(), Not(HasSubstr("!!! Error")))
            << std::endl
            << "Error found in output: " << out2.str() << std::endl;

        EXPECT_EQ(read_election_str, orig_election_str)
            << "Read election config does not match original" << std::endl;
    }
}

/**
 * Executes audit only
 */
// Supress warnings related to using the google test macro
// NOLINTNEXTLINE(misc-unused-parameters, readability-named-parameter)
TEST_F(ExampleDirsTest, MockAudit)
{
    for (string & examplePath: exampleDirs)
    {
        string ballotPath = examplePath + "/ballot.json";
        stringstream out;
        string election_path = examplePath + "/config";
        EXPECT_NO_THROW(
            { AgoraAirgap::audit(out, ballotPath, election_path); });
        EXPECT_EQ(out.str().find("Error"), string::npos)
            << "Error found in output: " << out.str() << std::endl;
        AgoraAirgap::audit(out, ballotPath, election_path);

        EXPECT_THAT(out.str(), HasSubstr("\n> Audit PASSED\n"))
            << std::endl
            << "Error found in output: " << out.str() << std::endl;

    }
}<|endoftext|>


<commit_before>#include <glog/logging.h>

#include <cstring>
#include <map>
#include <string>
#include <vector>

#include "boost/algorithm/string.hpp"
#include "caffe/caffe.hpp"

using caffe::Blob;
using caffe::Caffe;
using caffe::Net;
using caffe::Layer;
using caffe::shared_ptr;
using caffe::Timer;
using caffe::vector;

DEFINE_int32(gpu, -1,
    "Run in GPU mode on given device ID.");
DEFINE_string(solver, "",
    "The solver definition protocol buffer text file.");
DEFINE_string(model, "",
    "The model definition protocol buffer text file..");
DEFINE_string(snapshot, "",
    "Optional; the snapshot solver state to resume training.");
DEFINE_string(weights, "",
    "Optional; the pretrained weights to initialize finetuning. "
    "Cannot be set simultaneously with snapshot.");
DEFINE_int32(iterations, 50,
    "The number of iterations to run.");

// A simple registry for caffe commands.
typedef int (*BrewFunction)();
typedef std::map<caffe::string, BrewFunction> BrewMap;
BrewMap g_brew_map;

#define RegisterBrewFunction(func) \
namespace { \
class __Registerer_##func { \
 public: /* NOLINT */ \
  __Registerer_##func() { \
    g_brew_map[#func] = &func; \
  } \
}; \
__Registerer_##func g_registerer_##func; \
}

static BrewFunction GetBrewFunction(const caffe::string& name) {
  if (g_brew_map.count(name)) {
    return g_brew_map[name];
  } else {
    LOG(ERROR) << "Available caffe actions:";
    for (BrewMap::iterator it = g_brew_map.begin();
         it != g_brew_map.end(); ++it) {
      LOG(ERROR) << "\t" << it->first;
    }
    LOG(FATAL) << "Unknown action: " << name;
    return NULL;  // not reachable, just to suppress old compiler warnings.
  }
}

// caffe commands to call by
//     caffe <command> <args>
//
// To add a command, define a function "int command()" and register it with
// RegisterBrewFunction(action);

// Device Query: show diagnostic information for a GPU device.
int device_query() {
  CHECK_GT(FLAGS_gpu, -1) << "Need a device ID to query.";
  LOG(INFO) << "Querying device ID = " << FLAGS_gpu;
  caffe::Caffe::SetDevice(FLAGS_gpu);
  caffe::Caffe::DeviceQuery();
  return 0;
}
RegisterBrewFunction(device_query);

// Load the weights from the specified caffemodel(s) into the train and
// test nets.
void CopyLayers(caffe::Solver<float>* solver, const std::string& model_list) {
  std::vector<std::string> model_names;
  boost::split(model_names, model_list, boost::is_any_of(",") );
  for (int i = 0; i < model_names.size(); ++i) {
    LOG(INFO) << "Finetuning from " << model_names[i];
    solver->net()->CopyTrainedLayersFrom(model_names[i]);
    for (int j = 0; j < solver->test_nets().size(); ++j) {
      solver->test_nets()[j]->CopyTrainedLayersFrom(model_names[i]);
    }
  }
}

// Train / Finetune a model.
int train() {
  CHECK_GT(FLAGS_solver.size(), 0) << "Need a solver definition to train.";
  CHECK(!FLAGS_snapshot.size() || !FLAGS_weights.size())
      << "Give a snapshot to resume training or weights to finetune "
      "but not both.";

  caffe::SolverParameter solver_param;
  caffe::ReadProtoFromTextFileOrDie(FLAGS_solver, &solver_param);

  // If the gpu flag is not provided, allow the mode and device to be set
  // in the solver prototxt.
  if (FLAGS_gpu < 0
      && solver_param.solver_mode() == caffe::SolverParameter_SolverMode_GPU) {
    FLAGS_gpu = solver_param.device_id();
  }

  // Set device id and mode
  if (FLAGS_gpu >= 0) {
    LOG(INFO) << "Use GPU with device ID " << FLAGS_gpu;
    Caffe::SetDevice(FLAGS_gpu);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }

  LOG(INFO) << "Starting Optimization";
  shared_ptr<caffe::Solver<float> >
    solver(caffe::GetSolver<float>(solver_param));

  if (FLAGS_snapshot.size()) {
    LOG(INFO) << "Resuming from " << FLAGS_snapshot;
    solver->Solve(FLAGS_snapshot);
  } else if (FLAGS_weights.size()) {
    CopyLayers(&*solver, FLAGS_weights);
    solver->Solve();
  } else {
    solver->Solve();
  }
  LOG(INFO) << "Optimization Done.";
  return 0;
}
RegisterBrewFunction(train);

// Test: score a model.
int test() {
  CHECK_GT(FLAGS_model.size(), 0) << "Need a model definition to score.";
  CHECK_GT(FLAGS_weights.size(), 0) << "Need model weights to score.";

  // Set device id and mode
  if (FLAGS_gpu >= 0) {
    LOG(INFO) << "Use GPU with device ID " << FLAGS_gpu;
    Caffe::SetDevice(FLAGS_gpu);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }
  // Instantiate the caffe net.
  Net<float> caffe_net(FLAGS_model, caffe::TEST);
  caffe_net.CopyTrainedLayersFrom(FLAGS_weights);
  LOG(INFO) << "Running for " << FLAGS_iterations << " iterations.";

  vector<Blob<float>* > bottom_vec;
  vector<int> test_score_output_id;
  vector<float> test_score;
  float loss = 0;
  for (int i = 0; i < FLAGS_iterations; ++i) {
    float iter_loss;
    const vector<Blob<float>*>& result =
        caffe_net.Forward(bottom_vec, &iter_loss);
    loss += iter_loss;
    int idx = 0;
    for (int j = 0; j < result.size(); ++j) {
      const float* result_vec = result[j]->cpu_data();
      for (int k = 0; k < result[j]->count(); ++k, ++idx) {
        const float score = result_vec[k];
        if (i == 0) {
          test_score.push_back(score);
          test_score_output_id.push_back(j);
        } else {
          test_score[idx] += score;
        }
        const std::string& output_name = caffe_net.blob_names()[
            caffe_net.output_blob_indices()[j]];
        LOG(INFO) << "Batch " << i << ", " << output_name << " = " << score;
      }
    }
  }
  loss /= FLAGS_iterations;
  LOG(INFO) << "Loss: " << loss;
  for (int i = 0; i < test_score.size(); ++i) {
    const std::string& output_name = caffe_net.blob_names()[
        caffe_net.output_blob_indices()[test_score_output_id[i]]];
    const float loss_weight =
        caffe_net.blob_loss_weights()[caffe_net.output_blob_indices()[i]];
    std::ostringstream loss_msg_stream;
    const float mean_score = test_score[i] / FLAGS_iterations;
    if (loss_weight) {
      loss_msg_stream << " (* " << loss_weight
                      << " = " << loss_weight * mean_score << " loss)";
    }
    LOG(INFO) << output_name << " = " << mean_score << loss_msg_stream.str();
  }

  return 0;
}
RegisterBrewFunction(test);

// Time: benchmark the execution time of a model.
int time() {
  CHECK_GT(FLAGS_model.size(), 0) << "Need a model definition to time.";

  // Set device id and mode
  if (FLAGS_gpu >= 0) {
    LOG(INFO) << "Use GPU with device ID " << FLAGS_gpu;
    Caffe::SetDevice(FLAGS_gpu);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }
  // Instantiate the caffe net.
  Net<float> caffe_net(FLAGS_model, caffe::TRAIN);

  // Do a clean forward and backward pass, so that memory allocation are done
  // and future iterations will be more stable.
  LOG(INFO) << "Performing Forward";
  // Note that for the speed benchmark, we will assume that the network does
  // not take any input blobs.
  float initial_loss;
  caffe_net.Forward(vector<Blob<float>*>(), &initial_loss);
  LOG(INFO) << "Initial loss: " << initial_loss;
  LOG(INFO) << "Performing Backward";
  caffe_net.Backward();

  const vector<shared_ptr<Layer<float> > >& layers = caffe_net.layers();
  const vector<vector<Blob<float>*> >& bottom_vecs = caffe_net.bottom_vecs();
  const vector<vector<Blob<float>*> >& top_vecs = caffe_net.top_vecs();
  const vector<vector<bool> >& bottom_need_backward =
      caffe_net.bottom_need_backward();
  LOG(INFO) << "*** Benchmark begins ***";
  LOG(INFO) << "Testing for " << FLAGS_iterations << " iterations.";
  Timer total_timer;
  total_timer.Start();
  Timer forward_timer;
  Timer backward_timer;
  Timer timer;
  std::vector<double> forward_time_per_layer(layers.size(), 0.0);
  std::vector<double> backward_time_per_layer(layers.size(), 0.0);
  double forward_time = 0.0;
  double backward_time = 0.0;
  for (int j = 0; j < FLAGS_iterations; ++j) {
    Timer iter_timer;
    iter_timer.Start();
    forward_timer.Start();
    for (int i = 0; i < layers.size(); ++i) {
      timer.Start();
      layers[i]->Forward(bottom_vecs[i], top_vecs[i]);
      forward_time_per_layer[i] += timer.MicroSeconds();
    }
    forward_time += forward_timer.MicroSeconds();
    backward_timer.Start();
    for (int i = layers.size() - 1; i >= 0; --i) {
      timer.Start();
      layers[i]->Backward(top_vecs[i], bottom_need_backward[i],
                          bottom_vecs[i]);
      backward_time_per_layer[i] += timer.MicroSeconds();
    }
    backward_time += backward_timer.MicroSeconds();
    LOG(INFO) << "Iteration: " << j + 1 << " forward-backward time: "
      << iter_timer.MilliSeconds() << " ms.";
  }
  LOG(INFO) << "Average time per layer: ";
  for (int i = 0; i < layers.size(); ++i) {
    const caffe::string& layername = layers[i]->layer_param().name();
    LOG(INFO) << std::setfill(' ') << std::setw(10) << layername <<
      "\tforward: " << forward_time_per_layer[i] / 1000 /
      FLAGS_iterations << " ms.";
    LOG(INFO) << std::setfill(' ') << std::setw(10) << layername  <<
      "\tbackward: " << backward_time_per_layer[i] / 1000 /
      FLAGS_iterations << " ms.";
  }
  total_timer.Stop();
  LOG(INFO) << "Average Forward pass: " << forward_time / 1000 /
    FLAGS_iterations << " ms.";
  LOG(INFO) << "Average Backward pass: " << backward_time / 1000 /
    FLAGS_iterations << " ms.";
  LOG(INFO) << "Average Forward-Backward: " << total_timer.MilliSeconds() /
    FLAGS_iterations << " ms.";
  LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() << " ms.";
  LOG(INFO) << "*** Benchmark ends ***";
  return 0;
}
RegisterBrewFunction(time);

int main(int argc, char** argv) {
  // Print output to stderr (while still logging).
  FLAGS_alsologtostderr = 1;
  // Usage message.
  gflags::SetUsageMessage("command line brew\n"
      "usage: caffe <command> <args>\n\n"
      "commands:\n"
      "  train           train or finetune a model\n"
      "  test            score a model\n"
      "  device_query    show GPU diagnostic information\n"
      "  time            benchmark model execution time");
  // Run tool or show usage.
  caffe::GlobalInit(&argc, &argv);
  if (argc == 2) {
    return GetBrewFunction(caffe::string(argv[1]))();
  } else {
    gflags::ShowUsageWithFlagsRestrict(argv[0], "tools/caffe");
  }
}
<commit_msg>print Python exceptions when using Python layer with the caffe tool<commit_after>#include <glog/logging.h>

#include <cstring>
#include <map>
#include <string>
#include <vector>

#include "boost/algorithm/string.hpp"
#include "caffe/caffe.hpp"

#ifdef WITH_PYTHON_LAYER
#include "boost/python.hpp"
namespace bp = boost::python;
#endif

using caffe::Blob;
using caffe::Caffe;
using caffe::Net;
using caffe::Layer;
using caffe::shared_ptr;
using caffe::Timer;
using caffe::vector;

DEFINE_int32(gpu, -1,
    "Run in GPU mode on given device ID.");
DEFINE_string(solver, "",
    "The solver definition protocol buffer text file.");
DEFINE_string(model, "",
    "The model definition protocol buffer text file..");
DEFINE_string(snapshot, "",
    "Optional; the snapshot solver state to resume training.");
DEFINE_string(weights, "",
    "Optional; the pretrained weights to initialize finetuning. "
    "Cannot be set simultaneously with snapshot.");
DEFINE_int32(iterations, 50,
    "The number of iterations to run.");

// A simple registry for caffe commands.
typedef int (*BrewFunction)();
typedef std::map<caffe::string, BrewFunction> BrewMap;
BrewMap g_brew_map;

#define RegisterBrewFunction(func) \
namespace { \
class __Registerer_##func { \
 public: /* NOLINT */ \
  __Registerer_##func() { \
    g_brew_map[#func] = &func; \
  } \
}; \
__Registerer_##func g_registerer_##func; \
}

static BrewFunction GetBrewFunction(const caffe::string& name) {
  if (g_brew_map.count(name)) {
    return g_brew_map[name];
  } else {
    LOG(ERROR) << "Available caffe actions:";
    for (BrewMap::iterator it = g_brew_map.begin();
         it != g_brew_map.end(); ++it) {
      LOG(ERROR) << "\t" << it->first;
    }
    LOG(FATAL) << "Unknown action: " << name;
    return NULL;  // not reachable, just to suppress old compiler warnings.
  }
}

// caffe commands to call by
//     caffe <command> <args>
//
// To add a command, define a function "int command()" and register it with
// RegisterBrewFunction(action);

// Device Query: show diagnostic information for a GPU device.
int device_query() {
  CHECK_GT(FLAGS_gpu, -1) << "Need a device ID to query.";
  LOG(INFO) << "Querying device ID = " << FLAGS_gpu;
  caffe::Caffe::SetDevice(FLAGS_gpu);
  caffe::Caffe::DeviceQuery();
  return 0;
}
RegisterBrewFunction(device_query);

// Load the weights from the specified caffemodel(s) into the train and
// test nets.
void CopyLayers(caffe::Solver<float>* solver, const std::string& model_list) {
  std::vector<std::string> model_names;
  boost::split(model_names, model_list, boost::is_any_of(",") );
  for (int i = 0; i < model_names.size(); ++i) {
    LOG(INFO) << "Finetuning from " << model_names[i];
    solver->net()->CopyTrainedLayersFrom(model_names[i]);
    for (int j = 0; j < solver->test_nets().size(); ++j) {
      solver->test_nets()[j]->CopyTrainedLayersFrom(model_names[i]);
    }
  }
}

// Train / Finetune a model.
int train() {
  CHECK_GT(FLAGS_solver.size(), 0) << "Need a solver definition to train.";
  CHECK(!FLAGS_snapshot.size() || !FLAGS_weights.size())
      << "Give a snapshot to resume training or weights to finetune "
      "but not both.";

  caffe::SolverParameter solver_param;
  caffe::ReadProtoFromTextFileOrDie(FLAGS_solver, &solver_param);

  // If the gpu flag is not provided, allow the mode and device to be set
  // in the solver prototxt.
  if (FLAGS_gpu < 0
      && solver_param.solver_mode() == caffe::SolverParameter_SolverMode_GPU) {
    FLAGS_gpu = solver_param.device_id();
  }

  // Set device id and mode
  if (FLAGS_gpu >= 0) {
    LOG(INFO) << "Use GPU with device ID " << FLAGS_gpu;
    Caffe::SetDevice(FLAGS_gpu);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }

  LOG(INFO) << "Starting Optimization";
  shared_ptr<caffe::Solver<float> >
    solver(caffe::GetSolver<float>(solver_param));

  if (FLAGS_snapshot.size()) {
    LOG(INFO) << "Resuming from " << FLAGS_snapshot;
    solver->Solve(FLAGS_snapshot);
  } else if (FLAGS_weights.size()) {
    CopyLayers(&*solver, FLAGS_weights);
    solver->Solve();
  } else {
    solver->Solve();
  }
  LOG(INFO) << "Optimization Done.";
  return 0;
}
RegisterBrewFunction(train);

// Test: score a model.
int test() {
  CHECK_GT(FLAGS_model.size(), 0) << "Need a model definition to score.";
  CHECK_GT(FLAGS_weights.size(), 0) << "Need model weights to score.";

  // Set device id and mode
  if (FLAGS_gpu >= 0) {
    LOG(INFO) << "Use GPU with device ID " << FLAGS_gpu;
    Caffe::SetDevice(FLAGS_gpu);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }
  // Instantiate the caffe net.
  Net<float> caffe_net(FLAGS_model, caffe::TEST);
  caffe_net.CopyTrainedLayersFrom(FLAGS_weights);
  LOG(INFO) << "Running for " << FLAGS_iterations << " iterations.";

  vector<Blob<float>* > bottom_vec;
  vector<int> test_score_output_id;
  vector<float> test_score;
  float loss = 0;
  for (int i = 0; i < FLAGS_iterations; ++i) {
    float iter_loss;
    const vector<Blob<float>*>& result =
        caffe_net.Forward(bottom_vec, &iter_loss);
    loss += iter_loss;
    int idx = 0;
    for (int j = 0; j < result.size(); ++j) {
      const float* result_vec = result[j]->cpu_data();
      for (int k = 0; k < result[j]->count(); ++k, ++idx) {
        const float score = result_vec[k];
        if (i == 0) {
          test_score.push_back(score);
          test_score_output_id.push_back(j);
        } else {
          test_score[idx] += score;
        }
        const std::string& output_name = caffe_net.blob_names()[
            caffe_net.output_blob_indices()[j]];
        LOG(INFO) << "Batch " << i << ", " << output_name << " = " << score;
      }
    }
  }
  loss /= FLAGS_iterations;
  LOG(INFO) << "Loss: " << loss;
  for (int i = 0; i < test_score.size(); ++i) {
    const std::string& output_name = caffe_net.blob_names()[
        caffe_net.output_blob_indices()[test_score_output_id[i]]];
    const float loss_weight =
        caffe_net.blob_loss_weights()[caffe_net.output_blob_indices()[i]];
    std::ostringstream loss_msg_stream;
    const float mean_score = test_score[i] / FLAGS_iterations;
    if (loss_weight) {
      loss_msg_stream << " (* " << loss_weight
                      << " = " << loss_weight * mean_score << " loss)";
    }
    LOG(INFO) << output_name << " = " << mean_score << loss_msg_stream.str();
  }

  return 0;
}
RegisterBrewFunction(test);

// Time: benchmark the execution time of a model.
int time() {
  CHECK_GT(FLAGS_model.size(), 0) << "Need a model definition to time.";

  // Set device id and mode
  if (FLAGS_gpu >= 0) {
    LOG(INFO) << "Use GPU with device ID " << FLAGS_gpu;
    Caffe::SetDevice(FLAGS_gpu);
    Caffe::set_mode(Caffe::GPU);
  } else {
    LOG(INFO) << "Use CPU.";
    Caffe::set_mode(Caffe::CPU);
  }
  // Instantiate the caffe net.
  Net<float> caffe_net(FLAGS_model, caffe::TRAIN);

  // Do a clean forward and backward pass, so that memory allocation are done
  // and future iterations will be more stable.
  LOG(INFO) << "Performing Forward";
  // Note that for the speed benchmark, we will assume that the network does
  // not take any input blobs.
  float initial_loss;
  caffe_net.Forward(vector<Blob<float>*>(), &initial_loss);
  LOG(INFO) << "Initial loss: " << initial_loss;
  LOG(INFO) << "Performing Backward";
  caffe_net.Backward();

  const vector<shared_ptr<Layer<float> > >& layers = caffe_net.layers();
  const vector<vector<Blob<float>*> >& bottom_vecs = caffe_net.bottom_vecs();
  const vector<vector<Blob<float>*> >& top_vecs = caffe_net.top_vecs();
  const vector<vector<bool> >& bottom_need_backward =
      caffe_net.bottom_need_backward();
  LOG(INFO) << "*** Benchmark begins ***";
  LOG(INFO) << "Testing for " << FLAGS_iterations << " iterations.";
  Timer total_timer;
  total_timer.Start();
  Timer forward_timer;
  Timer backward_timer;
  Timer timer;
  std::vector<double> forward_time_per_layer(layers.size(), 0.0);
  std::vector<double> backward_time_per_layer(layers.size(), 0.0);
  double forward_time = 0.0;
  double backward_time = 0.0;
  for (int j = 0; j < FLAGS_iterations; ++j) {
    Timer iter_timer;
    iter_timer.Start();
    forward_timer.Start();
    for (int i = 0; i < layers.size(); ++i) {
      timer.Start();
      layers[i]->Forward(bottom_vecs[i], top_vecs[i]);
      forward_time_per_layer[i] += timer.MicroSeconds();
    }
    forward_time += forward_timer.MicroSeconds();
    backward_timer.Start();
    for (int i = layers.size() - 1; i >= 0; --i) {
      timer.Start();
      layers[i]->Backward(top_vecs[i], bottom_need_backward[i],
                          bottom_vecs[i]);
      backward_time_per_layer[i] += timer.MicroSeconds();
    }
    backward_time += backward_timer.MicroSeconds();
    LOG(INFO) << "Iteration: " << j + 1 << " forward-backward time: "
      << iter_timer.MilliSeconds() << " ms.";
  }
  LOG(INFO) << "Average time per layer: ";
  for (int i = 0; i < layers.size(); ++i) {
    const caffe::string& layername = layers[i]->layer_param().name();
    LOG(INFO) << std::setfill(' ') << std::setw(10) << layername <<
      "\tforward: " << forward_time_per_layer[i] / 1000 /
      FLAGS_iterations << " ms.";
    LOG(INFO) << std::setfill(' ') << std::setw(10) << layername  <<
      "\tbackward: " << backward_time_per_layer[i] / 1000 /
      FLAGS_iterations << " ms.";
  }
  total_timer.Stop();
  LOG(INFO) << "Average Forward pass: " << forward_time / 1000 /
    FLAGS_iterations << " ms.";
  LOG(INFO) << "Average Backward pass: " << backward_time / 1000 /
    FLAGS_iterations << " ms.";
  LOG(INFO) << "Average Forward-Backward: " << total_timer.MilliSeconds() /
    FLAGS_iterations << " ms.";
  LOG(INFO) << "Total Time: " << total_timer.MilliSeconds() << " ms.";
  LOG(INFO) << "*** Benchmark ends ***";
  return 0;
}
RegisterBrewFunction(time);

int main(int argc, char** argv) {
  // Print output to stderr (while still logging).
  FLAGS_alsologtostderr = 1;
  // Usage message.
  gflags::SetUsageMessage("command line brew\n"
      "usage: caffe <command> <args>\n\n"
      "commands:\n"
      "  train           train or finetune a model\n"
      "  test            score a model\n"
      "  device_query    show GPU diagnostic information\n"
      "  time            benchmark model execution time");
  // Run tool or show usage.
  caffe::GlobalInit(&argc, &argv);
  if (argc == 2) {
#ifdef WITH_PYTHON_LAYER
    try {
#endif
      return GetBrewFunction(caffe::string(argv[1]))();
#ifdef WITH_PYTHON_LAYER
    } catch (bp::error_already_set) {
      PyErr_Print();
      return 1;
    }
#endif
  } else {
    gflags::ShowUsageWithFlagsRestrict(argv[0], "tools/caffe");
  }
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file transaction.cpp
 * @author Dmitrii Khokhlov <winsvega@mail.ru>
 * @date 2015
 * Transaaction test functions.
 */

#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
	for (auto& i: _v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		if (_fillin == false)
		{
			BOOST_REQUIRE(o.count("rlp") > 0);
			Transaction txFromRlp;
			try
			{
				bytes stream = importByteArray(o["rlp"].get_str());
				RLP rlp(stream);
				txFromRlp = Transaction(rlp.data(), CheckSignature::Sender);
				if (!txFromRlp.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
			}
			catch(...)
			{
				BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}

			BOOST_REQUIRE(o.count("transaction") > 0);

			mObject tObj = o["transaction"].get_obj();
			Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckSignature::Sender);

			//Check the fields restored from RLP to original fields
			BOOST_CHECK_MESSAGE(txFromFields.data() == txFromRlp.data(), "Data in given RLP not matching the Transaction data!");
			BOOST_CHECK_MESSAGE(txFromFields.value() == txFromRlp.value(), "Value in given RLP not matching the Transaction value!");
			BOOST_CHECK_MESSAGE(txFromFields.gasPrice() == txFromRlp.gasPrice(), "GasPrice in given RLP not matching the Transaction gasPrice!");
			BOOST_CHECK_MESSAGE(txFromFields.gas() == txFromRlp.gas(),"Gas in given RLP not matching the Transaction gas!");
			BOOST_CHECK_MESSAGE(txFromFields.nonce() == txFromRlp.nonce(),"Nonce in given RLP not matching the Transaction nonce!");
			BOOST_CHECK_MESSAGE(txFromFields.receiveAddress() == txFromRlp.receiveAddress(), "Receive address in given RLP not matching the Transaction 'to' address!");
			BOOST_CHECK_MESSAGE(txFromFields.sender() == txFromRlp.sender(), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
			BOOST_CHECK_MESSAGE(txFromFields == txFromRlp, "However, txFromFields != txFromRlp!");
			BOOST_REQUIRE (o.count("sender") > 0);

			Address addressReaded = Address(o["sender"].get_str());
			BOOST_CHECK_MESSAGE(txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded, "Signature address of sender does not match given sender address!");
		}
		else
		{
			BOOST_REQUIRE(o.count("transaction") > 0);
			mObject tObj = o["transaction"].get_obj();

			//Construct Rlp of the given transaction
			RLPStream rlpStream = createRLPStreamFromTransactionFields(tObj);
			o["rlp"] = "0x" + toHex(rlpStream.out());

			try
			{
				Transaction txFromFields(rlpStream.out(), CheckSignature::Sender);
				if (!txFromFields.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );

				o["sender"] = toString(txFromFields.sender());
			}
			catch(Exception const& _e)
			{
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				o.erase(o.find("transaction"));
			}
		}
	}//for
}//doTransactionTests

} }// Namespace Close

BOOST_AUTO_TEST_SUITE(TransactionTests)

BOOST_AUTO_TEST_CASE(ttTransactionTest)
{
	dev::test::executeTests("ttTransactionTest", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(ttWrongRLPTransaction)
{
	dev::test::executeTests("ttWrongRLPTransaction", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(tt10mbDataField)
{
	if (test::Options::get().bigData)
	{
		auto start = chrono::steady_clock::now();

		dev::test::executeTests("tt10mbDataField", "/TransactionTests", dev::test::doTransactionTests);

		auto end = chrono::steady_clock::now();
		auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
		cnote << "test duration: " << duration.count() << " milliseconds.\n";
	}
}

BOOST_AUTO_TEST_CASE(ttCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doTransactionTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFile)
{
	dev::test::userDefinedTest("--singletest", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Exceptions<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file transaction.cpp
 * @author Dmitrii Khokhlov <winsvega@mail.ru>
 * @date 2015
 * Transaaction test functions.
 */

#include "TestHelper.h"

using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;

namespace dev {  namespace test {

void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
	for (auto& i: _v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		if (_fillin == false)
		{
			BOOST_REQUIRE(o.count("rlp") > 0);
			Transaction txFromRlp;
			try
			{
				bytes stream = importByteArray(o["rlp"].get_str());
				RLP rlp(stream);
				txFromRlp = Transaction(rlp.data(), CheckSignature::Sender);
				if (!txFromRlp.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
			}
			catch(Exception const& _e)
			{
				cnote << i.first;
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}
			catch(...)
			{
				BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}

			BOOST_REQUIRE(o.count("transaction") > 0);

			mObject tObj = o["transaction"].get_obj();
			Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckSignature::Sender);

			//Check the fields restored from RLP to original fields
			BOOST_CHECK_MESSAGE(txFromFields.data() == txFromRlp.data(), "Data in given RLP not matching the Transaction data!");
			BOOST_CHECK_MESSAGE(txFromFields.value() == txFromRlp.value(), "Value in given RLP not matching the Transaction value!");
			BOOST_CHECK_MESSAGE(txFromFields.gasPrice() == txFromRlp.gasPrice(), "GasPrice in given RLP not matching the Transaction gasPrice!");
			BOOST_CHECK_MESSAGE(txFromFields.gas() == txFromRlp.gas(),"Gas in given RLP not matching the Transaction gas!");
			BOOST_CHECK_MESSAGE(txFromFields.nonce() == txFromRlp.nonce(),"Nonce in given RLP not matching the Transaction nonce!");
			BOOST_CHECK_MESSAGE(txFromFields.receiveAddress() == txFromRlp.receiveAddress(), "Receive address in given RLP not matching the Transaction 'to' address!");
			BOOST_CHECK_MESSAGE(txFromFields.sender() == txFromRlp.sender(), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
			BOOST_CHECK_MESSAGE(txFromFields == txFromRlp, "However, txFromFields != txFromRlp!");
			BOOST_REQUIRE (o.count("sender") > 0);

			Address addressReaded = Address(o["sender"].get_str());
			BOOST_CHECK_MESSAGE(txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded, "Signature address of sender does not match given sender address!");
		}
		else
		{
			BOOST_REQUIRE(o.count("transaction") > 0);
			mObject tObj = o["transaction"].get_obj();

			//Construct Rlp of the given transaction
			RLPStream rlpStream = createRLPStreamFromTransactionFields(tObj);
			o["rlp"] = "0x" + toHex(rlpStream.out());

			try
			{
				Transaction txFromFields(rlpStream.out(), CheckSignature::Sender);
				if (!txFromFields.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );

				o["sender"] = toString(txFromFields.sender());
			}
			catch(Exception const& _e)
			{
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				o.erase(o.find("transaction"));
			}
		}
	}//for
}//doTransactionTests

} }// Namespace Close

BOOST_AUTO_TEST_SUITE(TransactionTests)

BOOST_AUTO_TEST_CASE(ttTransactionTest)
{
	dev::test::executeTests("ttTransactionTest", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(ttWrongRLPTransaction)
{
	dev::test::executeTests("ttWrongRLPTransaction", "/TransactionTests", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_CASE(tt10mbDataField)
{
	if (test::Options::get().bigData)
	{
		auto start = chrono::steady_clock::now();

		dev::test::executeTests("tt10mbDataField", "/TransactionTests", dev::test::doTransactionTests);

		auto end = chrono::steady_clock::now();
		auto duration(chrono::duration_cast<chrono::milliseconds>(end - start));
		cnote << "test duration: " << duration.count() << " milliseconds.\n";
	}
}

BOOST_AUTO_TEST_CASE(ttCreateTest)
{
	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
	{
		string arg = boost::unit_test::framework::master_test_suite().argv[i];
		if (arg == "--createtest")
		{
			if (boost::unit_test::framework::master_test_suite().argc <= i + 2)
			{
				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n";
				return;
			}
			try
			{
				cnote << "Populating tests...";
				json_spirit::mValue v;
				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1]));
				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty.");
				json_spirit::read_string(s, v);
				dev::test::doTransactionTests(v, true);
				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true)));
			}
			catch (Exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed transaction test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFile)
{
	dev::test::userDefinedTest("--singletest", dev::test::doTransactionTests);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>