<commit_before>// Copyright (c) 2016-2017 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "test/test_syscoin_services.h"
#include "utiltime.h"
#include "util.h"
#include "rpc/server.h"
#include "alias.h"
#include "cert.h"
#include "asset.h"
#include "base58.h"
#include "chainparams.h"
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <iterator>
#include <chrono>
#include "ranges.h"
using namespace boost::chrono;
using namespace std;
BOOST_GLOBAL_FIXTURE( SyscoinTestingSetup );

BOOST_FIXTURE_TEST_SUITE(syscoin_asset_allocation_tests, BasicSyscoinTestingSetup)
BOOST_AUTO_TEST_CASE(generate_asset_allocation_send)
{
	UniValue r;
	printf("Running generate_asset_allocation_send...\n");
	GenerateBlocks(5);
	AliasNew("node1", "jagassetallocationsend1", "data");
	AliasNew("node2", "jagassetallocationsend2", "data");
	string guid = AssetNew("node1", "usd", "jagassetallocationsend1", "data", "8", "false", "1", "-1");

	AssetSend("node1", guid, "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend1\\\",\\\"amount\\\":1}]\"", "assetallocationsend");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend1 false"));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false), 1 * COIN);

	string txid0 = AssetAllocationTransfer(false, "node1", guid, "jagassetallocationsend1", "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend2\\\",\\\"amount\\\":0.11}]\"", "allocationsendmemo");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend2 false"));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false),0.11 * COIN);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// send using zdag
	string txid1 = AssetAllocationTransfer(true, "node1", guid, "jagassetallocationsend1", "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend2\\\",\\\"amount\\\":0.12}]\"", "allocationsendmemo");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend2 false"));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false), 0.23 * COIN);

	// non zdag cannot be found since it was already mined, but ends up briefly in conflict state because sender is conflicted
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// first tx should have to wait 1 sec for good status
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid +  " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// wait for 1 second as required by unit test
	MilliSleep(1000);

	// second send
	string txid2 = AssetAllocationTransfer(true, "node1", guid, "jagassetallocationsend1", "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend2\\\",\\\"amount\\\":0.13}]\"", "allocationsendmemo");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend2 false"));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false), 0.36 * COIN);

	// sender is conflicted so txid0 is conflicted by extension even if its not found
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// first ones now OK because it was found explicitely
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// second one hasn't waited enough time yet
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// wait for 1.5 second to clear minor warning status
	MilliSleep(1500);
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// after pow, should get not found on all of them
	GenerateBlocks(1);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

}
BOOST_AUTO_TEST_CASE(generate_assetallocationpruning)
{
	UniValue r;
	// makes sure services expire in 100 blocks instead of 1 year of blocks for testing purposes
	printf("Running generate_assetallocationpruning...\n");
	AliasNew("node1", "jagprunealias2", "changeddata1");
	MilliSleep(5000);
	AliasNew("node2", "jagprunealias2node2", "data");
	// stop node2 create a service,  mine some blocks to expire the service, when we restart the node the service data won't be synced with node2
	StopNode("node2");
	string guid = AssetNew("node1", "bcf", "jagprunealias2", "pubdata");
	AssetSend("node1", guid, "\"[{\\\"aliasto\\\":\\\"jagprunealias2\\\",\\\"amount\\\":1}]\"", "assetallocationsend");
	AssetAllocationTransfer(false, "node1", guid, "jagprunealias2", "\"[{\\\"aliasto\\\":\\\"jagprunealias2node2\\\",\\\"amount\\\":0.11}]\"", "allocationsendmemo");
	// we can find it as normal first
	BOOST_CHECK_NO_THROW(CallRPC("node1", "assetinfo " + guid + " false"));
	// make sure our alias doesn't expire
	string hex_str = AliasUpdate("node1", "jagprunealias2");
	BOOST_CHECK(hex_str.empty());
	GenerateBlocks(5, "node1");
	ExpireAlias("jagprunealias2");
	StartNode("node2");
	GenerateBlocks(5, "node2");

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetinfo " + guid + " false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);

	// asset allocation is not expired but cannot claim interest because asset is expired
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagprunealias2node2 false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), false);

	BOOST_CHECK_THROW(r = CallRPC("node2", "assetallocationcollectinterest " + guid + " jagprunealias2node2 ''"), runtime_error);

	// should be pruned
	BOOST_CHECK_THROW(CallRPC("node2", "assetinfo " + guid + " false"), runtime_error);

	// expire asset allocation alias and now asset allocation is also expired
	ExpireAlias("jagprunealias2node2");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagprunealias2node2 false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);

	// stop node3
	StopNode("node3");
	// should fail: already expired alias
	BOOST_CHECK_THROW(CallRPC("node1", "assetupdate " + guid + " jagprunealias2 assets 0 0 ''"), runtime_error);
	GenerateBlocks(5, "node1");

	// stop and start node1
	StopNode("node1");
	StartNode("node1");
	GenerateBlocks(5, "node1");

	BOOST_CHECK_THROW(CallRPC("node1", "assetinfo " + guid + " false"), runtime_error);

	// create a new service
	AliasNew("node1", "jagprunealias2", "temp");
	AliasNew("node2", "jagprunealias2node2", "temp");
	string guid1 = AssetNew("node1", "bcf", "jagprunealias2", "pubdata");
	// ensure you can still update before expiry
	AssetUpdate("node1", guid1);
	AssetSend("node1", guid, "\"[{\\\"aliasto\\\":\\\"jagprunealias2\\\",\\\"amount\\\":1}]\"", "assetallocationsend");
	AssetAllocationTransfer(false, "node1", guid1, "jagprunealias2", "\"[{\\\"aliasto\\\":\\\"jagprunealias2node2\\\",\\\"amount\\\":0.11}]\"", "allocationsendmemo");
	// you can search it still on node1/node2
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	// make sure our alias doesn't expire
	hex_str = AliasUpdate("node1", "jagprunealias2");
	BOOST_CHECK(hex_str.empty());
	GenerateBlocks(5, "node1");
	ExpireAlias("jagprunealias2node2");
	// now it should be expired
	BOOST_CHECK_THROW(CallRPC("node1", "assetupdate " + guid1 + " jagprunealias2 assets 0 0 ''"), runtime_error);
	BOOST_CHECK_THROW(CallRPC("node2", "assetallocationcollectinterest " + guid + " jagprunealias2node2 ''"), runtime_error);
	GenerateBlocks(5, "node1");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);
	// and it should say its expired
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);
	GenerateBlocks(5, "node1");
	StartNode("node3");
	GenerateBlocks(5, "node3");
	// node3 shouldn't find the service at all (meaning node3 doesn't sync the data)
	BOOST_CHECK_THROW(CallRPC("node3", "assetinfo " + guid1 + " false"), runtime_error);
	BOOST_CHECK_THROW(CallRPC("node3", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"), runtime_error);
}
BOOST_AUTO_TEST_SUITE_END ()
<commit_msg>fix allocation test<commit_after>// Copyright (c) 2016-2017 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "test/test_syscoin_services.h"
#include "utiltime.h"
#include "util.h"
#include "rpc/server.h"
#include "alias.h"
#include "cert.h"
#include "asset.h"
#include "base58.h"
#include "chainparams.h"
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <iterator>
#include <chrono>
#include "ranges.h"
using namespace boost::chrono;
using namespace std;
BOOST_GLOBAL_FIXTURE( SyscoinTestingSetup );

BOOST_FIXTURE_TEST_SUITE(syscoin_asset_allocation_tests, BasicSyscoinTestingSetup)
BOOST_AUTO_TEST_CASE(generate_asset_allocation_send)
{
	UniValue r;
	printf("Running generate_asset_allocation_send...\n");
	GenerateBlocks(5);
	AliasNew("node1", "jagassetallocationsend1", "data");
	AliasNew("node2", "jagassetallocationsend2", "data");
	string guid = AssetNew("node1", "usd", "jagassetallocationsend1", "data", "8", "false", "1", "-1");

	AssetSend("node1", guid, "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend1\\\",\\\"amount\\\":1}]\"", "assetallocationsend");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend1 false"));
	UniValue balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false), 1 * COIN);

	string txid0 = AssetAllocationTransfer(false, "node1", guid, "jagassetallocationsend1", "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend2\\\",\\\"amount\\\":0.11}]\"", "allocationsendmemo");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend2 false"));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false),0.11 * COIN);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// send using zdag
	string txid1 = AssetAllocationTransfer(true, "node1", guid, "jagassetallocationsend1", "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend2\\\",\\\"amount\\\":0.12}]\"", "allocationsendmemo");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend2 false"));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false), 0.23 * COIN);

	// non zdag cannot be found since it was already mined, but ends up briefly in conflict state because sender is conflicted
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// first tx should have to wait 1 sec for good status
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid +  " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// wait for 1 second as required by unit test
	MilliSleep(1000);

	// second send
	string txid2 = AssetAllocationTransfer(true, "node1", guid, "jagassetallocationsend1", "\"[{\\\"aliasto\\\":\\\"jagassetallocationsend2\\\",\\\"amount\\\":0.13}]\"", "allocationsendmemo");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagassetallocationsend2 false"));
	balance = find_value(r.get_obj(), "balance");
	BOOST_CHECK_EQUAL(AssetAmountFromValue(balance, 8, false), 0.36 * COIN);

	// sender is conflicted so txid0 is conflicted by extension even if its not found
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// first ones now OK because it was found explicitely
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// second one hasn't waited enough time yet
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// check just sender
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_MINOR_CONFLICT_OK);

	// wait for 1.5 second to clear minor warning status
	MilliSleep(1500);
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_STATUS_OK);

	// after pow, should get not found on all of them
	GenerateBlocks(1);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid0));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid1));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 " + txid2));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

	// check just sender as well
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationsenderstatus " + guid + " jagassetallocationsend1 ''"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "status").get_int(), ZDAG_NOT_FOUND);

}
BOOST_AUTO_TEST_CASE(generate_assetallocationpruning)
{
	UniValue r;
	// makes sure services expire in 100 blocks instead of 1 year of blocks for testing purposes
	printf("Running generate_assetallocationpruning...\n");
	AliasNew("node1", "jagprunealias2", "changeddata1");
	MilliSleep(5000);
	AliasNew("node2", "jagprunealias2node2", "data");
	// stop node2 create a service,  mine some blocks to expire the service, when we restart the node the service data won't be synced with node2
	StopNode("node2");
	string guid = AssetNew("node1", "bcf", "jagprunealias2", "pubdata");
	AssetSend("node1", guid, "\"[{\\\"aliasto\\\":\\\"jagprunealias2\\\",\\\"amount\\\":1}]\"", "assetallocationsend");
	AssetAllocationTransfer(false, "node1", guid, "jagprunealias2", "\"[{\\\"aliasto\\\":\\\"jagprunealias2node2\\\",\\\"amount\\\":0.11}]\"", "allocationsendmemo");
	// we can find it as normal first
	BOOST_CHECK_NO_THROW(CallRPC("node1", "assetinfo " + guid + " false"));
	// make sure our alias doesn't expire
	string hex_str = AliasUpdate("node1", "jagprunealias2");
	BOOST_CHECK(hex_str.empty());
	GenerateBlocks(5, "node1");
	ExpireAlias("jagprunealias2");
	StartNode("node2");
	GenerateBlocks(5, "node2");

	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetinfo " + guid + " false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);

	// asset allocation is not expired but cannot claim interest because asset is expired
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagprunealias2node2 false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), false);

	BOOST_CHECK_THROW(r = CallRPC("node2", "assetallocationcollectinterest " + guid + " jagprunealias2node2 ''"), runtime_error);

	// should be pruned
	BOOST_CHECK_THROW(CallRPC("node2", "assetinfo " + guid + " false"), runtime_error);

	// expire asset allocation alias and now asset allocation is also expired
	ExpireAlias("jagprunealias2node2");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid + " jagprunealias2node2 false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);

	// stop node3
	StopNode("node3");
	// should fail: already expired alias
	BOOST_CHECK_THROW(CallRPC("node1", "assetupdate " + guid + " jagprunealias2 assets 0 0 ''"), runtime_error);
	GenerateBlocks(5, "node1");

	// stop and start node1
	StopNode("node1");
	StartNode("node1");
	GenerateBlocks(5, "node1");

	BOOST_CHECK_THROW(CallRPC("node1", "assetinfo " + guid + " false"), runtime_error);

	// create a new service
	AliasNew("node1", "jagprunealias2", "temp");
	AliasNew("node2", "jagprunealias2node2", "temp");
	string guid1 = AssetNew("node1", "bcf", "jagprunealias2", "pubdata");
	// ensure you can still update before expiry
	AssetUpdate("node1", guid1);
	AssetSend("node1", guid1, "\"[{\\\"aliasto\\\":\\\"jagprunealias2\\\",\\\"amount\\\":1}]\"", "assetallocationsend");
	AssetAllocationTransfer(false, "node1", guid1, "jagprunealias2", "\"[{\\\"aliasto\\\":\\\"jagprunealias2node2\\\",\\\"amount\\\":0.11}]\"", "allocationsendmemo");
	// you can search it still on node1/node2
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	// make sure our alias doesn't expire
	hex_str = AliasUpdate("node1", "jagprunealias2");
	BOOST_CHECK(hex_str.empty());
	GenerateBlocks(5, "node1");
	ExpireAlias("jagprunealias2node2");
	// now it should be expired
	BOOST_CHECK_THROW(CallRPC("node1", "assetupdate " + guid1 + " jagprunealias2 assets 0 0 ''"), runtime_error);
	BOOST_CHECK_THROW(CallRPC("node2", "assetallocationcollectinterest " + guid1 + " jagprunealias2node2 ''"), runtime_error);
	GenerateBlocks(5, "node1");
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node1", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);
	// and it should say its expired
	BOOST_CHECK_NO_THROW(r = CallRPC("node2", "assetinfo " + guid1 + " false"));
	BOOST_CHECK_EQUAL(find_value(r.get_obj(), "expired").get_bool(), true);
	GenerateBlocks(5, "node1");
	StartNode("node3");
	GenerateBlocks(5, "node3");
	// node3 shouldn't find the service at all (meaning node3 doesn't sync the data)
	BOOST_CHECK_THROW(CallRPC("node3", "assetinfo " + guid1 + " false"), runtime_error);
	BOOST_CHECK_THROW(CallRPC("node3", "assetallocationinfo " + guid1 + " jagprunealias2node2 false"), runtime_error);
}
BOOST_AUTO_TEST_SUITE_END ()
<|endoftext|>


<commit_before>//
//   Copyright 2013 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//
#include "topology.h"

#include <sstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

PxOsdUtilSubdivTopology::PxOsdUtilSubdivTopology():
    name("noname"),
    numVertices(0),
    refinementLevel(2)  // arbitrary, start with a reasonable subdivision level
{
    std::cout << "Creating subdiv topology object\n";
}

PxOsdUtilSubdivTopology::~PxOsdUtilSubdivTopology()
{
    std::cout << "Destroying subdiv topology object\n";
}

bool
PxOsdUtilSubdivTopology::Initialize(
    int numVerticesParam,
    const int *nvertsParam, int numFaces,
    const int *indicesParam, int indicesLen,
    int levels,
    string *errorMessage)
{

    numVertices = numVerticesParam;
    refinementLevel = levels;

    nverts.resize(numFaces);
    for (int i=0; i<numFaces; ++i) {
        nverts[i] = nvertsParam[i];
    }

    indices.resize(indicesLen);
    for (int i=0; i<indicesLen; ++i) {
        indices[i] = indicesParam[i];
    }

    return IsValid(errorMessage);
}

bool
PxOsdUtilSubdivTopology::IsValid(string *errorMessage) const
{
    if (numVertices == 0) {
        if (errorMessage) {
            stringstream ss;
            ss << "Topology " << name << " has no vertices";
            *errorMessage = ss.str();
        }
        return false;
    }

    for (int i=0; i<(int)indices.size(); ++i) {
        if ((indices[i] < 0) or
            (indices[i] >= numVertices)) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad index " << indices[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }

    }

    int totalNumIndices = 0;
    for (int i=0; i< (int)nverts.size(); ++i) {
        if (nverts[i] < 1) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad nverts " << nverts[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }
        totalNumIndices += nverts[i];
    }

    if (totalNumIndices != (int)indices.size()) {
        if (errorMessage) {
            *errorMessage = "Bad indexing for face topology";
        }

        return false;
    }

    std::cout << "\n";

    return true;
}

void
PxOsdUtilSubdivTopology::Print() const
{
    std::cout << "Mesh " << name << "\n";
    std::cout << "\tnumVertices = " << numVertices << "\n";
    std::cout << "\trefinementLevel = " << refinementLevel << "\n";
    std::cout << "\tindices ( " << indices.size() << ") : ";
    for (int i=0; i<(int)indices.size(); ++i) {
        std::cout << indices[i] << ", ";
    }
    std::cout << "\n";

    std::cout << "\tnverts ( " << nverts.size() << ") : ";
    for (int i=0; i<(int)nverts.size(); ++i) {
        std::cout << nverts[i] << ", ";
    }
    std::cout << "\n";

}

bool
PxOsdUtilSubdivTopology::ReadFromObjFile( char const * fname,
                                          vector<float> *pointPositions,
                                          std::string *errorMessage ) {

    FILE * handle = fopen( fname, "rt" );
    if (not handle) {
        stringstream ss;
        ss << "Could not open .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fseek( handle, 0, SEEK_END );
    size_t size = ftell(handle);
    fseek( handle, 0, SEEK_SET );

    char * shapeStr = new char[size+1];

    if ( fread( shapeStr, size, 1, handle)!=1 ) {
        stringstream ss;
        ss << "Error reading .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fclose(handle);

    shapeStr[size]='\0';

    name = fname;

    return ParseFromObjString(shapeStr, 1, pointPositions );
}

static char const * sgets( char * s, int size, char ** stream ) {
    for (int i=0; i<size; ++i) {
        if ( (*stream)[i]=='\n' or (*stream)[i]=='\0') {

            memcpy(s, *stream, i);
            s[i]='\0';

            if ((*stream)[i]=='\0')
                return 0;
            else {
                (*stream) += i+1;
                return s;
            }
        }
    }
    return 0;
}

bool
PxOsdUtilSubdivTopology::ParseFromObjString(
    char const * shapestr, int axis,
    vector<float> *pointPositions,
    std::string *errorMessage)
{
    char * str=const_cast<char *>(shapestr), line[256];
    bool done = false;

    while( not done ) {

        done = sgets(line, sizeof(line), &str)==0;
        char* end = &line[strlen(line)-1];
        if (*end == '\n')
            *end = '\0'; // strip trailing nl

        float x, y, z, u, v;
        switch (line[0]) {
        case 'v': switch (line[1]) {
            case ' ':
                if(sscanf(line, "v %f %f %f", &x, &y, &z) == 3) {
                    pointPositions->push_back(x);
                    switch( axis ) {
                    case 0 : pointPositions->push_back(-z);
                        pointPositions->push_back(y); break;
                    case 1 : pointPositions->push_back(y);
                        pointPositions->push_back(z); break;
                    }
                } break;
            case 't':
                if(sscanf(line, "vt %f %f", &u, &v) == 2) {
                    //XXX:gelder
                    // extract UVs
                    // s->uvs.push_back(u);
                    // s->uvs.push_back(v);
                } break;
            case 'n' :
                break; // skip normals for now
            }
            break;
        case 'f':
            if(line[1] == ' ')  {
                int vi, ti, ni;
                const char* cp = &line[2];
                while (*cp == ' ') cp++;
                int numVerts = 0, nitems=0;
                while( (nitems=sscanf(cp, "%d/%d/%d", &vi, &ti, &ni))>0) {
                    numVerts++;
                    indices.push_back(vi-1);
                    //XXX:gelder
                    // Extract face varying uvs
                    //if(nitems >= 1) s->faceuvs.push_back(ti-1);
                    //if(nitems >= 2) s->facenormals.push_back(ni-1);
                    while (*cp && *cp != ' ') cp++;
                    while (*cp == ' ') cp++;
                }
                nverts.push_back(numVerts);
            }
            break;
//        case 't' : if(line[1] == ' ') {
//                shape::tag * t = tag::parseTag( line );
//                if (t)
//                    s->tags.push_back(t);
//            } break;
        }
    }

    numVertices = pointPositions->size()/3;

    return true;
}
<commit_msg>Fixed VS2010 build errors.<commit_after>//
//   Copyright 2013 Pixar
//
//   Licensed under the Apache License, Version 2.0 (the "Apache License")
//   with the following modification; you may not use this file except in
//   compliance with the Apache License and the following modification to it:
//   Section 6. Trademarks. is deleted and replaced with:
//
//   6. Trademarks. This License does not grant permission to use the trade
//      names, trademarks, service marks, or product names of the Licensor
//      and its affiliates, except as required to comply with Section 4(c) of
//      the License and to reproduce the content of the NOTICE file.
//
//   You may obtain a copy of the Apache License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the Apache License with the above modification is
//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//   KIND, either express or implied. See the Apache License for the specific
//   language governing permissions and limitations under the Apache License.
//
#include "topology.h"

#include <sstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

PxOsdUtilSubdivTopology::PxOsdUtilSubdivTopology():
    name("noname"),
    numVertices(0),
    refinementLevel(2)  // arbitrary, start with a reasonable subdivision level
{
    std::cout << "Creating subdiv topology object\n";
}

PxOsdUtilSubdivTopology::~PxOsdUtilSubdivTopology()
{
    std::cout << "Destroying subdiv topology object\n";
}

bool
PxOsdUtilSubdivTopology::Initialize(
    int numVerticesParam,
    const int *nvertsParam, int numFaces,
    const int *indicesParam, int indicesLen,
    int levels,
    string *errorMessage)
{

    numVertices = numVerticesParam;
    refinementLevel = levels;

    nverts.resize(numFaces);
    for (int i=0; i<numFaces; ++i) {
        nverts[i] = nvertsParam[i];
    }

    indices.resize(indicesLen);
    for (int i=0; i<indicesLen; ++i) {
        indices[i] = indicesParam[i];
    }

    return IsValid(errorMessage);
}

bool
PxOsdUtilSubdivTopology::IsValid(string *errorMessage) const
{
    if (numVertices == 0) {
        if (errorMessage) {
            stringstream ss;
            ss << "Topology " << name << " has no vertices";
            *errorMessage = ss.str();
        }
        return false;
    }

    for (int i=0; i<(int)indices.size(); ++i) {
        if ((indices[i] < 0) or
            (indices[i] >= numVertices)) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad index " << indices[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }

    }

    int totalNumIndices = 0;
    for (int i=0; i< (int)nverts.size(); ++i) {
        if (nverts[i] < 1) {
            if (errorMessage) {
                stringstream ss;
                ss << "Topology " << name << " has bad nverts " << nverts[i] << " at index " << i;
                *errorMessage = ss.str();
            }
            return false;
        }
        totalNumIndices += nverts[i];
    }

    if (totalNumIndices != (int)indices.size()) {
        if (errorMessage) {
            *errorMessage = "Bad indexing for face topology";
        }

        return false;
    }

    std::cout << "\n";

    return true;
}

void
PxOsdUtilSubdivTopology::Print() const
{
    std::cout << "Mesh " << name << "\n";
    std::cout << "\tnumVertices = " << numVertices << "\n";
    std::cout << "\trefinementLevel = " << refinementLevel << "\n";
    std::cout << "\tindices ( " << indices.size() << ") : ";
    for (int i=0; i<(int)indices.size(); ++i) {
        std::cout << indices[i] << ", ";
    }
    std::cout << "\n";

    std::cout << "\tnverts ( " << nverts.size() << ") : ";
    for (int i=0; i<(int)nverts.size(); ++i) {
        std::cout << nverts[i] << ", ";
    }
    std::cout << "\n";

}

bool
PxOsdUtilSubdivTopology::ReadFromObjFile( char const * fname,
                                          vector<float> *pointPositions,
                                          std::string *errorMessage ) {

    FILE * handle = fopen( fname, "rt" );
    if (not handle) {
        stringstream ss;
        ss << "Could not open .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fseek( handle, 0, SEEK_END );
    size_t size = ftell(handle);
    fseek( handle, 0, SEEK_SET );

    char * shapeStr = new char[size+1];

    if ( fread( shapeStr, size, 1, handle)!=1 ) {
        stringstream ss;
        ss << "Error reading .obj file " << fname ;
        *errorMessage = ss.str();
        return false;
    }

    fclose(handle);

    shapeStr[size]='\0';

    name = fname;

    return ParseFromObjString(shapeStr, 1, pointPositions );
}

static char const * sgets( char * s, int size, char ** stream ) {
    for (int i=0; i<size; ++i) {
        if ( (*stream)[i]=='\n' or (*stream)[i]=='\0') {

            memcpy(s, *stream, i);
            s[i]='\0';

            if ((*stream)[i]=='\0')
                return 0;
            else {
                (*stream) += i+1;
                return s;
            }
        }
    }
    return 0;
}

bool
PxOsdUtilSubdivTopology::ParseFromObjString(
    char const * shapestr, int axis,
    vector<float> *pointPositions,
    std::string *errorMessage)
{
    char * str=const_cast<char *>(shapestr), line[256];
    bool done = false;

    while( not done ) {

        done = sgets(line, sizeof(line), &str)==0;
        char* end = &line[strlen(line)-1];
        if (*end == '\n')
            *end = '\0'; // strip trailing nl

        float x, y, z, u, v;
        switch (line[0]) {
        case 'v': switch (line[1]) {
            case ' ':
                if(sscanf(line, "v %f %f %f", &x, &y, &z) == 3) {
                    pointPositions->push_back(x);
                    switch( axis ) {
                    case 0 : pointPositions->push_back(-z);
                        pointPositions->push_back(y); break;
                    case 1 : pointPositions->push_back(y);
                        pointPositions->push_back(z); break;
                    }
                } break;
            case 't':
                if(sscanf(line, "vt %f %f", &u, &v) == 2) {
                    //XXX:gelder
                    // extract UVs
                    // s->uvs.push_back(u);
                    // s->uvs.push_back(v);
                } break;
            case 'n' :
                break; // skip normals for now
            }
            break;
        case 'f':
            if(line[1] == ' ')  {
                int vi, ti, ni;
                const char* cp = &line[2];
                while (*cp == ' ') cp++;
                int numVerts = 0, nitems=0;
                while( (nitems=sscanf(cp, "%d/%d/%d", &vi, &ti, &ni))>0) {
                    numVerts++;
                    indices.push_back(vi-1);
                    //XXX:gelder
                    // Extract face varying uvs
                    //if(nitems >= 1) s->faceuvs.push_back(ti-1);
                    //if(nitems >= 2) s->facenormals.push_back(ni-1);
                    while (*cp && *cp != ' ') cp++;
                    while (*cp == ' ') cp++;
                }
                nverts.push_back(numVerts);
            }
            break;
//        case 't' : if(line[1] == ' ') {
//                shape::tag * t = tag::parseTag( line );
//                if (t)
//                    s->tags.push_back(t);
//            } break;
        }
    }

    numVertices = (int)pointPositions->size()/3;

    return true;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/counter_values_table.h"

namespace perfetto {
namespace trace_processor {

CounterValuesTable::CounterValuesTable(sqlite3*, const TraceStorage* storage)
    : storage_(storage) {}

void CounterValuesTable::RegisterTable(sqlite3* db,
                                       const TraceStorage* storage) {
  SqliteTable::Register<CounterValuesTable>(db, storage, "counter");
}

StorageSchema CounterValuesTable::CreateStorageSchema() {
  const auto& cs = storage_->counter_values();
  return StorageSchema::Builder()
      .AddGenericNumericColumn("id", RowIdAccessor(TableId::kCounterValues))
      .AddNumericColumn("track_id", &cs.track_ids(), &cs.rows_for_track_id())
      .AddOrderedNumericColumn("ts", &cs.timestamps())
      .AddNumericColumn("value", &cs.values())
      .AddNumericColumn("arg_set_id", &cs.arg_set_ids())
      .Build({"id"});
}

uint32_t CounterValuesTable::RowCount() {
  return storage_->counter_values().size();
}

int CounterValuesTable::BestIndex(const QueryConstraints& qc,
                                  BestIndexInfo* info) {
  info->estimated_cost = EstimateCost(qc);
  info->sqlite_omit_order_by = true;
  for (auto& c_info : info->constraint_info)
    c_info.sqlite_omit = true;

  return SQLITE_OK;
}

uint32_t CounterValuesTable::EstimateCost(const QueryConstraints& qc) {
  if (HasEqConstraint(qc, "counter_id"))
    return RowCount() / 100;
  return RowCount();
}

}  // namespace trace_processor
}  // namespace perfetto
<commit_msg>trace_processor: fix counter values best index logic am: 202c12e4ab am: 31b59abb38<commit_after>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/counter_values_table.h"

namespace perfetto {
namespace trace_processor {

CounterValuesTable::CounterValuesTable(sqlite3*, const TraceStorage* storage)
    : storage_(storage) {}

void CounterValuesTable::RegisterTable(sqlite3* db,
                                       const TraceStorage* storage) {
  SqliteTable::Register<CounterValuesTable>(db, storage, "counter");
}

StorageSchema CounterValuesTable::CreateStorageSchema() {
  const auto& cs = storage_->counter_values();
  return StorageSchema::Builder()
      .AddGenericNumericColumn("id", RowIdAccessor(TableId::kCounterValues))
      .AddNumericColumn("track_id", &cs.track_ids(), &cs.rows_for_track_id())
      .AddOrderedNumericColumn("ts", &cs.timestamps())
      .AddNumericColumn("value", &cs.values())
      .AddNumericColumn("arg_set_id", &cs.arg_set_ids())
      .Build({"id"});
}

uint32_t CounterValuesTable::RowCount() {
  return storage_->counter_values().size();
}

int CounterValuesTable::BestIndex(const QueryConstraints& qc,
                                  BestIndexInfo* info) {
  info->estimated_cost = EstimateCost(qc);
  info->sqlite_omit_order_by = true;
  for (auto& c_info : info->constraint_info)
    c_info.sqlite_omit = true;

  return SQLITE_OK;
}

uint32_t CounterValuesTable::EstimateCost(const QueryConstraints& qc) {
  if (HasEqConstraint(qc, "track_id"))
    return RowCount() / 100;
  return RowCount();
}

}  // namespace trace_processor
}  // namespace perfetto
<|endoftext|>


<commit_before>//===-- DWARFDebugInfoEntry.cpp --------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DWARFDebugInfoEntry.h"
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFFormValue.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace dwarf;

void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
                                      const DWARFCompileUnit *cu,
                                      unsigned recurseDepth,
                                      unsigned indent) const {
  DataExtractor debug_info_data = cu->getDebugInfoExtractor();
  uint32_t offset = Offset;

  if (debug_info_data.isValidOffset(offset)) {
    uint64_t abbrCode = debug_info_data.getULEB128(&offset);

    OS << format("\n0x%8.8x: ", Offset);
    if (abbrCode) {
      if (AbbrevDecl) {
        OS.indent(indent) << TagString(AbbrevDecl->getTag())
                          << format(" [%u] %c\n", abbrCode,
                                    AbbrevDecl->hasChildren() ? '*': ' ');

        // Dump all data in the .debug_info for the attributes
        const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
        for (uint32_t i = 0; i != numAttributes; ++i) {
          uint16_t attr = AbbrevDecl->getAttrByIndex(i);
          uint16_t form = AbbrevDecl->getFormByIndex(i);
          dumpAttribute(OS, cu, &offset, attr, form, indent);
        }

        const DWARFDebugInfoEntryMinimal *child = getFirstChild();
        if (recurseDepth > 0 && child) {
          while (child) {
            child->dump(OS, cu, recurseDepth-1, indent+2);
            child = child->getSibling();
          }
        }
      } else {
        OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
           << abbrCode << '\n';
      }
    } else {
      OS.indent(indent) << "NULL\n";
    }
  }
}

void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
                                               const DWARFCompileUnit *cu,
                                               uint32_t* offset_ptr,
                                               uint16_t attr,
                                               uint16_t form,
                                               unsigned indent) const {
  OS << format("0x%8.8x: ", *offset_ptr);
  OS.indent(indent+2)   << AttributeString(attr)
                      << " [" << FormEncodingString(form) << ']';

  DWARFFormValue formValue(form);

  if (!formValue.extractValue(cu->getDebugInfoExtractor(), offset_ptr, cu))
    return;

  OS << "\t(";
  formValue.dump(OS, 0, cu);
  OS << ")\n";
}

bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
                                             const uint8_t *fixed_form_sizes,
                                             uint32_t *offset_ptr) {
  Offset = *offset_ptr;

  DataExtractor debug_info_data = cu->getDebugInfoExtractor();
  uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr);

  assert (fixed_form_sizes); // For best performance this should be specified!

  if (abbrCode) {
    uint32_t offset = *offset_ptr;

    AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);

    // Skip all data in the .debug_info for the attributes
    const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
    uint32_t i;
    uint16_t form;
    for (i=0; i<numAttributes; ++i) {
      form = AbbrevDecl->getFormByIndex(i);

      const uint8_t fixed_skip_size = fixed_form_sizes[form];
      if (fixed_skip_size)
        offset += fixed_skip_size;
      else {
        bool form_is_indirect = false;
        do {
          form_is_indirect = false;
          uint32_t form_size = 0;
          switch (form) {
          // Blocks if inlined data that have a length field and the data bytes
          // inlined in the .debug_info.
          case DW_FORM_block:
            form_size = debug_info_data.getULEB128(&offset);
            break;
          case DW_FORM_block1:
            form_size = debug_info_data.getU8(&offset);
            break;
          case DW_FORM_block2:
            form_size = debug_info_data.getU16(&offset);
            break;
          case DW_FORM_block4:
            form_size = debug_info_data.getU32(&offset);
            break;

          // Inlined NULL terminated C-strings
          case DW_FORM_string:
            debug_info_data.getCStr(&offset);
            break;

          // Compile unit address sized values
          case DW_FORM_addr:
          case DW_FORM_ref_addr:
            form_size = cu->getAddressByteSize();
            break;

          // 1 byte values
          case DW_FORM_data1:
          case DW_FORM_flag:
          case DW_FORM_ref1:
            form_size = 1;
            break;

          // 2 byte values
          case DW_FORM_data2:
          case DW_FORM_ref2:
            form_size = 2;
            break;

          // 4 byte values
          case DW_FORM_strp:
          case DW_FORM_data4:
          case DW_FORM_ref4:
            form_size = 4;
            break;

          // 8 byte values
          case DW_FORM_data8:
          case DW_FORM_ref8:
            form_size = 8;
            break;

          // signed or unsigned LEB 128 values
          case DW_FORM_sdata:
          case DW_FORM_udata:
          case DW_FORM_ref_udata:
            debug_info_data.getULEB128(&offset);
            break;

          case DW_FORM_indirect:
            form_is_indirect = true;
            form = debug_info_data.getULEB128(&offset);
            break;

          default:
            *offset_ptr = Offset;
            return false;
          }
          offset += form_size;

        } while (form_is_indirect);
      }
    }
    *offset_ptr = offset;
    return true;
  } else {
    AbbrevDecl = NULL;
    return true; // NULL debug tag entry
  }

  return false;
}

bool
DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
                                    uint32_t *offset_ptr) {
  DataExtractor debug_info_data = cu->getDebugInfoExtractor();
  const uint32_t cu_end_offset = cu->getNextCompileUnitOffset();
  const uint8_t cu_addr_size = cu->getAddressByteSize();
  uint32_t offset = *offset_ptr;
  if ((offset < cu_end_offset) && debug_info_data.isValidOffset(offset)) {
    Offset = offset;

    uint64_t abbrCode = debug_info_data.getULEB128(&offset);

    if (abbrCode) {
      AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);

      if (AbbrevDecl) {
        uint16_t tag = AbbrevDecl->getTag();

        bool isCompileUnitTag = tag == DW_TAG_compile_unit;
        if(cu && isCompileUnitTag)
          const_cast<DWARFCompileUnit*>(cu)->setBaseAddress(0);

        // Skip all data in the .debug_info for the attributes
        const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
        for (uint32_t i = 0; i != numAttributes; ++i) {
          uint16_t attr = AbbrevDecl->getAttrByIndex(i);
          uint16_t form = AbbrevDecl->getFormByIndex(i);

          if (isCompileUnitTag &&
              ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) {
            DWARFFormValue form_value(form);
            if (form_value.extractValue(debug_info_data, &offset, cu)) {
              if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
                const_cast<DWARFCompileUnit*>(cu)
                  ->setBaseAddress(form_value.getUnsigned());
            }
          } else {
            bool form_is_indirect = false;
            do {
              form_is_indirect = false;
              register uint32_t form_size = 0;
              switch (form) {
              // Blocks if inlined data that have a length field and the data
              // bytes // inlined in the .debug_info
              case DW_FORM_block:
                form_size = debug_info_data.getULEB128(&offset);
                break;
              case DW_FORM_block1:
                form_size = debug_info_data.getU8(&offset);
                break;
              case DW_FORM_block2:
                form_size = debug_info_data.getU16(&offset);
                break;
              case DW_FORM_block4:
                form_size = debug_info_data.getU32(&offset);
                break;

              // Inlined NULL terminated C-strings
              case DW_FORM_string:
                debug_info_data.getCStr(&offset);
                break;

              // Compile unit address sized values
              case DW_FORM_addr:
              case DW_FORM_ref_addr:
                form_size = cu_addr_size;
                break;

              // 1 byte values
              case DW_FORM_data1:
              case DW_FORM_flag:
              case DW_FORM_ref1:
                form_size = 1;
                break;

              // 2 byte values
              case DW_FORM_data2:
              case DW_FORM_ref2:
                form_size = 2;
                break;

                // 4 byte values
              case DW_FORM_strp:
                form_size = 4;
                break;

              case DW_FORM_data4:
              case DW_FORM_ref4:
                form_size = 4;
                break;

              // 8 byte values
              case DW_FORM_data8:
              case DW_FORM_ref8:
                form_size = 8;
                break;

              // signed or unsigned LEB 128 values
              case DW_FORM_sdata:
              case DW_FORM_udata:
              case DW_FORM_ref_udata:
                debug_info_data.getULEB128(&offset);
                break;

              case DW_FORM_indirect:
                form = debug_info_data.getULEB128(&offset);
                form_is_indirect = true;
                break;

              default:
                *offset_ptr = offset;
                return false;
              }

              offset += form_size;
            } while (form_is_indirect);
          }
        }
        *offset_ptr = offset;
        return true;
      }
    } else {
      AbbrevDecl = NULL;
      *offset_ptr = offset;
      return true;    // NULL debug tag entry
    }
  }

  return false;
}

uint32_t
DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
                                              const uint16_t attr,
                                              DWARFFormValue &form_value,
                                              uint32_t *end_attr_offset_ptr)
                                              const {
  if (AbbrevDecl) {
    uint32_t attr_idx = AbbrevDecl->findAttributeIndex(attr);

    if (attr_idx != -1U) {
      uint32_t offset = getOffset();

      DataExtractor debug_info_data = cu->getDebugInfoExtractor();

      // Skip the abbreviation code so we are at the data for the attributes
      debug_info_data.getULEB128(&offset);

      uint32_t idx = 0;
      while (idx < attr_idx)
        DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(idx++),
                                  debug_info_data, &offset, cu);

      const uint32_t attr_offset = offset;
      form_value = DWARFFormValue(AbbrevDecl->getFormByIndex(idx));
      if (form_value.extractValue(debug_info_data, &offset, cu)) {
        if (end_attr_offset_ptr)
          *end_attr_offset_ptr = offset;
        return attr_offset;
      }
    }
  }

  return 0;
}

const char*
DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
    const DWARFCompileUnit* cu,
    const uint16_t attr,
    const char* fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value)) {
    DataExtractor stringExtractor(cu->getContext().getStringSection(),
        false, 0);
    return form_value.getAsCString(&stringExtractor);
  }
  return fail_value;
}

uint64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
    const DWARFCompileUnit* cu,
    const uint16_t attr,
    uint64_t fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value))
      return form_value.getUnsigned();
  return fail_value;
}

int64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
    const DWARFCompileUnit* cu,
    const uint16_t attr,
    int64_t fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value))
      return form_value.getSigned();
  return fail_value;
}

uint64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
                                                  const DWARFCompileUnit* cu,
                                                  const uint16_t attr,
                                                  uint64_t fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value))
      return form_value.getReference(cu);
  return fail_value;
}

void
DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu,
                                               DWARFDebugAranges *debug_aranges)
                                                   const {
  if (AbbrevDecl) {
    uint16_t tag = AbbrevDecl->getTag();
    if (tag == DW_TAG_subprogram) {
      uint64_t hi_pc = -1ULL;
      uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
      if (lo_pc != -1ULL)
        hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
      if (hi_pc != -1ULL)
        debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc);
    }

    const DWARFDebugInfoEntryMinimal *child = getFirstChild();
    while (child) {
      child->buildAddressRangeTable(cu, debug_aranges);
      child = child->getSibling();
    }
  }
}
<commit_msg>DWARF: Make DIE printing more bulletproof.<commit_after>//===-- DWARFDebugInfoEntry.cpp --------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "DWARFDebugInfoEntry.h"
#include "DWARFCompileUnit.h"
#include "DWARFContext.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFFormValue.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace dwarf;

void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
                                      const DWARFCompileUnit *cu,
                                      unsigned recurseDepth,
                                      unsigned indent) const {
  DataExtractor debug_info_data = cu->getDebugInfoExtractor();
  uint32_t offset = Offset;

  if (debug_info_data.isValidOffset(offset)) {
    uint64_t abbrCode = debug_info_data.getULEB128(&offset);

    OS << format("\n0x%8.8x: ", Offset);
    if (abbrCode) {
      if (AbbrevDecl) {
        const char *tagString = TagString(getTag());
        if (tagString)
          OS.indent(indent) << tagString;
        else
          OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag());
        OS << format(" [%u] %c\n", abbrCode,
                     AbbrevDecl->hasChildren() ? '*' : ' ');

        // Dump all data in the .debug_info for the attributes
        const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
        for (uint32_t i = 0; i != numAttributes; ++i) {
          uint16_t attr = AbbrevDecl->getAttrByIndex(i);
          uint16_t form = AbbrevDecl->getFormByIndex(i);
          dumpAttribute(OS, cu, &offset, attr, form, indent);
        }

        const DWARFDebugInfoEntryMinimal *child = getFirstChild();
        if (recurseDepth > 0 && child) {
          while (child) {
            child->dump(OS, cu, recurseDepth-1, indent+2);
            child = child->getSibling();
          }
        }
      } else {
        OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
           << abbrCode << '\n';
      }
    } else {
      OS.indent(indent) << "NULL\n";
    }
  }
}

void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
                                               const DWARFCompileUnit *cu,
                                               uint32_t* offset_ptr,
                                               uint16_t attr,
                                               uint16_t form,
                                               unsigned indent) const {
  OS << format("0x%8.8x: ", *offset_ptr);
  OS.indent(indent+2);
  const char *attrString = AttributeString(attr);
  if (attrString)
    OS << attrString;
  else
    OS << format("DW_AT_Unknown_%x", attr);
  const char *formString = FormEncodingString(form);
  if (formString)
    OS << " [" << formString << ']';
  else
    OS << format(" [DW_FORM_Unknown_%x]", form);

  DWARFFormValue formValue(form);

  if (!formValue.extractValue(cu->getDebugInfoExtractor(), offset_ptr, cu))
    return;

  OS << "\t(";
  formValue.dump(OS, 0, cu);
  OS << ")\n";
}

bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
                                             const uint8_t *fixed_form_sizes,
                                             uint32_t *offset_ptr) {
  Offset = *offset_ptr;

  DataExtractor debug_info_data = cu->getDebugInfoExtractor();
  uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr);

  assert (fixed_form_sizes); // For best performance this should be specified!

  if (abbrCode) {
    uint32_t offset = *offset_ptr;

    AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);

    // Skip all data in the .debug_info for the attributes
    const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
    uint32_t i;
    uint16_t form;
    for (i=0; i<numAttributes; ++i) {
      form = AbbrevDecl->getFormByIndex(i);

      const uint8_t fixed_skip_size = fixed_form_sizes[form];
      if (fixed_skip_size)
        offset += fixed_skip_size;
      else {
        bool form_is_indirect = false;
        do {
          form_is_indirect = false;
          uint32_t form_size = 0;
          switch (form) {
          // Blocks if inlined data that have a length field and the data bytes
          // inlined in the .debug_info.
          case DW_FORM_block:
            form_size = debug_info_data.getULEB128(&offset);
            break;
          case DW_FORM_block1:
            form_size = debug_info_data.getU8(&offset);
            break;
          case DW_FORM_block2:
            form_size = debug_info_data.getU16(&offset);
            break;
          case DW_FORM_block4:
            form_size = debug_info_data.getU32(&offset);
            break;

          // Inlined NULL terminated C-strings
          case DW_FORM_string:
            debug_info_data.getCStr(&offset);
            break;

          // Compile unit address sized values
          case DW_FORM_addr:
          case DW_FORM_ref_addr:
            form_size = cu->getAddressByteSize();
            break;

          // 1 byte values
          case DW_FORM_data1:
          case DW_FORM_flag:
          case DW_FORM_ref1:
            form_size = 1;
            break;

          // 2 byte values
          case DW_FORM_data2:
          case DW_FORM_ref2:
            form_size = 2;
            break;

          // 4 byte values
          case DW_FORM_strp:
          case DW_FORM_data4:
          case DW_FORM_ref4:
            form_size = 4;
            break;

          // 8 byte values
          case DW_FORM_data8:
          case DW_FORM_ref8:
            form_size = 8;
            break;

          // signed or unsigned LEB 128 values
          case DW_FORM_sdata:
          case DW_FORM_udata:
          case DW_FORM_ref_udata:
            debug_info_data.getULEB128(&offset);
            break;

          case DW_FORM_indirect:
            form_is_indirect = true;
            form = debug_info_data.getULEB128(&offset);
            break;

          default:
            *offset_ptr = Offset;
            return false;
          }
          offset += form_size;

        } while (form_is_indirect);
      }
    }
    *offset_ptr = offset;
    return true;
  } else {
    AbbrevDecl = NULL;
    return true; // NULL debug tag entry
  }

  return false;
}

bool
DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
                                    uint32_t *offset_ptr) {
  DataExtractor debug_info_data = cu->getDebugInfoExtractor();
  const uint32_t cu_end_offset = cu->getNextCompileUnitOffset();
  const uint8_t cu_addr_size = cu->getAddressByteSize();
  uint32_t offset = *offset_ptr;
  if ((offset < cu_end_offset) && debug_info_data.isValidOffset(offset)) {
    Offset = offset;

    uint64_t abbrCode = debug_info_data.getULEB128(&offset);

    if (abbrCode) {
      AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode);

      if (AbbrevDecl) {
        uint16_t tag = AbbrevDecl->getTag();

        bool isCompileUnitTag = tag == DW_TAG_compile_unit;
        if(cu && isCompileUnitTag)
          const_cast<DWARFCompileUnit*>(cu)->setBaseAddress(0);

        // Skip all data in the .debug_info for the attributes
        const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
        for (uint32_t i = 0; i != numAttributes; ++i) {
          uint16_t attr = AbbrevDecl->getAttrByIndex(i);
          uint16_t form = AbbrevDecl->getFormByIndex(i);

          if (isCompileUnitTag &&
              ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) {
            DWARFFormValue form_value(form);
            if (form_value.extractValue(debug_info_data, &offset, cu)) {
              if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
                const_cast<DWARFCompileUnit*>(cu)
                  ->setBaseAddress(form_value.getUnsigned());
            }
          } else {
            bool form_is_indirect = false;
            do {
              form_is_indirect = false;
              register uint32_t form_size = 0;
              switch (form) {
              // Blocks if inlined data that have a length field and the data
              // bytes // inlined in the .debug_info
              case DW_FORM_block:
                form_size = debug_info_data.getULEB128(&offset);
                break;
              case DW_FORM_block1:
                form_size = debug_info_data.getU8(&offset);
                break;
              case DW_FORM_block2:
                form_size = debug_info_data.getU16(&offset);
                break;
              case DW_FORM_block4:
                form_size = debug_info_data.getU32(&offset);
                break;

              // Inlined NULL terminated C-strings
              case DW_FORM_string:
                debug_info_data.getCStr(&offset);
                break;

              // Compile unit address sized values
              case DW_FORM_addr:
              case DW_FORM_ref_addr:
                form_size = cu_addr_size;
                break;

              // 1 byte values
              case DW_FORM_data1:
              case DW_FORM_flag:
              case DW_FORM_ref1:
                form_size = 1;
                break;

              // 2 byte values
              case DW_FORM_data2:
              case DW_FORM_ref2:
                form_size = 2;
                break;

                // 4 byte values
              case DW_FORM_strp:
                form_size = 4;
                break;

              case DW_FORM_data4:
              case DW_FORM_ref4:
                form_size = 4;
                break;

              // 8 byte values
              case DW_FORM_data8:
              case DW_FORM_ref8:
                form_size = 8;
                break;

              // signed or unsigned LEB 128 values
              case DW_FORM_sdata:
              case DW_FORM_udata:
              case DW_FORM_ref_udata:
                debug_info_data.getULEB128(&offset);
                break;

              case DW_FORM_indirect:
                form = debug_info_data.getULEB128(&offset);
                form_is_indirect = true;
                break;

              default:
                *offset_ptr = offset;
                return false;
              }

              offset += form_size;
            } while (form_is_indirect);
          }
        }
        *offset_ptr = offset;
        return true;
      }
    } else {
      AbbrevDecl = NULL;
      *offset_ptr = offset;
      return true;    // NULL debug tag entry
    }
  }

  return false;
}

uint32_t
DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu,
                                              const uint16_t attr,
                                              DWARFFormValue &form_value,
                                              uint32_t *end_attr_offset_ptr)
                                              const {
  if (AbbrevDecl) {
    uint32_t attr_idx = AbbrevDecl->findAttributeIndex(attr);

    if (attr_idx != -1U) {
      uint32_t offset = getOffset();

      DataExtractor debug_info_data = cu->getDebugInfoExtractor();

      // Skip the abbreviation code so we are at the data for the attributes
      debug_info_data.getULEB128(&offset);

      uint32_t idx = 0;
      while (idx < attr_idx)
        DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(idx++),
                                  debug_info_data, &offset, cu);

      const uint32_t attr_offset = offset;
      form_value = DWARFFormValue(AbbrevDecl->getFormByIndex(idx));
      if (form_value.extractValue(debug_info_data, &offset, cu)) {
        if (end_attr_offset_ptr)
          *end_attr_offset_ptr = offset;
        return attr_offset;
      }
    }
  }

  return 0;
}

const char*
DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
    const DWARFCompileUnit* cu,
    const uint16_t attr,
    const char* fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value)) {
    DataExtractor stringExtractor(cu->getContext().getStringSection(),
        false, 0);
    return form_value.getAsCString(&stringExtractor);
  }
  return fail_value;
}

uint64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
    const DWARFCompileUnit* cu,
    const uint16_t attr,
    uint64_t fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value))
      return form_value.getUnsigned();
  return fail_value;
}

int64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
    const DWARFCompileUnit* cu,
    const uint16_t attr,
    int64_t fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value))
      return form_value.getSigned();
  return fail_value;
}

uint64_t
DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
                                                  const DWARFCompileUnit* cu,
                                                  const uint16_t attr,
                                                  uint64_t fail_value) const {
  DWARFFormValue form_value;
  if (getAttributeValue(cu, attr, form_value))
      return form_value.getReference(cu);
  return fail_value;
}

void
DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu,
                                               DWARFDebugAranges *debug_aranges)
                                                   const {
  if (AbbrevDecl) {
    uint16_t tag = AbbrevDecl->getTag();
    if (tag == DW_TAG_subprogram) {
      uint64_t hi_pc = -1ULL;
      uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
      if (lo_pc != -1ULL)
        hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
      if (hi_pc != -1ULL)
        debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc);
    }

    const DWARFDebugInfoEntryMinimal *child = getFirstChild();
    while (child) {
      child->buildAddressRangeTable(cu, debug_aranges);
      child = child->getSibling();
    }
  }
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "luanode.h"
#include "luanode_constants.h"

#define SET_ERR_FIELD(e, v)  lua_pushinteger(L, boost::asio::error::e); lua_setfield(L, t, #v);

void LuaNode::DefineConstants(lua_State* L)
{
	lua_newtable(L);
	int t = lua_gettop(L);

	SET_ERR_FIELD(access_denied, EACCES);
	SET_ERR_FIELD(address_family_not_supported, EAFNOSUPPORT);
	SET_ERR_FIELD(address_in_use, EADDRINUSE);
	SET_ERR_FIELD(already_connected, EISCONN);
	SET_ERR_FIELD(already_started, EALREADY);
	SET_ERR_FIELD(broken_pipe, EPIPE);
	SET_ERR_FIELD(connection_aborted, ECONNABORTED);
	SET_ERR_FIELD(connection_refused, ECONNREFUSED);
	SET_ERR_FIELD(connection_reset, ECONNRESET);
	SET_ERR_FIELD(bad_descriptor, EBADF);
	SET_ERR_FIELD(fault, EFAULT);
	SET_ERR_FIELD(host_unreachable, EHOSTUNREACH);
	SET_ERR_FIELD(in_progress, EINPROGRESS);
	SET_ERR_FIELD(interrupted, EINTR);
	SET_ERR_FIELD(invalid_argument, EINVAL);
	SET_ERR_FIELD(message_size, EMSGSIZE);
	SET_ERR_FIELD(name_too_long, ENAMETOOLONG);
	SET_ERR_FIELD(network_down, ENETDOWN);
	SET_ERR_FIELD(network_reset, ENETRESET);
	SET_ERR_FIELD(network_unreachable, ENETUNREACH);
	SET_ERR_FIELD(no_descriptors, EMFILE);
	SET_ERR_FIELD(no_buffer_space, ENOBUFS);
	SET_ERR_FIELD(no_memory, ENOMEM);
	SET_ERR_FIELD(no_permission, EPERM);
	SET_ERR_FIELD(no_protocol_option, ENOPROTOOPT);
	SET_ERR_FIELD(not_connected, ENOTCONN);
	SET_ERR_FIELD(not_socket, ENOTSOCK);
	SET_ERR_FIELD(operation_aborted, ECANCELED);
	SET_ERR_FIELD(operation_not_supported, EOPNOTSUPP);
	SET_ERR_FIELD(shut_down, ESHUTDOWN);
	SET_ERR_FIELD(timed_out, ETIMEDOUT);
	SET_ERR_FIELD(try_again, EAGAIN);
	SET_ERR_FIELD(would_block, EWOULDBLOCK);

	SET_ERR_FIELD(host_not_found, HOST_NOT_FOUND);
	SET_ERR_FIELD(host_not_found_try_again, TRY_AGAIN);
	SET_ERR_FIELD(no_data, NO_DATA);
	SET_ERR_FIELD(no_recovery, NO_RECOVERY);
}

#undef SET_ERR_FIELD
<commit_msg>Renamed macro<commit_after>#include "stdafx.h"
#include "luanode.h"
#include "luanode_constants.h"
#include <errno.h>

#define SET_BOOST_ERR_FIELD(e, v)  lua_pushinteger(L, boost::asio::error::e); lua_setfield(L, t, #v);

#if defined (_WIN32)
# define SET_ERR_FIELD(e) lua_pushinteger(L, WSA ## e); lua_setfield(L, t, #e);
#else
# define SET_ERR_FIELD(e) lua_pushinteger(L, e); lua_setfield(L, t, #e);
#endif

void LuaNode::DefineConstants(lua_State* L)
{
	lua_newtable(L);
	int t = lua_gettop(L);

	lua_pushinteger(L, boost::asio::error::eof); lua_setfield(L, t, "EOF");

	SET_BOOST_ERR_FIELD(access_denied, EACCES);
	SET_BOOST_ERR_FIELD(address_family_not_supported, EAFNOSUPPORT);
	SET_BOOST_ERR_FIELD(address_in_use, EADDRINUSE);
	SET_BOOST_ERR_FIELD(already_connected, EISCONN);
	SET_BOOST_ERR_FIELD(already_started, EALREADY);
	SET_BOOST_ERR_FIELD(broken_pipe, EPIPE);
	SET_BOOST_ERR_FIELD(connection_aborted, ECONNABORTED);
	SET_BOOST_ERR_FIELD(connection_refused, ECONNREFUSED);
	SET_BOOST_ERR_FIELD(connection_reset, ECONNRESET);
	SET_BOOST_ERR_FIELD(bad_descriptor, EBADF);
	SET_BOOST_ERR_FIELD(fault, EFAULT);
	SET_BOOST_ERR_FIELD(host_unreachable, EHOSTUNREACH);
	SET_BOOST_ERR_FIELD(in_progress, EINPROGRESS);
	SET_BOOST_ERR_FIELD(interrupted, EINTR);
	SET_BOOST_ERR_FIELD(invalid_argument, EINVAL);
	SET_BOOST_ERR_FIELD(message_size, EMSGSIZE);
	SET_BOOST_ERR_FIELD(name_too_long, ENAMETOOLONG);
	SET_BOOST_ERR_FIELD(network_down, ENETDOWN);
	SET_BOOST_ERR_FIELD(network_reset, ENETRESET);
	SET_BOOST_ERR_FIELD(network_unreachable, ENETUNREACH);
	SET_BOOST_ERR_FIELD(no_descriptors, EMFILE);
	SET_BOOST_ERR_FIELD(no_buffer_space, ENOBUFS);
	SET_BOOST_ERR_FIELD(no_memory, ENOMEM);
	SET_BOOST_ERR_FIELD(no_permission, EPERM);
	SET_BOOST_ERR_FIELD(no_protocol_option, ENOPROTOOPT);
	SET_BOOST_ERR_FIELD(not_connected, ENOTCONN);
	SET_BOOST_ERR_FIELD(not_socket, ENOTSOCK);
	SET_BOOST_ERR_FIELD(operation_aborted, ECANCELED);
	SET_BOOST_ERR_FIELD(operation_not_supported, EOPNOTSUPP);
	SET_BOOST_ERR_FIELD(shut_down, ESHUTDOWN);
	SET_BOOST_ERR_FIELD(timed_out, ETIMEDOUT);
	SET_BOOST_ERR_FIELD(try_again, EAGAIN);
	SET_BOOST_ERR_FIELD(would_block, EWOULDBLOCK);

	SET_BOOST_ERR_FIELD(host_not_found, HOST_NOT_FOUND);
	SET_BOOST_ERR_FIELD(host_not_found_try_again, TRY_AGAIN);
	SET_BOOST_ERR_FIELD(no_data, NO_DATA);
	SET_BOOST_ERR_FIELD(no_recovery, NO_RECOVERY);

#ifdef EPROCLIM
	SET_ERR_FIELD(EPROCLIM);
#endif

#ifdef WSAEPROCLIM
	SET_ERR_FIELD(EPROCLIM);
#endif

#ifdef EDESTADDRREQ
	SET_ERR_FIELD(EDESTADDRREQ);
#endif

#ifdef EPROTOTYPE
	SET_ERR_FIELD(EPROTOTYPE);
#endif

#ifdef EPROTONOSUPPORT
	SET_ERR_FIELD(EPROTONOSUPPORT);
#endif

#if defined(ESOCKTNOSUPPORT) || defined(WSAESOCKTNOSUPPORT)
	SET_ERR_FIELD(ESOCKTNOSUPPORT);
#endif

#if defined(EPFNOSUPPORT) || defined(WSAEPFNOSUPPORT)
	SET_ERR_FIELD(EPFNOSUPPORT);
#endif

#ifdef EADDRNOTAVAIL
	SET_ERR_FIELD(EADDRNOTAVAIL);
#endif

#if defined(EHOSTDOWN) || defined(WSAEHOSTDOWN)
	SET_ERR_FIELD(EHOSTDOWN);
#endif

#if defined(EDISCON) || defined(WSAEDISCON)
	SET_ERR_FIELD(EDISCON);
#endif
}

#undef SET_ERR_FIELD
<|endoftext|>


<commit_before>// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <sstream>

#include "src/v8.h"

#include "src/compiler/operator.h"
#include "test/cctest/cctest.h"

using namespace v8::internal;
using namespace v8::internal::compiler;

#define NaN (v8::base::OS::nan_value())

TEST(TestOperatorMnemonic) {
  SimpleOperator op1(10, Operator::kNoProperties, 0, 0, "ThisOne");
  CHECK_EQ(0, strcmp(op1.mnemonic(), "ThisOne"));

  SimpleOperator op2(11, Operator::kNoProperties, 0, 0, "ThatOne");
  CHECK_EQ(0, strcmp(op2.mnemonic(), "ThatOne"));

  Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "Mnemonic1", 12333);
  CHECK_EQ(0, strcmp(op3.mnemonic(), "Mnemonic1"));

  Operator1<double> op4(13, Operator::kNoProperties, 0, 1, "TheOther", 99.9);
  CHECK_EQ(0, strcmp(op4.mnemonic(), "TheOther"));
}

TEST(TestSimpleOperatorHash) {
  SimpleOperator op1(17, Operator::kNoProperties, 0, 0, "Another");
  CHECK_EQ(17, op1.HashCode());

  SimpleOperator op2(18, Operator::kNoProperties, 0, 0, "Falsch");
  CHECK_EQ(18, op2.HashCode());
}

TEST(TestSimpleOperatorEquals) {
  SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
  SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");

  CHECK(op1a.Equals(&op1a));
  CHECK(op1a.Equals(&op1b));
  CHECK(op1b.Equals(&op1a));
  CHECK(op1b.Equals(&op1b));

  SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Falsch1");
  SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Falsch2");

  CHECK(op2a.Equals(&op2a));
  CHECK(op2a.Equals(&op2b));
  CHECK(op2b.Equals(&op2a));
  CHECK(op2b.Equals(&op2b));

  CHECK(!op1a.Equals(&op2a));
  CHECK(!op1a.Equals(&op2b));
  CHECK(!op1b.Equals(&op2a));
  CHECK(!op1b.Equals(&op2b));

  CHECK(!op2a.Equals(&op1a));
  CHECK(!op2a.Equals(&op1b));
  CHECK(!op2b.Equals(&op1a));
  CHECK(!op2b.Equals(&op1b));
}

static SmartArrayPointer<const char> OperatorToString(Operator* op) {
  std::ostringstream os;
  os << *op;
  return SmartArrayPointer<const char>(StrDup(os.str().c_str()));
}

TEST(TestSimpleOperatorPrint) {
  SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
  SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");

  CHECK_EQ("Another1", OperatorToString(&op1a).get());
  CHECK_EQ("Another2", OperatorToString(&op1b).get());

  SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Flog1");
  SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Flog2");

  CHECK_EQ("Flog1", OperatorToString(&op2a).get());
  CHECK_EQ("Flog2", OperatorToString(&op2b).get());
}

TEST(TestOperator1intHash) {
  Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11);
  Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11);

  CHECK_EQ(op1a.HashCode(), op1b.HashCode());

  Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", 3);
  Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", 4);

  CHECK_NE(op1a.HashCode(), op2a.HashCode());
  CHECK_NE(op2a.HashCode(), op2b.HashCode());
}

TEST(TestOperator1intEquals) {
  Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11);
  Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11);

  CHECK(op1a.Equals(&op1a));
  CHECK(op1a.Equals(&op1b));
  CHECK(op1b.Equals(&op1a));
  CHECK(op1b.Equals(&op1b));

  Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3);
  Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Im", 4);

  CHECK(op2a.Equals(&op2a));
  CHECK(!op2a.Equals(&op2b));
  CHECK(!op2b.Equals(&op2a));
  CHECK(op2b.Equals(&op2b));

  CHECK(!op1a.Equals(&op2a));
  CHECK(!op1a.Equals(&op2b));
  CHECK(!op1b.Equals(&op2a));
  CHECK(!op1b.Equals(&op2b));

  CHECK(!op2a.Equals(&op1a));
  CHECK(!op2a.Equals(&op1b));
  CHECK(!op2b.Equals(&op1a));
  CHECK(!op2b.Equals(&op1b));

  SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");

  CHECK(!op1a.Equals(&op3));
  CHECK(!op1b.Equals(&op3));
  CHECK(!op2a.Equals(&op3));
  CHECK(!op2b.Equals(&op3));

  CHECK(!op3.Equals(&op1a));
  CHECK(!op3.Equals(&op1b));
  CHECK(!op3.Equals(&op2a));
  CHECK(!op3.Equals(&op2b));
}

TEST(TestOperator1intPrint) {
  Operator1<int> op1(12, Operator::kNoProperties, 0, 1, "Op1Test", 0);
  CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());

  Operator1<int> op2(12, Operator::kNoProperties, 0, 1, "Op1Test", 66666666);
  CHECK_EQ("Op1Test[66666666]", OperatorToString(&op2).get());

  Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "FooBar", 2347);
  CHECK_EQ("FooBar[2347]", OperatorToString(&op3).get());

  Operator1<int> op4(12, Operator::kNoProperties, 0, 1, "BarFoo", -879);
  CHECK_EQ("BarFoo[-879]", OperatorToString(&op4).get());
}

TEST(TestOperator1doubleHash) {
  Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11.77);
  Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11.77);

  CHECK_EQ(op1a.HashCode(), op1b.HashCode());

  Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", -6.7);
  Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", -6.8);

  CHECK_NE(op1a.HashCode(), op2a.HashCode());
  CHECK_NE(op2a.HashCode(), op2b.HashCode());
}

TEST(TestOperator1doubleEquals) {
  Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11.77);
  Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11.77);

  CHECK(op1a.Equals(&op1a));
  CHECK(op1a.Equals(&op1b));
  CHECK(op1b.Equals(&op1a));
  CHECK(op1b.Equals(&op1b));

  Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3.1);
  Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Im", 3.2);

  CHECK(op2a.Equals(&op2a));
  CHECK(!op2a.Equals(&op2b));
  CHECK(!op2b.Equals(&op2a));
  CHECK(op2b.Equals(&op2b));

  CHECK(!op1a.Equals(&op2a));
  CHECK(!op1a.Equals(&op2b));
  CHECK(!op1b.Equals(&op2a));
  CHECK(!op1b.Equals(&op2b));

  CHECK(!op2a.Equals(&op1a));
  CHECK(!op2a.Equals(&op1b));
  CHECK(!op2b.Equals(&op1a));
  CHECK(!op2b.Equals(&op1b));

  SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");

  CHECK(!op1a.Equals(&op3));
  CHECK(!op1b.Equals(&op3));
  CHECK(!op2a.Equals(&op3));
  CHECK(!op2b.Equals(&op3));

  CHECK(!op3.Equals(&op1a));
  CHECK(!op3.Equals(&op1b));
  CHECK(!op3.Equals(&op2a));
  CHECK(!op3.Equals(&op2b));

  Operator1<double> op4a(24, Operator::kNoProperties, 0, 0, "Bashful", NaN);
  Operator1<double> op4b(24, Operator::kNoProperties, 0, 0, "Bashful", NaN);

  CHECK(op4a.Equals(&op4a));
  CHECK(op4a.Equals(&op4b));
  CHECK(op4b.Equals(&op4a));
  CHECK(op4b.Equals(&op4b));

  CHECK(!op3.Equals(&op4a));
  CHECK(!op3.Equals(&op4b));
  CHECK(!op3.Equals(&op4a));
  CHECK(!op3.Equals(&op4b));
}

TEST(TestOperator1doublePrint) {
  Operator1<double> op1(12, Operator::kNoProperties, 0, 1, "Op1Test", 0);
  CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());

  Operator1<double> op2(12, Operator::kNoProperties, 0, 1, "Op1Test", 7.3);
  CHECK_EQ("Op1Test[7.3]", OperatorToString(&op2).get());

  Operator1<double> op3(12, Operator::kNoProperties, 0, 1, "FooBar", 2e+123);
  CHECK_EQ("FooBar[2e+123]", OperatorToString(&op3).get());

  Operator1<double> op5(12, Operator::kNoProperties, 0, 1, "BarFoo", NaN);
  CHECK_EQ("BarFoo[nan]", OperatorToString(&op5).get());
}
<commit_msg>Fix windows build after r24322.<commit_after>// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <sstream>

#include "src/v8.h"

#include "src/compiler/operator.h"
#include "test/cctest/cctest.h"

using namespace v8::internal;
using namespace v8::internal::compiler;

TEST(TestOperatorMnemonic) {
  SimpleOperator op1(10, Operator::kNoProperties, 0, 0, "ThisOne");
  CHECK_EQ(0, strcmp(op1.mnemonic(), "ThisOne"));

  SimpleOperator op2(11, Operator::kNoProperties, 0, 0, "ThatOne");
  CHECK_EQ(0, strcmp(op2.mnemonic(), "ThatOne"));

  Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "Mnemonic1", 12333);
  CHECK_EQ(0, strcmp(op3.mnemonic(), "Mnemonic1"));

  Operator1<double> op4(13, Operator::kNoProperties, 0, 1, "TheOther", 99.9);
  CHECK_EQ(0, strcmp(op4.mnemonic(), "TheOther"));
}

TEST(TestSimpleOperatorHash) {
  SimpleOperator op1(17, Operator::kNoProperties, 0, 0, "Another");
  CHECK_EQ(17, op1.HashCode());

  SimpleOperator op2(18, Operator::kNoProperties, 0, 0, "Falsch");
  CHECK_EQ(18, op2.HashCode());
}

TEST(TestSimpleOperatorEquals) {
  SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
  SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");

  CHECK(op1a.Equals(&op1a));
  CHECK(op1a.Equals(&op1b));
  CHECK(op1b.Equals(&op1a));
  CHECK(op1b.Equals(&op1b));

  SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Falsch1");
  SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Falsch2");

  CHECK(op2a.Equals(&op2a));
  CHECK(op2a.Equals(&op2b));
  CHECK(op2b.Equals(&op2a));
  CHECK(op2b.Equals(&op2b));

  CHECK(!op1a.Equals(&op2a));
  CHECK(!op1a.Equals(&op2b));
  CHECK(!op1b.Equals(&op2a));
  CHECK(!op1b.Equals(&op2b));

  CHECK(!op2a.Equals(&op1a));
  CHECK(!op2a.Equals(&op1b));
  CHECK(!op2b.Equals(&op1a));
  CHECK(!op2b.Equals(&op1b));
}

static SmartArrayPointer<const char> OperatorToString(Operator* op) {
  std::ostringstream os;
  os << *op;
  return SmartArrayPointer<const char>(StrDup(os.str().c_str()));
}

TEST(TestSimpleOperatorPrint) {
  SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
  SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");

  CHECK_EQ("Another1", OperatorToString(&op1a).get());
  CHECK_EQ("Another2", OperatorToString(&op1b).get());

  SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Flog1");
  SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Flog2");

  CHECK_EQ("Flog1", OperatorToString(&op2a).get());
  CHECK_EQ("Flog2", OperatorToString(&op2b).get());
}

TEST(TestOperator1intHash) {
  Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11);
  Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11);

  CHECK_EQ(op1a.HashCode(), op1b.HashCode());

  Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", 3);
  Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", 4);

  CHECK_NE(op1a.HashCode(), op2a.HashCode());
  CHECK_NE(op2a.HashCode(), op2b.HashCode());
}

TEST(TestOperator1intEquals) {
  Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11);
  Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11);

  CHECK(op1a.Equals(&op1a));
  CHECK(op1a.Equals(&op1b));
  CHECK(op1b.Equals(&op1a));
  CHECK(op1b.Equals(&op1b));

  Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3);
  Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Im", 4);

  CHECK(op2a.Equals(&op2a));
  CHECK(!op2a.Equals(&op2b));
  CHECK(!op2b.Equals(&op2a));
  CHECK(op2b.Equals(&op2b));

  CHECK(!op1a.Equals(&op2a));
  CHECK(!op1a.Equals(&op2b));
  CHECK(!op1b.Equals(&op2a));
  CHECK(!op1b.Equals(&op2b));

  CHECK(!op2a.Equals(&op1a));
  CHECK(!op2a.Equals(&op1b));
  CHECK(!op2b.Equals(&op1a));
  CHECK(!op2b.Equals(&op1b));

  SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");

  CHECK(!op1a.Equals(&op3));
  CHECK(!op1b.Equals(&op3));
  CHECK(!op2a.Equals(&op3));
  CHECK(!op2b.Equals(&op3));

  CHECK(!op3.Equals(&op1a));
  CHECK(!op3.Equals(&op1b));
  CHECK(!op3.Equals(&op2a));
  CHECK(!op3.Equals(&op2b));
}

TEST(TestOperator1intPrint) {
  Operator1<int> op1(12, Operator::kNoProperties, 0, 1, "Op1Test", 0);
  CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());

  Operator1<int> op2(12, Operator::kNoProperties, 0, 1, "Op1Test", 66666666);
  CHECK_EQ("Op1Test[66666666]", OperatorToString(&op2).get());

  Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "FooBar", 2347);
  CHECK_EQ("FooBar[2347]", OperatorToString(&op3).get());

  Operator1<int> op4(12, Operator::kNoProperties, 0, 1, "BarFoo", -879);
  CHECK_EQ("BarFoo[-879]", OperatorToString(&op4).get());
}

TEST(TestOperator1doubleHash) {
  Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11.77);
  Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11.77);

  CHECK_EQ(op1a.HashCode(), op1b.HashCode());

  Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", -6.7);
  Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", -6.8);

  CHECK_NE(op1a.HashCode(), op2a.HashCode());
  CHECK_NE(op2a.HashCode(), op2b.HashCode());
}

TEST(TestOperator1doubleEquals) {
  Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11.77);
  Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11.77);

  CHECK(op1a.Equals(&op1a));
  CHECK(op1a.Equals(&op1b));
  CHECK(op1b.Equals(&op1a));
  CHECK(op1b.Equals(&op1b));

  Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3.1);
  Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Im", 3.2);

  CHECK(op2a.Equals(&op2a));
  CHECK(!op2a.Equals(&op2b));
  CHECK(!op2b.Equals(&op2a));
  CHECK(op2b.Equals(&op2b));

  CHECK(!op1a.Equals(&op2a));
  CHECK(!op1a.Equals(&op2b));
  CHECK(!op1b.Equals(&op2a));
  CHECK(!op1b.Equals(&op2b));

  CHECK(!op2a.Equals(&op1a));
  CHECK(!op2a.Equals(&op1b));
  CHECK(!op2b.Equals(&op1a));
  CHECK(!op2b.Equals(&op1b));

  SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");

  CHECK(!op1a.Equals(&op3));
  CHECK(!op1b.Equals(&op3));
  CHECK(!op2a.Equals(&op3));
  CHECK(!op2b.Equals(&op3));

  CHECK(!op3.Equals(&op1a));
  CHECK(!op3.Equals(&op1b));
  CHECK(!op3.Equals(&op2a));
  CHECK(!op3.Equals(&op2b));

  Operator1<double> op4a(24, Operator::kNoProperties, 0, 0, "Bashful", NaN);
  Operator1<double> op4b(24, Operator::kNoProperties, 0, 0, "Bashful", NaN);

  CHECK(op4a.Equals(&op4a));
  CHECK(op4a.Equals(&op4b));
  CHECK(op4b.Equals(&op4a));
  CHECK(op4b.Equals(&op4b));

  CHECK(!op3.Equals(&op4a));
  CHECK(!op3.Equals(&op4b));
  CHECK(!op3.Equals(&op4a));
  CHECK(!op3.Equals(&op4b));
}
<|endoftext|>