<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 state.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2014
 * State test functions.
 */

#include <boost/filesystem/operations.hpp>
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h>
#include <libevm/VM.h>
#include "TestHelper.h"

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

namespace dev {  namespace test {

void doStateTests(json_spirit::mValue& v, bool _fillin)
{
	processCommandLineOptions();

	for (auto& i: v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

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

		ImportTest importer(o, _fillin);

		State theState = importer.m_statePre;
		bytes tx = importer.m_transaction.rlp();
		bytes output;

		try
		{
			theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
		}
		catch (Exception const& _e)
		{
			cnote << "state execution did throw an exception: " << diagnostic_information(_e);
		}
		catch (std::exception const& _e)
		{
			cnote << "state execution did throw an exception: " << _e.what();
		}

		if (_fillin)
		{
#if ETH_FATDB
			importer.exportTest(output, theState);
#else
			BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
#endif
		}
		else
		{
			BOOST_REQUIRE(o.count("post") > 0);
			BOOST_REQUIRE(o.count("out") > 0);

			// check output
			checkOutput(output, o);

			// check logs
			checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);

			// check addresses
#if ETH_FATDB
			auto expectedAddrs = importer.m_statePost.addresses();
			auto resultAddrs = theState.addresses();
			for (auto& expectedPair : expectedAddrs)
			{
				auto& expectedAddr = expectedPair.first;
				auto resultAddrIt = resultAddrs.find(expectedAddr);
				if (resultAddrIt == resultAddrs.end())
					BOOST_ERROR("Missing expected address " << expectedAddr);
				else
				{
					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");

					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
				}
			}
			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs);
#endif
			BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root");
		}
	}
}
} }// Namespace Close

BOOST_AUTO_TEST_SUITE(StateTests)

BOOST_AUTO_TEST_CASE(stExample)
{
	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSystemOperationsTest)
{
	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
{
	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stLogTests)
{
	dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRecursiveCreate)
{
	dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stInitCodeTest)
{
	dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stTransactionTest)
{
	dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSpecialTest)
{
	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRefundTest)
{
	dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stBlockHashTest)
{
	dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest)
{
	   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 == "--quadratic" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);

					   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(stMemoryStressTest)
{
	   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 == "--memory" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);

					   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(stSolidityTest)
 {
		dev::test::executeTests("stSolidityTest", "/StateTests", dev::test::doStateTests);
 }

BOOST_AUTO_TEST_CASE(stMemoryTest)
{
	   dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stCreateTest)
{
	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::doStateTests(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 state test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFileState)
{
	dev::test::userDefinedTest("--statetest", dev::test::doStateTests);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>only check rootHash of state if FATDB is off<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 state.cpp
 * @author Christoph Jentzsch <cj@ethdev.com>
 * @date 2014
 * State test functions.
 */

#include <boost/filesystem/operations.hpp>
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h>
#include <libethereum/State.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Defaults.h>
#include <libevm/VM.h>
#include "TestHelper.h"

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

namespace dev {  namespace test {

void doStateTests(json_spirit::mValue& v, bool _fillin)
{
	processCommandLineOptions();

	for (auto& i: v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

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

		ImportTest importer(o, _fillin);

		State theState = importer.m_statePre;
		bytes tx = importer.m_transaction.rlp();
		bytes output;

		try
		{
			theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
		}
		catch (Exception const& _e)
		{
			cnote << "state execution did throw an exception: " << diagnostic_information(_e);
		}
		catch (std::exception const& _e)
		{
			cnote << "state execution did throw an exception: " << _e.what();
		}

		if (_fillin)
		{
#if ETH_FATDB
			importer.exportTest(output, theState);
#else
			BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off"));
#endif
		}
		else
		{
			BOOST_REQUIRE(o.count("post") > 0);
			BOOST_REQUIRE(o.count("out") > 0);

			// check output
			checkOutput(output, o);

			// check logs
			checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);

			// check addresses
#if ETH_FATDB
			cout << "fatDB is defined\n";
			auto expectedAddrs = importer.m_statePost.addresses();
			auto resultAddrs = theState.addresses();
			for (auto& expectedPair : expectedAddrs)
			{
				auto& expectedAddr = expectedPair.first;
				auto resultAddrIt = resultAddrs.find(expectedAddr);
				if (resultAddrIt == resultAddrs.end())
					BOOST_ERROR("Missing expected address " << expectedAddr);
				else
				{
					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");

					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
				}
			}
			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs);
#endif
			BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root");
		}
	}
}
} }// Namespace Close

BOOST_AUTO_TEST_SUITE(StateTests)

BOOST_AUTO_TEST_CASE(stExample)
{
	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSystemOperationsTest)
{
	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stPreCompiledContracts)
{
	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stLogTests)
{
	dev::test::executeTests("stLogTests", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRecursiveCreate)
{
	dev::test::executeTests("stRecursiveCreate", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stInitCodeTest)
{
	dev::test::executeTests("stInitCodeTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stTransactionTest)
{
	dev::test::executeTests("stTransactionTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stSpecialTest)
{
	dev::test::executeTests("stSpecialTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stRefundTest)
{
	dev::test::executeTests("stRefundTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stBlockHashTest)
{
	dev::test::executeTests("stBlockHashTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stQuadraticComplexityTest)
{
	   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 == "--quadratic" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stQuadraticComplexityTest", "/StateTests", dev::test::doStateTests);

					   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(stMemoryStressTest)
{
	   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 == "--memory" || arg == "--all")
			   {
					   auto start = chrono::steady_clock::now();

					   dev::test::executeTests("stMemoryStressTest", "/StateTests", dev::test::doStateTests);

					   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(stSolidityTest)
 {
		dev::test::executeTests("stSolidityTest", "/StateTests", dev::test::doStateTests);
 }

BOOST_AUTO_TEST_CASE(stMemoryTest)
{
	   dev::test::executeTests("stMemoryTest", "/StateTests", dev::test::doStateTests);
}

BOOST_AUTO_TEST_CASE(stCreateTest)
{
	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::doStateTests(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 state test with Exception: " << diagnostic_information(_e));
			}
			catch (std::exception const& _e)
			{
				BOOST_ERROR("Failed state test with Exception: " << _e.what());
			}
		}
	}
}

BOOST_AUTO_TEST_CASE(userDefinedFileState)
{
	dev::test::userDefinedTest("--statetest", dev::test::doStateTests);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
 * Copyright 2013-2014 Michael M. Magruder (https://github.com/mikemag)
 *
 * 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 <cmath>
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
#include <set>
#include <boost/optional/optional.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <sys/stat.h>

#include "machine.h"
#include "point.h"
#include "paths.h"
#include "shapes.h"
#include "gcode-writer.h"
#include "overview-writer.h"
#include "MonkeyCAMConfig.h"

using std::string;
using std::vector;
using std::set;

namespace MonkeyCAM {

// @TODO: load more parts
std::unique_ptr<ShapeEndPart> loadEndPart(boost::property_tree::ptree& config) {
  auto type = config.get<std::string>("type");
  assert(type == "Basic Bezier" || type == "Flat");
  if (type == "Basic Bezier") {
    auto endHandle = config.get<double>("end handle");
    auto transitionHandle = config.get<double>("transition handle");

    return std::unique_ptr<ShapeEndPart> {
      new BasicBezier { endHandle, transitionHandle } };
  }
  else if (type == "Flat") {
    auto flatWidth = config.get<double>("flat width");
    auto endHandle = config.get<double>("end handle");
    auto transitionHandle = config.get<double>("transition handle");

    return std::unique_ptr<ShapeEndPart> {
      new FlatBezier {flatWidth, endHandle, transitionHandle } };
  }
  __builtin_unreachable();
}

// @TODO: load more parts
std::unique_ptr<ShapeEdgePart> loadEdgePart(
  boost::property_tree::ptree& config)
{
  auto type = config.get<std::string>("type");
  assert(type == "Basic Arc");
  return std::unique_ptr<ShapeEdgePart> { new BasicArc };
}

std::unique_ptr<InsertPack> loadInserts(boost::property_tree::ptree& config) {
  auto countNose = config.get<int>("count nose");
  auto countTail = config.get<int>("count tail");
  auto offset = config.get<double>("offset", 4);
  auto hSpacing = config.get<double>("horizontal spacing", 4);
  auto vSpacing = config.get<double>("vertical spacing", 4);
  return std::unique_ptr<InsertPack> {
    new SnowboardInsertPack { countNose, countTail, offset,
        hSpacing, vSpacing } };
}

std::unique_ptr<BoardShape> loadBoard(boost::property_tree::ptree& config) {
  auto name = config.get<std::string>("board.name");
  auto noseLength = config.get<double>("board.nose length");
  auto eeLength = config.get<double>("board.effective edge length");
  auto tailLength = config.get<double>("board.tail length");
  auto sidecutRadius = config.get<double>("board.sidecut radius");
  auto waistWidth = config.get<double>("board.waist width");
  auto taper = config.get<double>("board.taper");
  auto nose = loadEndPart(config.get_child("board.nose shape"));
  auto edge = loadEdgePart(config.get_child("board.edge shape"));
  auto tail = loadEndPart(config.get_child("board.tail shape"));
  auto spacerWidth = config.get<double>("board.nose and tail spacer width");

  boost::optional<MCFixed> refStance(
    config.get_optional<double>("board.reference stance width"));
  boost::optional<MCFixed> setback(
    config.get_optional<double>("board.stance setback"));
  auto npc = config.get_child_optional("board.nose insert pack");
  std::unique_ptr<InsertPack> nosePack;
  if (npc) {
    nosePack = loadInserts(npc.get());
  }
  std::unique_ptr<InsertPack> tailPack;
  auto tpc = config.get_child_optional("board.tail insert pack");
  if (tpc) {
    tailPack = loadInserts(tpc.get());
  }

  boost::optional<MCFixed> noseEdgeExt(
    config.get_optional<double>("board.nose edge extension"));
  boost::optional<MCFixed> tailEdgeExt(
    config.get_optional<double>("board.tail edge extension"));

  return std::unique_ptr<BoardShape> {
    new BoardShape { name, noseLength, eeLength, tailLength, sidecutRadius,
        waistWidth, taper, nose, edge, tail, refStance, setback,
        nosePack, tailPack, spacerWidth, noseEdgeExt, tailEdgeExt } };
}

BoardProfile::End loadProfileEnd(boost::property_tree::ptree& config) {
  auto taperStart = config.get<double>("taper start");
  auto pullStart = config.get<double>("start handle");
  auto pullEnd = config.get<double>("end handle");
  auto taperEnd = config.get<double>("taper end");
  return BoardProfile::End { taperStart, pullStart, pullEnd, taperEnd };
}

BoardProfile loadProfile(boost::property_tree::ptree& config,
                         BoardShape& shape) {
  auto noseThickness = config.get<double>("profile.nose thickness");
  auto centerThickness = config.get<double>("profile.center thickness");
  auto tailThickness = config.get<double>("profile.tail thickness");
  auto noseEnd = loadProfileEnd(config.get_child("profile.nose taper"));
  auto tailEnd = loadProfileEnd(config.get_child("profile.tail taper"));

  BoardProfile profile { noseThickness, centerThickness, tailThickness,
      noseEnd, tailEnd, shape };
  return profile;
}

} // namespace MonkeyCAM

void usage(const char* program) {
  printf("\nUsage: %s --board brd.json --machine mach.json --binding bnd.json "
         "[--outdir <existing dir>]\n\n",
         program);
}

void generateOverview(MonkeyCAM::OverviewWriter& overview,
                      MonkeyCAM::BoardShape& shape,
                      MonkeyCAM::BoardProfile& profile) {
  overview.addRaw(R"(
)"
                  R"(This data is provided on an "AS IS" BASIS WITHOUT )"
                  "WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
                  "implied. You should inspect this very carefully and "
                  "recgonize that these overviews are not 100% accurate "
                  "representations of the generated G-Code programs. "
                  "YOU ARE RESPONSIBLE FOR ENSURING THOSE PROGRAMS WILL NOT "
                  "DAMAGE YOUR MACHINE OR MATERIALS.
");
  overview.addFormatted(R"(
%s
)",
                        shape.name().c_str());
  time_t rawtime;
  time(&rawtime);
  struct tm* timeinfo = localtime(&rawtime);
  char timebuff[80];
  strftime(timebuff, sizeof(timebuff), "%Y-%m-%d %X %Z", timeinfo);
  overview.addFormatted(R"(
Generated by )"
                        R"()"
                        R"(MonkeyCAM v%d.%d.%d at %s
)",
                        MonkeyCAM_VERSION_MAJOR,
                        MonkeyCAM_VERSION_MINOR,
                        MonkeyCAM_VERSION_PATCH,
                        timebuff);
  overview.addFormatted(
    "
This is an overview of board %s, showing details of the overall shape, "
    "major dimensions, and diagrams of the primary G-Code paths against "
    "various reference shapes.
",
    shape.name().c_str());
  overview.addRaw(
    "
Every file generated by MonkeyCAM, including this one, is "
    "self-contained and does not rely on any other files generated or included "
    "within the MonkeyCAM distribution. Thus you can copy it wherever you'd "
    "like, send it to your friends, etc.
");
  overview.addRaw(
    "
This overview is designed for you to zoom into it using your favorite "
    "browser. All of the diagrams are built with vector graphics and will "
    "scale perfectly. Zoom in to get a good look at the details, how shapes "
    "fit together, and where they fall on the reference grid. In Chrome: "
    "&#8984+/&#8984- (or Ctrl+/Ctrl- for Windows).
");

  vector<const MonkeyCAM::DebugPathSet*> sets;
  for (auto pathSet : shape.debugPathSets()) {
    sets.push_back(pathSet);
    if (pathSet->header() == "Core shape") {
      sets.push_back(&profile.debugPathSet());
    }
  }

  overview.addRaw("
Contents

");
  for (auto pathSet : sets) {
    overview.addFormatted("
%s
",
                          pathSet->headerLink().c_str(),
                          pathSet->header().c_str());
  }
  overview.addRaw("
<a href=\"#Configuration\"Configuration
");
  overview.addRaw("
");

  int dw = std::ceil(shape.overallLength().dbl());
  int dh = std::ceil(shape.maxWidth().dbl());

  auto renderPathSet = [&](const MonkeyCAM::DebugPathSet& pathSet) {
    overview.addHeader(pathSet.header(), pathSet.headerLink());
    for (auto& desc : pathSet.descriptions()) {
      overview.addRaw(desc.c_str());
    }
    overview.addRaw("
");
    set<string> seenDescs;
    auto descFormatter = [&](const MonkeyCAM::DebugAnnotationDesc& desc) {
      if (desc.name() != "" && seenDescs.find(desc.name()) == seenDescs.end()) {
        overview.addFormatted(
          R"(
%s (%s)

%s
)",
          desc.name().c_str(),
          desc.color().c_str(),
          desc.color().c_str(),
          desc.desc().c_str());
        seenDescs.insert(desc.name());
      }
    };
    for (auto& path : pathSet.paths()) {
      descFormatter(path.desc());
    }
    for (auto& a : pathSet.annotations()) {
      descFormatter(a.desc());
    }
    overview.addRaw("
");
    overview.startDrawing(dw, dh);
    for (auto& path : pathSet.paths()) {
      overview.addPath(path, path.desc().color(), path.desc().dashed());
    }
    for (auto& annotation : pathSet.annotations()) {
      overview.addAnnotation(annotation);
    }
    overview.endDrawing();
  };

  for (auto pathSet : sets) {
    renderPathSet(*pathSet);
  }
}

int main(int argc, char *argv[]) {
  printf("MonkeyCAM v%d.%d.%d, Copyright (C) 2013-2014 Michael M. Magruder\n",
         MonkeyCAM_VERSION_MAJOR,
         MonkeyCAM_VERSION_MINOR,
         MonkeyCAM_VERSION_PATCH);
  printf("This is free software; see the source for license information. There "
         "is\nNO warranty; not even for MERCHANTABILITY or FITNESS FOR A "
         "PARTICULAR PURPOSE.\n");
  printf("\n");

  string boardDef = "";
  string machineDef = "";
  string outdir = "";
  for (int i = 1; i < argc; ++i) {
    if ((string(argv[i]) == "--board") && (i + 1 < argc)) {
      boardDef = string(argv[++i]);
    } else if ((string(argv[i]) == "--machine") && (i + 1 < argc)) {
      machineDef = string(argv[++i]);
    } else if ((string(argv[i]) == "--binding") && (i + 1 < argc)) {
      bindingDef = string(argv[++i]);
    } else if ((string(argv[i]) == "--outdir") && (i + 1 < argc)) {
      outdir = string(argv[++i]);
    }
  }
  if (boardDef == "") {
    printf("Missing required board definition file\n");
    usage(argv[0]);
    return 1;
  }
  if (machineDef == "") {
    printf("Missing required machine definition file\n");
    usage(argv[0]);
    return 1;
  }
  // REG_TODO ADD SOMETHING HERE TO DEAL WITH SITUATION WHEN BINDING DEF IS NOT SUPPLIED?
  if (outdir == "") {
    outdir = ".";
  }
  struct stat stats;
  if ((stat(outdir.c_str(), &stats) != 0) || !S_ISDIR(stats.st_mode)) {
    printf("Output directory '%s' does not exist, please create it first.\n",
           outdir.c_str());
    return 1;
  }
#ifndef __MINGW32__
  if (outdir[outdir.size() - 1] != '/') {
    outdir += '/';
  }
#else
  if (outdir[outdir.size() - 1] != '\\') {
    outdir += '\\';
  }
#endif
  printf("Using board '%s', machine '%s'\n",
         boardDef.c_str(), machineDef.c_str());
  // REG_TODO Modify this to output binding def as well - need it to be optional though...

  boost::property_tree::ptree machineConfig;
  read_json(machineDef, machineConfig);
  boost::property_tree::ptree boardConfig;
  read_json(boardDef, boardConfig);

  printf("Building board shapes...\n");
  const MonkeyCAM::Machine machine { machineConfig };
  auto shape = MonkeyCAM::loadBoard(boardConfig);
  auto profile = MonkeyCAM::loadProfile(boardConfig, *shape);

  printf("Generating G-code programs to '%s'...\n", outdir.c_str());
  // Force the overall and core shapes to generate first, so they are
  // first in the overview.
  shape->buildCorePath(machine);
  shape->generateTopProfile(machine, profile).write(outdir);
  shape->generateEdgeTrench(machine).write(outdir);
  shape->generateCoreEdgeGroove(machine).write(outdir);
  shape->generateNoseTailSpacerCutout(machine).write(outdir);
  shape->generateGuideHoles(machine).write(outdir);
  shape->generateCoreAlignmentMarks(machine).write(outdir);
  shape->generateBaseCutout(machine).write(outdir);
  shape->generateInsertHoles(machine).write(outdir);
  shape->generateTopCutout(machine).write(outdir);

  string overviewName = shape->name() + "-overview.html";
  printf("Generating HTML overview %s%s\n",
         outdir.c_str(), overviewName.c_str());
  MonkeyCAM::OverviewWriter overview(outdir + overviewName, shape->name());
  generateOverview(overview, *shape, profile);
  overview.addHeader("Configuration");
  overview.addRaw("
The configuration used to generate this overview is "
                  "echoed here to ensure it can always be regenerated later. "
                  "Note this is MonkeyCAM's interpretation of the files, "
                  "not the raw files.
");
  auto configLink = "https://github.com/mikemag/MonkeyCAM/blob/master/docs/Configuration_Guide.md";
  overview.addFormatted(
    R"(
Board configuration file "%s":
)",
    configLink, boardDef.c_str());
  overview.addCode([&](std::ofstream& s) {
      write_json(s, boardConfig);
    });
  overview.addFormatted(
    R"(
Machine configuration file "%s":
)",
    configLink, machineDef.c_str());
  overview.addCode([&](std::ofstream& s) {
      write_json(s, machineConfig);
    });

  printf("Done.\n");
  return 0;
}
<commit_msg>working no bindingdef<commit_after>/*
 * Copyright 2013-2014 Michael M. Magruder (https://github.com/mikemag)
 *
 * 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 <cmath>
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
#include <set>
#include <boost/optional/optional.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <sys/stat.h>

#include "machine.h"
#include "point.h"
#include "paths.h"
#include "shapes.h"
#include "gcode-writer.h"
#include "overview-writer.h"
#include "MonkeyCAMConfig.h"

using std::string;
using std::vector;
using std::set;

namespace MonkeyCAM {

// @TODO: load more parts
std::unique_ptr<ShapeEndPart> loadEndPart(boost::property_tree::ptree& config) {
  auto type = config.get<std::string>("type");
  assert(type == "Basic Bezier" || type == "Flat");
  if (type == "Basic Bezier") {
    auto endHandle = config.get<double>("end handle");
    auto transitionHandle = config.get<double>("transition handle");

    return std::unique_ptr<ShapeEndPart> {
      new BasicBezier { endHandle, transitionHandle } };
  }
  else if (type == "Flat") {
    auto flatWidth = config.get<double>("flat width");
    auto endHandle = config.get<double>("end handle");
    auto transitionHandle = config.get<double>("transition handle");

    return std::unique_ptr<ShapeEndPart> {
      new FlatBezier {flatWidth, endHandle, transitionHandle } };
  }
  __builtin_unreachable();
}

// @TODO: load more parts
std::unique_ptr<ShapeEdgePart> loadEdgePart(
  boost::property_tree::ptree& config)
{
  auto type = config.get<std::string>("type");
  assert(type == "Basic Arc");
  return std::unique_ptr<ShapeEdgePart> { new BasicArc };
}

std::unique_ptr<InsertPack> loadInserts(boost::property_tree::ptree& config) {
  auto countNose = config.get<int>("count nose");
  auto countTail = config.get<int>("count tail");
  auto offset = config.get<double>("offset", 4);
  auto hSpacing = config.get<double>("horizontal spacing", 4);
  auto vSpacing = config.get<double>("vertical spacing", 4);
  return std::unique_ptr<InsertPack> {
    new SnowboardInsertPack { countNose, countTail, offset,
        hSpacing, vSpacing } };
}

std::unique_ptr<BoardShape> loadBoard(boost::property_tree::ptree& config) {
  auto name = config.get<std::string>("board.name");
  auto noseLength = config.get<double>("board.nose length");
  auto eeLength = config.get<double>("board.effective edge length");
  auto tailLength = config.get<double>("board.tail length");
  auto sidecutRadius = config.get<double>("board.sidecut radius");
  auto waistWidth = config.get<double>("board.waist width");
  auto taper = config.get<double>("board.taper");
  auto nose = loadEndPart(config.get_child("board.nose shape"));
  auto edge = loadEdgePart(config.get_child("board.edge shape"));
  auto tail = loadEndPart(config.get_child("board.tail shape"));
  auto spacerWidth = config.get<double>("board.nose and tail spacer width");

  boost::optional<MCFixed> refStance(
    config.get_optional<double>("board.reference stance width"));
  boost::optional<MCFixed> setback(
    config.get_optional<double>("board.stance setback"));
  auto npc = config.get_child_optional("board.nose insert pack");
  std::unique_ptr<InsertPack> nosePack;
  if (npc) {
    nosePack = loadInserts(npc.get());
  }
  std::unique_ptr<InsertPack> tailPack;
  auto tpc = config.get_child_optional("board.tail insert pack");
  if (tpc) {
    tailPack = loadInserts(tpc.get());
  }

  boost::optional<MCFixed> noseEdgeExt(
    config.get_optional<double>("board.nose edge extension"));
  boost::optional<MCFixed> tailEdgeExt(
    config.get_optional<double>("board.tail edge extension"));

  return std::unique_ptr<BoardShape> {
    new BoardShape { name, noseLength, eeLength, tailLength, sidecutRadius,
        waistWidth, taper, nose, edge, tail, refStance, setback,
        nosePack, tailPack, spacerWidth, noseEdgeExt, tailEdgeExt } };
}

BoardProfile::End loadProfileEnd(boost::property_tree::ptree& config) {
  auto taperStart = config.get<double>("taper start");
  auto pullStart = config.get<double>("start handle");
  auto pullEnd = config.get<double>("end handle");
  auto taperEnd = config.get<double>("taper end");
  return BoardProfile::End { taperStart, pullStart, pullEnd, taperEnd };
}

BoardProfile loadProfile(boost::property_tree::ptree& config,
                         BoardShape& shape) {
  auto noseThickness = config.get<double>("profile.nose thickness");
  auto centerThickness = config.get<double>("profile.center thickness");
  auto tailThickness = config.get<double>("profile.tail thickness");
  auto noseEnd = loadProfileEnd(config.get_child("profile.nose taper"));
  auto tailEnd = loadProfileEnd(config.get_child("profile.tail taper"));

  BoardProfile profile { noseThickness, centerThickness, tailThickness,
      noseEnd, tailEnd, shape };
  return profile;
}

} // namespace MonkeyCAM

void usage(const char* program) {
  printf("\nUsage: %s --board brd.json --machine mach.json --binding bnd.json "
         "[--outdir <existing dir>]\n\n",
         program);
}

void generateOverview(MonkeyCAM::OverviewWriter& overview,
                      MonkeyCAM::BoardShape& shape,
                      MonkeyCAM::BoardProfile& profile) {
  overview.addRaw(R"(
)"
                  R"(This data is provided on an "AS IS" BASIS WITHOUT )"
                  "WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
                  "implied. You should inspect this very carefully and "
                  "recgonize that these overviews are not 100% accurate "
                  "representations of the generated G-Code programs. "
                  "YOU ARE RESPONSIBLE FOR ENSURING THOSE PROGRAMS WILL NOT "
                  "DAMAGE YOUR MACHINE OR MATERIALS.
");
  overview.addFormatted(R"(
%s
)",
                        shape.name().c_str());
  time_t rawtime;
  time(&rawtime);
  struct tm* timeinfo = localtime(&rawtime);
  char timebuff[80];
  strftime(timebuff, sizeof(timebuff), "%Y-%m-%d %X %Z", timeinfo);
  overview.addFormatted(R"(
Generated by )"
                        R"()"
                        R"(MonkeyCAM v%d.%d.%d at %s
)",
                        MonkeyCAM_VERSION_MAJOR,
                        MonkeyCAM_VERSION_MINOR,
                        MonkeyCAM_VERSION_PATCH,
                        timebuff);
  overview.addFormatted(
    "
This is an overview of board %s, showing details of the overall shape, "
    "major dimensions, and diagrams of the primary G-Code paths against "
    "various reference shapes.
",
    shape.name().c_str());
  overview.addRaw(
    "
Every file generated by MonkeyCAM, including this one, is "
    "self-contained and does not rely on any other files generated or included "
    "within the MonkeyCAM distribution. Thus you can copy it wherever you'd "
    "like, send it to your friends, etc.
");
  overview.addRaw(
    "
This overview is designed for you to zoom into it using your favorite "
    "browser. All of the diagrams are built with vector graphics and will "
    "scale perfectly. Zoom in to get a good look at the details, how shapes "
    "fit together, and where they fall on the reference grid. In Chrome: "
    "&#8984+/&#8984- (or Ctrl+/Ctrl- for Windows).
");

  vector<const MonkeyCAM::DebugPathSet*> sets;
  for (auto pathSet : shape.debugPathSets()) {
    sets.push_back(pathSet);
    if (pathSet->header() == "Core shape") {
      sets.push_back(&profile.debugPathSet());
    }
  }

  overview.addRaw("
Contents

");
  for (auto pathSet : sets) {
    overview.addFormatted("
%s
",
                          pathSet->headerLink().c_str(),
                          pathSet->header().c_str());
  }
  overview.addRaw("
<a href=\"#Configuration\"Configuration
");
  overview.addRaw("
");

  int dw = std::ceil(shape.overallLength().dbl());
  int dh = std::ceil(shape.maxWidth().dbl());

  auto renderPathSet = [&](const MonkeyCAM::DebugPathSet& pathSet) {
    overview.addHeader(pathSet.header(), pathSet.headerLink());
    for (auto& desc : pathSet.descriptions()) {
      overview.addRaw(desc.c_str());
    }
    overview.addRaw("
");
    set<string> seenDescs;
    auto descFormatter = [&](const MonkeyCAM::DebugAnnotationDesc& desc) {
      if (desc.name() != "" && seenDescs.find(desc.name()) == seenDescs.end()) {
        overview.addFormatted(
          R"(
%s (%s)

%s
)",
          desc.name().c_str(),
          desc.color().c_str(),
          desc.color().c_str(),
          desc.desc().c_str());
        seenDescs.insert(desc.name());
      }
    };
    for (auto& path : pathSet.paths()) {
      descFormatter(path.desc());
    }
    for (auto& a : pathSet.annotations()) {
      descFormatter(a.desc());
    }
    overview.addRaw("
");
    overview.startDrawing(dw, dh);
    for (auto& path : pathSet.paths()) {
      overview.addPath(path, path.desc().color(), path.desc().dashed());
    }
    for (auto& annotation : pathSet.annotations()) {
      overview.addAnnotation(annotation);
    }
    overview.endDrawing();
  };

  for (auto pathSet : sets) {
    renderPathSet(*pathSet);
  }
}

int main(int argc, char *argv[]) {
  printf("MonkeyCAM v%d.%d.%d, Copyright (C) 2013-2014 Michael M. Magruder\n",
         MonkeyCAM_VERSION_MAJOR,
         MonkeyCAM_VERSION_MINOR,
         MonkeyCAM_VERSION_PATCH);
  printf("This is free software; see the source for license information. There "
         "is\nNO warranty; not even for MERCHANTABILITY or FITNESS FOR A "
         "PARTICULAR PURPOSE.\n");
  printf("\n");

  string boardDef = "";
  string machineDef = "";
  string bindingDef = "";
  string outdir = "";
  for (int i = 1; i < argc; ++i) {
    if ((string(argv[i]) == "--board") && (i + 1 < argc)) {
      boardDef = string(argv[++i]);
    } else if ((string(argv[i]) == "--machine") && (i + 1 < argc)) {
      machineDef = string(argv[++i]);
    } else if ((string(argv[i]) == "--binding") && (i + 1 < argc)) {
      bindingDef = string(argv[++i]);
    } else if ((string(argv[i]) == "--outdir") && (i + 1 < argc)) {
      outdir = string(argv[++i]);
    }
  }
  if (boardDef == "") {
    printf("Missing required board definition file\n");
    usage(argv[0]);
    return 1;
  }
  if (machineDef == "") {
    printf("Missing required machine definition file\n");
    usage(argv[0]);
    return 1;
  }
  // REG_TODO ADD SOMETHING HERE TO DEAL WITH SITUATION WHEN BINDING DEF IS NOT SUPPLIED?
  if (outdir == "") {
    outdir = ".";
  }
  struct stat stats;
  if ((stat(outdir.c_str(), &stats) != 0) || !S_ISDIR(stats.st_mode)) {
    printf("Output directory '%s' does not exist, please create it first.\n",
           outdir.c_str());
    return 1;
  }
#ifndef __MINGW32__
  if (outdir[outdir.size() - 1] != '/') {
    outdir += '/';
  }
#else
  if (outdir[outdir.size() - 1] != '\\') {
    outdir += '\\';
  }
#endif
  printf("Using board '%s', machine '%s'\n",
         boardDef.c_str(), machineDef.c_str());
  // REG_TODO Modify this to output binding def as well - need it to be optional though...

  boost::property_tree::ptree machineConfig;
  read_json(machineDef, machineConfig);
  boost::property_tree::ptree boardConfig;
  read_json(boardDef, boardConfig);
  boost::property_tree::ptree bindingConfig;
  read_json(bindingDef, bindingConfig);

  printf("Building board shapes...\n");
  const MonkeyCAM::Machine machine { machineConfig };
  auto shape = MonkeyCAM::loadBoard(boardConfig);
  auto profile = MonkeyCAM::loadProfile(boardConfig, *shape);

  printf("Generating G-code programs to '%s'...\n", outdir.c_str());
  // Force the overall and core shapes to generate first, so they are
  // first in the overview.
  shape->buildCorePath(machine);
  shape->generateTopProfile(machine, profile).write(outdir);
  shape->generateEdgeTrench(machine).write(outdir);
  shape->generateCoreEdgeGroove(machine).write(outdir);
  shape->generateNoseTailSpacerCutout(machine).write(outdir);
  shape->generateGuideHoles(machine).write(outdir);
  shape->generateCoreAlignmentMarks(machine).write(outdir);
  shape->generateBaseCutout(machine).write(outdir);
  shape->generateInsertHoles(machine).write(outdir);
  shape->generateTopCutout(machine).write(outdir);

  string overviewName = shape->name() + "-overview.html";
  printf("Generating HTML overview %s%s\n",
         outdir.c_str(), overviewName.c_str());
  MonkeyCAM::OverviewWriter overview(outdir + overviewName, shape->name());
  generateOverview(overview, *shape, profile);
  overview.addHeader("Configuration");
  overview.addRaw("
The configuration used to generate this overview is "
                  "echoed here to ensure it can always be regenerated later. "
                  "Note this is MonkeyCAM's interpretation of the files, "
                  "not the raw files.
");
  auto configLink = "https://github.com/mikemag/MonkeyCAM/blob/master/docs/Configuration_Guide.md";
  overview.addFormatted(
    R"(
Board configuration file "%s":
)",
    configLink, boardDef.c_str());
  overview.addCode([&](std::ofstream& s) {
      write_json(s, boardConfig);
    });
  overview.addFormatted(
    R"(
Machine configuration file "%s":
)",
    configLink, machineDef.c_str());
  overview.addCode([&](std::ofstream& s) {
      write_json(s, machineConfig);
    });

  printf("Done.\n");
  return 0;
}
<|endoftext|>


<commit_before>#include <exodus/program.h>
programinit()

function main() {

	//init:
	var reqfile = COMMAND.a(2);
	var reqtext = COMMAND.a(3);
	var padding = COMMAND.a(4);

	if (not(reqfile or reqtext)) {
		errputl("syntax: dbgrep filename text");
		errputl("        dbgrep - text");
		//stop();
	}

	// get filenames
	var filenames = listfiles();
	var nfiles = filenames.dcount(FM);

	for (int filen = 1; filen <= nfiles; ++filen) {

		var filename = filenames.a(filen);

		if (filename.index("preselect") or filename.index("select_stage2"))
			continue;

		// filter by reqfilename. "-" means all files
		if (reqfile and reqfile ne "-" and filename ne reqfile.lcase())
			continue;

		// OPEN FILE or skip file
		var file;
		if (not(file.open(filename))) {
			errputl(filename.quote() ^ " file cannot be opened");
			continue;
		}

		file.select();

		var nresults = 1;
		var key;
		while (file.readnext(key)) {

			// get record or skip
			var data;
			if (not(data.read(file, key))) {
				//abort(key.quote()^" is missing from " ^ file.quote());
				continue;
			}

			if (reqtext and (not(data.lcase().index(reqtext.lcase())) or not(key.lcase().index(reqtext.lcase())))) {
				continue;
			}

			// padding & startpos used to contextualise found reqtext
			var startpos = data.index(reqtext);

			var leftcontext = data.substr(startpos - padding, padding);
			var rightcontext = data.substr(startpos + length(reqtext), padding);

			var context = leftcontext ^ "\033[1;31m" ^ reqtext ^ "\033[0m" ^ rightcontext;

			var(filename ^ " : " ^ key ^ " :: " ^ context).outputl();
		}
	}

	return 0;
}

programexit()
<commit_msg>improve dbgrep<commit_after>#include <exodus/program.h>
programinit()

function main() {

	//init:
	var reqfile = COMMAND.a(2);
	var reqtext = COMMAND.a(3);
	var padding = COMMAND.a(4);

	bool hasreqtext = reqtext.len();
	if (not hasreqtext) {
		errputl("syntax: dbgrep filename text");
		errputl("        dbgrep - text");
		//stop();
	}

	bool caseinsensitive = OPTIONS.index("I");
	if (caseinsensitive)
		reqtext.lcaser();

	if (not padding)
		padding = 256;

	var colored_reqtext=reqtext;
	if (TERMINAL)
				colored_reqtext = "\033[1;31m" ^ reqtext ^ "\033[0m";

	// get filenames
	var filenames = listfiles();

	for (var filename : filenames) {

		if (filename.index("preselect") or filename.index("select_stage2"))
			continue;

		// filter by reqfilename. "-" means all files
		if (reqfile and reqfile ne "-" and filename ne reqfile.lcase())
			continue;

		// OPEN FILE or skip file
		var file;
		if (not(file.open(filename))) {
			errputl(filename.quote() ^ " file cannot be opened");
			continue;
		}

		file.select("SELECT " ^ filename ^ " (SR)");

		var nresults = 1;
		while (file.readnext(RECORD, ID, MV)) {

			if (esctoexit())
				stop();

//			// get record or skip
//			var RECORD;
//			if (not(RECORD.read(file, ID))) {
//				//abort(ID.quote()^" is missing from " ^ file.quote());
//				continue;
//			}

			if (caseinsensitive) {
				RECORD.lcaser();
				ID.lcaser();
			}

			if (not RECORD.index(reqtext) and not ID.index(reqtext)) {
				continue;
			}

			// padding & startpos used to contextualise found reqtext
			var startpos = RECORD.index(reqtext);
			var startpos2 = startpos - padding;
			if (startpos2 < 1) {
				padding += startpos2;
				startpos = 1;
			}
			//var leftcontext = RECORD.substr(startpos - padding, padding).field2(FM, -1);
			var leftcontext = RECORD.substr(startpos2, padding).field2(FM, -1);
			var rightcontext = RECORD.substr(startpos + length(reqtext), padding).a(1);

			printl(filename, ID, leftcontext ^ colored_reqtext ^ rightcontext);
			//var(filename ^ " : " ^ ID ^ " :: " ^ context).outputl();
		}
	}

	return 0;
}

programexit()
<|endoftext|>


<commit_before>#include "AccelerometerTest.h"

AccelerometerTest::AccelerometerTest()
{
	Requires(chassis);
}

// Called just before this Command runs the first time
void AccelerometerTest::Initialize()
{
chassis->accelerometer->InitTable();

}

// Called repeatedly when this Command is scheduled to run
void AccelerometerTest::Execute()
{
xSpeed = chassis->accelerometer->GetX();
ySpeed = chassis->accelerometer->GetY();
}

// Make this return true when this Command no longer needs to run execute()
bool AccelerometerTest::IsFinished()
{

}

// Called once after isFinished returns true
void AccelerometerTest::End()
{

}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void AccelerometerTest::Interrupted()
{
	End();
}
<commit_msg>Deleted Table<commit_after>#include "AccelerometerTest.h"

AccelerometerTest::AccelerometerTest()
{
	Requires(chassis);
}

// Called just before this Command runs the first time
void AccelerometerTest::Initialize()
{

}

// Called repeatedly when this Command is scheduled to run
void AccelerometerTest::Execute()
{
xSpeed = chassis->accelerometer->GetX();
ySpeed = chassis->accelerometer->GetY();
}

// Make this return true when this Command no longer needs to run execute()
bool AccelerometerTest::IsFinished()
{
return false;
}

// Called once after isFinished returns true
void AccelerometerTest::End()
{

}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void AccelerometerTest::Interrupted()
{
	End();
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * 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.
 *is % allowed in string
 */

#include <memory>
#include <string>
#include <thread>
#include <utility>
#include <vector>

#include <gflags/gflags.h>
#include <grpc++/create_channel.h>
#include <grpc++/grpc++.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>

#include "src/proto/grpc/testing/metrics.grpc.pb.h"
#include "src/proto/grpc/testing/metrics.pb.h"
#include "test/cpp/interop/interop_client.h"
#include "test/cpp/interop/stress_interop_client.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/util/metrics_server.h"
#include "test/cpp/util/test_config.h"

extern "C" {
extern void gpr_default_log(gpr_log_func_args* args);
}

DEFINE_int32(metrics_port, 8081, "The metrics server port.");

DEFINE_int32(sleep_duration_ms, 0,
             "The duration (in millisec) between two"
             " consecutive test calls (per server) issued by the server.");

DEFINE_int32(test_duration_secs, -1,
             "The length of time (in seconds) to run"
             " the test. Enter -1 if the test should run continuously until"
             " forcefully terminated.");

DEFINE_string(server_addresses, "localhost:8080",
              "The list of server addresses. The format is: \n"
              " \"<name_1>:<port_1>,<name_2>:<port_1>...<name_N>:<port_N>\"\n"
              " Note: <name> can be servername or IP address.");

DEFINE_int32(num_channels_per_server, 1, "Number of channels for each server");

DEFINE_int32(num_stubs_per_channel, 1,
             "Number of stubs per each channels to server. This number also "
             "indicates the max number of parallel RPC calls on each channel "
             "at any given time.");

// TODO(sreek): Add more test cases here in future
DEFINE_string(test_cases, "",
              "List of test cases to call along with the"
              " relative weights in the following format:\n"
              " \"<testcase_1:w_1>,<testcase_2:w_2>...<testcase_n:w_n>\"\n"
              " The following testcases are currently supported:\n"
              "   empty_unary\n"
              "   large_unary\n"
              "   large_compressed_unary\n"
              "   client_streaming\n"
              "   server_streaming\n"
              "   server_compressed_streaming\n"
              "   slow_consumer\n"
              "   half_duplex\n"
              "   ping_pong\n"
              "   cancel_after_begin\n"
              "   cancel_after_first_response\n"
              "   timeout_on_sleeping_server\n"
              "   empty_stream\n"
              "   status_code_and_message\n"
              "   custom_metadata\n"
              " Example: \"empty_unary:20,large_unary:10,empty_stream:70\"\n"
              " The above will execute 'empty_unary', 20% of the time,"
              " 'large_unary', 10% of the time and 'empty_stream' the remaining"
              " 70% of the time");

DEFINE_int32(log_level, GPR_LOG_SEVERITY_INFO,
             "Severity level of messages that should be logged. Any messages "
             "greater than or equal to the level set here will be logged. "
             "The choices are: 0 (GPR_LOG_SEVERITY_DEBUG), 1 "
             "(GPR_LOG_SEVERITY_INFO) and 2 (GPR_LOG_SEVERITY_ERROR)");

DEFINE_bool(do_not_abort_on_transient_failures, true,
            "If set to 'true', abort() is not called in case of transient "
            "failures like temporary connection failures.");

// Options from client.cc (for compatibility with interop test).
// TODO(sreek): Consolidate overlapping options
DEFINE_bool(use_tls, false, "Whether to use tls.");
DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
DEFINE_string(server_host_override, "foo.test.google.fr",
              "Override the server host which is sent in HTTP header");

using grpc::testing::kTestCaseList;
using grpc::testing::MetricsService;
using grpc::testing::MetricsServiceImpl;
using grpc::testing::StressTestInteropClient;
using grpc::testing::TestCaseType;
using grpc::testing::UNKNOWN_TEST;
using grpc::testing::WeightedRandomTestSelector;

static int log_level = GPR_LOG_SEVERITY_DEBUG;

// A simple wrapper to grp_default_log() function. This only logs messages at or
// above the current log level (set in 'log_level' variable)
void TestLogFunction(gpr_log_func_args* args) {
  if (args->severity >= log_level) {
    gpr_default_log(args);
  }
}

TestCaseType GetTestTypeFromName(const grpc::string& test_name) {
  TestCaseType test_case = UNKNOWN_TEST;

  for (auto it = kTestCaseList.begin(); it != kTestCaseList.end(); it++) {
    if (test_name == it->second) {
      test_case = it->first;
      break;
    }
  }

  return test_case;
}

// Converts a string of comma delimited tokens to a vector of tokens
bool ParseCommaDelimitedString(const grpc::string& comma_delimited_str,
                               std::vector<grpc::string>& tokens) {
  size_t bpos = 0;
  size_t epos = grpc::string::npos;

  while ((epos = comma_delimited_str.find(',', bpos)) != grpc::string::npos) {
    tokens.emplace_back(comma_delimited_str.substr(bpos, epos - bpos));
    bpos = epos + 1;
  }

  tokens.emplace_back(comma_delimited_str.substr(bpos));  // Last token
  return true;
}

// Input: Test case string "<testcase_name:weight>,<testcase_name:weight>...."
// Output:
//   - Whether parsing was successful (return value)
//   - Vector of (test_type_enum, weight) pairs returned via 'tests' parameter
bool ParseTestCasesString(const grpc::string& test_cases,
                          std::vector<std::pair<TestCaseType, int>>& tests) {
  bool is_success = true;

  std::vector<grpc::string> tokens;
  ParseCommaDelimitedString(test_cases, tokens);

  for (auto it = tokens.begin(); it != tokens.end(); it++) {
    // Token is in the form <test_name>:<test_weight>
    size_t colon_pos = it->find(':');
    if (colon_pos == grpc::string::npos) {
      gpr_log(GPR_ERROR, "Error in parsing test case string: %s", it->c_str());
      is_success = false;
      break;
    }

    grpc::string test_name = it->substr(0, colon_pos);
    int weight = std::stoi(it->substr(colon_pos + 1));
    TestCaseType test_case = GetTestTypeFromName(test_name);
    if (test_case == UNKNOWN_TEST) {
      gpr_log(GPR_ERROR, "Unknown test case: %s", test_name.c_str());
      is_success = false;
      break;
    }

    tests.emplace_back(std::make_pair(test_case, weight));
  }

  return is_success;
}

// For debugging purposes
void LogParameterInfo(const std::vector<grpc::string>& addresses,
                      const std::vector<std::pair<TestCaseType, int>>& tests) {
  gpr_log(GPR_INFO, "server_addresses: %s", FLAGS_server_addresses.c_str());
  gpr_log(GPR_INFO, "test_cases : %s", FLAGS_test_cases.c_str());
  gpr_log(GPR_INFO, "sleep_duration_ms: %d", FLAGS_sleep_duration_ms);
  gpr_log(GPR_INFO, "test_duration_secs: %d", FLAGS_test_duration_secs);
  gpr_log(GPR_INFO, "num_channels_per_server: %d",
          FLAGS_num_channels_per_server);
  gpr_log(GPR_INFO, "num_stubs_per_channel: %d", FLAGS_num_stubs_per_channel);
  gpr_log(GPR_INFO, "log_level: %d", FLAGS_log_level);
  gpr_log(GPR_INFO, "do_not_abort_on_transient_failures: %s",
          FLAGS_do_not_abort_on_transient_failures ? "true" : "false");

  int num = 0;
  for (auto it = addresses.begin(); it != addresses.end(); it++) {
    gpr_log(GPR_INFO, "%d:%s", ++num, it->c_str());
  }

  num = 0;
  for (auto it = tests.begin(); it != tests.end(); it++) {
    TestCaseType test_case = it->first;
    int weight = it->second;
    gpr_log(GPR_INFO, "%d. TestCaseType: %d, Weight: %d", ++num, test_case,
            weight);
  }
}

int main(int argc, char** argv) {
  grpc::testing::InitTest(&argc, &argv, true);

  if (FLAGS_log_level > GPR_LOG_SEVERITY_ERROR ||
      FLAGS_log_level < GPR_LOG_SEVERITY_DEBUG) {
    gpr_log(GPR_ERROR, "log_level should be an integer between %d and %d",
            GPR_LOG_SEVERITY_DEBUG, GPR_LOG_SEVERITY_ERROR);
    return 1;
  }

  // Change the default log function to TestLogFunction which respects the
  // log_level setting.
  log_level = FLAGS_log_level;
  gpr_set_log_function(TestLogFunction);

  srand(time(NULL));

  // Parse the server addresses
  std::vector<grpc::string> server_addresses;
  ParseCommaDelimitedString(FLAGS_server_addresses, server_addresses);

  // Parse test cases and weights
  if (FLAGS_test_cases.length() == 0) {
    gpr_log(GPR_ERROR, "No test cases supplied");
    return 1;
  }

  std::vector<std::pair<TestCaseType, int>> tests;
  if (!ParseTestCasesString(FLAGS_test_cases, tests)) {
    gpr_log(GPR_ERROR, "Error in parsing test cases string %s ",
            FLAGS_test_cases.c_str());
    return 1;
  }

  LogParameterInfo(server_addresses, tests);

  WeightedRandomTestSelector test_selector(tests);
  MetricsServiceImpl metrics_service;

  gpr_log(GPR_INFO, "Starting test(s)..");

  std::vector<std::thread> test_threads;

  // Create and start the test threads.
  // Note that:
  // - Each server can have multiple channels (as configured by
  // FLAGS_num_channels_per_server).
  //
  // - Each channel can have multiple stubs (as configured by
  // FLAGS_num_stubs_per_channel). This is to test calling multiple RPCs in
  // parallel on the same channel.
  int thread_idx = 0;
  int server_idx = -1;
  char buffer[256];
  for (auto it = server_addresses.begin(); it != server_addresses.end(); it++) {
    ++server_idx;
    // Create channel(s) for each server
    for (int channel_idx = 0; channel_idx < FLAGS_num_channels_per_server;
         channel_idx++) {
      gpr_log(GPR_INFO, "Starting test with %s channel_idx=%d..", it->c_str(),
              channel_idx);
      std::shared_ptr<grpc::Channel> channel = grpc::CreateTestChannel(
          *it, FLAGS_server_host_override, FLAGS_use_tls, !FLAGS_use_test_ca);

      // Create stub(s) for each channel
      for (int stub_idx = 0; stub_idx < FLAGS_num_stubs_per_channel;
           stub_idx++) {
        StressTestInteropClient* client = new StressTestInteropClient(
            ++thread_idx, *it, channel, test_selector, FLAGS_test_duration_secs,
            FLAGS_sleep_duration_ms, FLAGS_do_not_abort_on_transient_failures);

        bool is_already_created = false;
        // QpsGauge name
        std::snprintf(buffer, sizeof(buffer),
                      "/stress_test/server_%d/channel_%d/stub_%d/qps",
                      server_idx, channel_idx, stub_idx);

        test_threads.emplace_back(std::thread(
            &StressTestInteropClient::MainLoop, client,
            metrics_service.CreateQpsGauge(buffer, &is_already_created)));

        // The QpsGauge should not have been already created
        GPR_ASSERT(!is_already_created);
      }
    }
  }

  // Start metrics server before waiting for the stress test threads
  std::unique_ptr<grpc::Server> metrics_server;
  if (FLAGS_metrics_port > 0) {
    metrics_server = metrics_service.StartServer(FLAGS_metrics_port);
  }

  // Wait for the stress test threads to complete
  for (auto it = test_threads.begin(); it != test_threads.end(); it++) {
    it->join();
  }

  return 0;
}
<commit_msg>Properly clean up stress test clients<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * 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.
 *is % allowed in string
 */

#include <memory>
#include <string>
#include <thread>
#include <utility>
#include <vector>

#include <gflags/gflags.h>
#include <grpc++/create_channel.h>
#include <grpc++/grpc++.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>

#include "src/proto/grpc/testing/metrics.grpc.pb.h"
#include "src/proto/grpc/testing/metrics.pb.h"
#include "test/cpp/interop/interop_client.h"
#include "test/cpp/interop/stress_interop_client.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/util/metrics_server.h"
#include "test/cpp/util/test_config.h"

extern "C" {
extern void gpr_default_log(gpr_log_func_args* args);
}

DEFINE_int32(metrics_port, 8081, "The metrics server port.");

DEFINE_int32(sleep_duration_ms, 0,
             "The duration (in millisec) between two"
             " consecutive test calls (per server) issued by the server.");

DEFINE_int32(test_duration_secs, -1,
             "The length of time (in seconds) to run"
             " the test. Enter -1 if the test should run continuously until"
             " forcefully terminated.");

DEFINE_string(server_addresses, "localhost:8080",
              "The list of server addresses. The format is: \n"
              " \"<name_1>:<port_1>,<name_2>:<port_1>...<name_N>:<port_N>\"\n"
              " Note: <name> can be servername or IP address.");

DEFINE_int32(num_channels_per_server, 1, "Number of channels for each server");

DEFINE_int32(num_stubs_per_channel, 1,
             "Number of stubs per each channels to server. This number also "
             "indicates the max number of parallel RPC calls on each channel "
             "at any given time.");

// TODO(sreek): Add more test cases here in future
DEFINE_string(test_cases, "",
              "List of test cases to call along with the"
              " relative weights in the following format:\n"
              " \"<testcase_1:w_1>,<testcase_2:w_2>...<testcase_n:w_n>\"\n"
              " The following testcases are currently supported:\n"
              "   empty_unary\n"
              "   large_unary\n"
              "   large_compressed_unary\n"
              "   client_streaming\n"
              "   server_streaming\n"
              "   server_compressed_streaming\n"
              "   slow_consumer\n"
              "   half_duplex\n"
              "   ping_pong\n"
              "   cancel_after_begin\n"
              "   cancel_after_first_response\n"
              "   timeout_on_sleeping_server\n"
              "   empty_stream\n"
              "   status_code_and_message\n"
              "   custom_metadata\n"
              " Example: \"empty_unary:20,large_unary:10,empty_stream:70\"\n"
              " The above will execute 'empty_unary', 20% of the time,"
              " 'large_unary', 10% of the time and 'empty_stream' the remaining"
              " 70% of the time");

DEFINE_int32(log_level, GPR_LOG_SEVERITY_INFO,
             "Severity level of messages that should be logged. Any messages "
             "greater than or equal to the level set here will be logged. "
             "The choices are: 0 (GPR_LOG_SEVERITY_DEBUG), 1 "
             "(GPR_LOG_SEVERITY_INFO) and 2 (GPR_LOG_SEVERITY_ERROR)");

DEFINE_bool(do_not_abort_on_transient_failures, true,
            "If set to 'true', abort() is not called in case of transient "
            "failures like temporary connection failures.");

// Options from client.cc (for compatibility with interop test).
// TODO(sreek): Consolidate overlapping options
DEFINE_bool(use_tls, false, "Whether to use tls.");
DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
DEFINE_string(server_host_override, "foo.test.google.fr",
              "Override the server host which is sent in HTTP header");

using grpc::testing::kTestCaseList;
using grpc::testing::MetricsService;
using grpc::testing::MetricsServiceImpl;
using grpc::testing::StressTestInteropClient;
using grpc::testing::TestCaseType;
using grpc::testing::UNKNOWN_TEST;
using grpc::testing::WeightedRandomTestSelector;

static int log_level = GPR_LOG_SEVERITY_DEBUG;

// A simple wrapper to grp_default_log() function. This only logs messages at or
// above the current log level (set in 'log_level' variable)
void TestLogFunction(gpr_log_func_args* args) {
  if (args->severity >= log_level) {
    gpr_default_log(args);
  }
}

TestCaseType GetTestTypeFromName(const grpc::string& test_name) {
  TestCaseType test_case = UNKNOWN_TEST;

  for (auto it = kTestCaseList.begin(); it != kTestCaseList.end(); it++) {
    if (test_name == it->second) {
      test_case = it->first;
      break;
    }
  }

  return test_case;
}

// Converts a string of comma delimited tokens to a vector of tokens
bool ParseCommaDelimitedString(const grpc::string& comma_delimited_str,
                               std::vector<grpc::string>& tokens) {
  size_t bpos = 0;
  size_t epos = grpc::string::npos;

  while ((epos = comma_delimited_str.find(',', bpos)) != grpc::string::npos) {
    tokens.emplace_back(comma_delimited_str.substr(bpos, epos - bpos));
    bpos = epos + 1;
  }

  tokens.emplace_back(comma_delimited_str.substr(bpos));  // Last token
  return true;
}

// Input: Test case string "<testcase_name:weight>,<testcase_name:weight>...."
// Output:
//   - Whether parsing was successful (return value)
//   - Vector of (test_type_enum, weight) pairs returned via 'tests' parameter
bool ParseTestCasesString(const grpc::string& test_cases,
                          std::vector<std::pair<TestCaseType, int>>& tests) {
  bool is_success = true;

  std::vector<grpc::string> tokens;
  ParseCommaDelimitedString(test_cases, tokens);

  for (auto it = tokens.begin(); it != tokens.end(); it++) {
    // Token is in the form <test_name>:<test_weight>
    size_t colon_pos = it->find(':');
    if (colon_pos == grpc::string::npos) {
      gpr_log(GPR_ERROR, "Error in parsing test case string: %s", it->c_str());
      is_success = false;
      break;
    }

    grpc::string test_name = it->substr(0, colon_pos);
    int weight = std::stoi(it->substr(colon_pos + 1));
    TestCaseType test_case = GetTestTypeFromName(test_name);
    if (test_case == UNKNOWN_TEST) {
      gpr_log(GPR_ERROR, "Unknown test case: %s", test_name.c_str());
      is_success = false;
      break;
    }

    tests.emplace_back(std::make_pair(test_case, weight));
  }

  return is_success;
}

// For debugging purposes
void LogParameterInfo(const std::vector<grpc::string>& addresses,
                      const std::vector<std::pair<TestCaseType, int>>& tests) {
  gpr_log(GPR_INFO, "server_addresses: %s", FLAGS_server_addresses.c_str());
  gpr_log(GPR_INFO, "test_cases : %s", FLAGS_test_cases.c_str());
  gpr_log(GPR_INFO, "sleep_duration_ms: %d", FLAGS_sleep_duration_ms);
  gpr_log(GPR_INFO, "test_duration_secs: %d", FLAGS_test_duration_secs);
  gpr_log(GPR_INFO, "num_channels_per_server: %d",
          FLAGS_num_channels_per_server);
  gpr_log(GPR_INFO, "num_stubs_per_channel: %d", FLAGS_num_stubs_per_channel);
  gpr_log(GPR_INFO, "log_level: %d", FLAGS_log_level);
  gpr_log(GPR_INFO, "do_not_abort_on_transient_failures: %s",
          FLAGS_do_not_abort_on_transient_failures ? "true" : "false");

  int num = 0;
  for (auto it = addresses.begin(); it != addresses.end(); it++) {
    gpr_log(GPR_INFO, "%d:%s", ++num, it->c_str());
  }

  num = 0;
  for (auto it = tests.begin(); it != tests.end(); it++) {
    TestCaseType test_case = it->first;
    int weight = it->second;
    gpr_log(GPR_INFO, "%d. TestCaseType: %d, Weight: %d", ++num, test_case,
            weight);
  }
}

int main(int argc, char** argv) {
  grpc::testing::InitTest(&argc, &argv, true);

  if (FLAGS_log_level > GPR_LOG_SEVERITY_ERROR ||
      FLAGS_log_level < GPR_LOG_SEVERITY_DEBUG) {
    gpr_log(GPR_ERROR, "log_level should be an integer between %d and %d",
            GPR_LOG_SEVERITY_DEBUG, GPR_LOG_SEVERITY_ERROR);
    return 1;
  }

  // Change the default log function to TestLogFunction which respects the
  // log_level setting.
  log_level = FLAGS_log_level;
  gpr_set_log_function(TestLogFunction);

  srand(time(NULL));

  // Parse the server addresses
  std::vector<grpc::string> server_addresses;
  ParseCommaDelimitedString(FLAGS_server_addresses, server_addresses);

  // Parse test cases and weights
  if (FLAGS_test_cases.length() == 0) {
    gpr_log(GPR_ERROR, "No test cases supplied");
    return 1;
  }

  std::vector<std::pair<TestCaseType, int>> tests;
  if (!ParseTestCasesString(FLAGS_test_cases, tests)) {
    gpr_log(GPR_ERROR, "Error in parsing test cases string %s ",
            FLAGS_test_cases.c_str());
    return 1;
  }

  LogParameterInfo(server_addresses, tests);

  WeightedRandomTestSelector test_selector(tests);
  MetricsServiceImpl metrics_service;

  gpr_log(GPR_INFO, "Starting test(s)..");

  std::vector<std::thread> test_threads;
  std::vector<std::unique_ptr<StressTestInteropClient>> clients;

  // Create and start the test threads.
  // Note that:
  // - Each server can have multiple channels (as configured by
  // FLAGS_num_channels_per_server).
  //
  // - Each channel can have multiple stubs (as configured by
  // FLAGS_num_stubs_per_channel). This is to test calling multiple RPCs in
  // parallel on the same channel.
  int thread_idx = 0;
  int server_idx = -1;
  char buffer[256];
  for (auto it = server_addresses.begin(); it != server_addresses.end(); it++) {
    ++server_idx;
    // Create channel(s) for each server
    for (int channel_idx = 0; channel_idx < FLAGS_num_channels_per_server;
         channel_idx++) {
      gpr_log(GPR_INFO, "Starting test with %s channel_idx=%d..", it->c_str(),
              channel_idx);
      std::shared_ptr<grpc::Channel> channel = grpc::CreateTestChannel(
          *it, FLAGS_server_host_override, FLAGS_use_tls, !FLAGS_use_test_ca);

      // Create stub(s) for each channel
      for (int stub_idx = 0; stub_idx < FLAGS_num_stubs_per_channel;
           stub_idx++) {
        clients.emplace_back(new StressTestInteropClient(
            ++thread_idx, *it, channel, test_selector, FLAGS_test_duration_secs,
            FLAGS_sleep_duration_ms, FLAGS_do_not_abort_on_transient_failures));

        bool is_already_created = false;
        // QpsGauge name
        std::snprintf(buffer, sizeof(buffer),
                      "/stress_test/server_%d/channel_%d/stub_%d/qps",
                      server_idx, channel_idx, stub_idx);

        test_threads.emplace_back(std::thread(
            &StressTestInteropClient::MainLoop, clients.back().get(),
            metrics_service.CreateQpsGauge(buffer, &is_already_created)));

        // The QpsGauge should not have been already created
        GPR_ASSERT(!is_already_created);
      }
    }
  }

  // Start metrics server before waiting for the stress test threads
  std::unique_ptr<grpc::Server> metrics_server;
  if (FLAGS_metrics_port > 0) {
    metrics_server = metrics_service.StartServer(FLAGS_metrics_port);
  }

  // Wait for the stress test threads to complete
  for (auto it = test_threads.begin(); it != test_threads.end(); it++) {
    it->join();
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "NasaWorldWindToOpenStreetMapConverter.h"

#include <QtCore/QDebug>
#include <QtCore/QString>
#include <cmath>

NasaWorldWindToOpenStreetMapConverter::NasaWorldWindToOpenStreetMapConverter( QObject * const parent )
    : QObject( parent ),
      m_osmTileEdgeLengthPixel( 256 ),
      m_nwwTileEdgeLengthPixel( 512 ),
      m_emptyPixel( qRgba( 0, 0, 0, 255 )),
      m_nwwTileLevel(),
      m_nwwMapWidthTiles(),
      m_nwwMapHeightTiles(),
      m_nwwMapWidthPixel(),
      m_nwwMapHeightPixel(),
      m_osmTileLevel(),
      m_osmMapEdgeLengthTiles(),
      m_osmMapEdgeLengthPixel()
{
}

void NasaWorldWindToOpenStreetMapConverter::setSourcePath( QDir const & sourcePath )
{
    if ( !sourcePath.exists() )
        qFatal("Source path does not exist.");
    m_sourceBaseDirectory = sourcePath;
}

void NasaWorldWindToOpenStreetMapConverter::setDestinationPath( QDir const & destinationPath )
{
    if ( !destinationPath.exists() ) {
        qDebug() << "Destination path " << destinationPath << "does not exist, creating.";
        destinationPath.mkpath( destinationPath.path() );
    }
    m_destinationBaseDirectory = destinationPath;
}

void NasaWorldWindToOpenStreetMapConverter::setNwwTileLevel( int const level )
{
    m_nwwTileLevel = level;
    m_nwwMapWidthTiles = 10 * pow( 2, m_nwwTileLevel );
    m_nwwMapHeightTiles = 5 * pow( 2, m_nwwTileLevel );
    m_nwwMapWidthPixel = m_nwwMapWidthTiles * m_nwwTileEdgeLengthPixel;
    m_nwwMapHeightPixel = m_nwwMapHeightTiles * m_nwwTileEdgeLengthPixel;
    qDebug() << "nwwTileLevel:" << m_nwwTileLevel
             << "\nnwwMapWidthTiles:" << m_nwwMapWidthTiles
             << "\nnwwMapHeightTiles:" << m_nwwMapHeightTiles
             << "\nnwwMapWidthPixel:" << m_nwwMapWidthPixel
             << "\nnwwMapHeightPixel:" << m_nwwMapHeightPixel;
}

void NasaWorldWindToOpenStreetMapConverter::setOsmTileLevel( int const level )
{
    m_osmTileLevel = level;
    m_osmMapEdgeLengthTiles = pow( 2, m_osmTileLevel );
    m_osmMapEdgeLengthPixel = m_osmMapEdgeLengthTiles * m_osmTileEdgeLengthPixel;
    qDebug() << "osmTileLevel:" << m_osmTileLevel
             << "\nosmMapEdgeLengthTiles:" << m_osmMapEdgeLengthTiles
             << "\nosmMapEdgeLengthPixel:" << m_osmMapEdgeLengthPixel;
}

void NasaWorldWindToOpenStreetMapConverter::start()
{
    int const tileX1 = 0; // 11:1114 12:1125;
    int const tileX2 = m_osmMapEdgeLengthTiles;
    int const tileY1 = 0;
    int const tileY2 = m_osmMapEdgeLengthTiles;

    for ( int tileX = tileX1; tileX < tileX2; ++tileX ) {
        QDir const tileDirectory = checkAndCreateDirectory( tileX );
        for ( int tileY = tileY1; tileY < tileY2; ++tileY ) {
            QImage const osmTile = calcOsmTile( tileX, tileY );

            // hack
            if ( osmTile.isNull() )
                continue;

            QString const filename = tileDirectory.path() + QString( "/%1.png" ).arg( tileY );
            bool const saved = osmTile.save( filename );
            if ( !saved )
                qFatal("Unable to save tile '%s'.", filename.toStdString().c_str() );
        }
    }
    emit finished();
}

void NasaWorldWindToOpenStreetMapConverter::testReprojection()
{
    qDebug() << "\nTesting osm pixel x -> lon[rad]";
    qDebug() << 0 << "->" << osmPixelXtoLonRad( 0 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel / 4 );
    qDebug() << m_osmMapEdgeLengthPixel / 2 << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel / 2 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 * 3 << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel / 4 * 3 );
    qDebug() << m_osmMapEdgeLengthPixel << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel );

    qDebug() << "\nTesting osm pixel y -> lat[rad]";
    qDebug() << 0 << "->" << osmPixelYtoLatRad( 0 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel / 4 );
    qDebug() << m_osmMapEdgeLengthPixel / 2 << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel / 2 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 * 3 << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel / 4 * 3 );
    qDebug() << m_osmMapEdgeLengthPixel << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel );

    qDebug() << "\nTesting lon[rad] -> nww pixel x";
    qDebug() <<       -M_PI << "->" << lonRadToNwwPixelX( -M_PI );
    qDebug() << -M_PI / 2.0 << "->" << lonRadToNwwPixelX( -M_PI / 2.0 );
    qDebug() <<           0 << "->" << lonRadToNwwPixelX(     0 );
    qDebug() <<  M_PI / 2.0 << "->" << lonRadToNwwPixelX(  M_PI / 2.0 );
    qDebug() <<        M_PI << "->" << lonRadToNwwPixelX(  M_PI );

    qDebug() << "\nTesting lat[rad] -> nww pixel y";
    qDebug() <<  M_PI / 2.0 << "->" << latRadToNwwPixelY(  M_PI / 2.0 );
    qDebug() <<           0 << "->" << latRadToNwwPixelY(     0 );
    qDebug() << -M_PI / 2.0 << "->" << latRadToNwwPixelY( -M_PI / 2.0 );
}

QImage NasaWorldWindToOpenStreetMapConverter::calcOsmTile( int const tileX, int const tileY )
{
    qDebug() << "calcOsmTile( tileX=" << tileX << ", tileY=" << tileY << " )";
    int const basePixelX = tileX * m_osmTileEdgeLengthPixel;
    int const basePixelY = tileY * m_osmTileEdgeLengthPixel;

    QSize const tileSize( m_osmTileEdgeLengthPixel, m_osmTileEdgeLengthPixel );
    QImage tile( tileSize, QImage::Format_ARGB32 );

    for ( int y = 0; y < m_osmTileEdgeLengthPixel; ++y ) {
        int const pixelY = basePixelY + y;
        double const latRad = osmPixelYtoLatRad( pixelY );

        for ( int x = 0; x < m_osmTileEdgeLengthPixel; ++x ) {
            int const pixelX = basePixelX + x;
            double const lonRad = osmPixelXtoLonRad( pixelX );
            QRgb const color = nwwPixel( lonRad, latRad );

            // for testing purposes only save complete tiles
            if ( color == m_emptyPixel )
                return QImage();

            tile.setPixel( x, y, color );
        }
    }
    return tile;
}

QDir NasaWorldWindToOpenStreetMapConverter::checkAndCreateDirectory( int const tileX ) const
{
    QDir const tileDirectory( m_destinationBaseDirectory.path() + QString("/%1/%2").arg( m_osmTileLevel ).arg( tileX ));
    if ( !tileDirectory.exists() ) {
        bool const created = tileDirectory.mkpath( tileDirectory.path() );
        if ( !created )
            qFatal("Unable to create directory '%s'.", tileDirectory.path().toStdString().c_str() );
    }
    return tileDirectory;
}

QRgb NasaWorldWindToOpenStreetMapConverter::nwwPixel( double const lonRad, double const latRad )
{
    double const x = lonRadToNwwPixelX( lonRad );
    double const y = latRadToNwwPixelY( latRad );

    // for now, just round
    int const xr = round( x );
    int const yr = round( y );
    int const roundedTileId = ( xr << 16 ) + yr;
    if ( m_nwwTileMissing.contains( roundedTileId ))
        return m_emptyPixel;

    return nwwPixel( xr, yr );

    int const x1 = x;
    int const x2 = x1 + 1;
    int const y1 = y;
    int const y2 = y1 + 1;

    // first check if all tiles are missing
    int const topLeftTileId = (x1 << 16) + y2;
    int const topRightTileId = (x2 << 16) + y2;
    int const bottomLeftTileId = (x1 << 16) + y1;
    int const bottomRightTileId = (x2 << 16) + y1;
    if ( m_nwwTileMissing.contains( topLeftTileId ) && topLeftTileId == topRightTileId
         && topLeftTileId == bottomLeftTileId && topLeftTileId == bottomRightTileId )
        return m_emptyPixel;

    if ( m_nwwTileMissing.contains( topRightTileId )
         && m_nwwTileMissing.contains( bottomLeftTileId ) && m_nwwTileMissing.contains( bottomRightTileId ))
        return m_emptyPixel;

    QRgb const topLeftPixel = nwwPixel( x1, y2 );
    QRgb const topRightPixel = nwwPixel( x2, y2 );
    QRgb const bottomLeftPixel = nwwPixel( x1, y1 );
    QRgb const bottomRightPixel = nwwPixel( x2, y1 );

    // cheap hack to see if osm tiles look somehow ok
    if ( topLeftPixel != m_emptyPixel )
        return topLeftPixel;
    else if ( topRightPixel != m_emptyPixel )
        return topRightPixel;
    else if ( bottomLeftPixel != m_emptyPixel )
        return bottomLeftPixel;
    else if ( bottomRightPixel != m_emptyPixel )
        return bottomRightPixel;
    else
        return m_emptyPixel;

    //double const fractionalX = x - x1;
    //double const fractionalY = y - y1;
}

QRgb NasaWorldWindToOpenStreetMapConverter::nwwPixel( int const pixelX, int const pixelY )
{
    int const tileX = pixelX / m_nwwTileEdgeLengthPixel;
    int const tileY = pixelY / m_nwwTileEdgeLengthPixel;
    QPair<QImage, bool> tile = nwwTile( tileX, tileY );
    if ( !tile.second )
        return m_emptyPixel;
    else
        return tile.first.pixel( pixelX % m_nwwTileEdgeLengthPixel,
                                 m_nwwTileEdgeLengthPixel - pixelY % m_nwwTileEdgeLengthPixel - 1 );
}

QPair<QImage, bool> NasaWorldWindToOpenStreetMapConverter::nwwTile( int const tileX, int const tileY )
{
    int const tileId = (tileX << 16) + tileY;

    // first check cache
    QImage * const cachedTile = m_nwwTileCache.object( tileId );
    if ( cachedTile )
        return QPair<QImage, bool>( *cachedTile, true );

    // fast check if tile is missing, perhaps move into caller
    if ( m_nwwTileMissing.contains( tileId ))
        return QPair<QImage, bool>( QImage(), false );

    QString const filename = QString("%1/%2/%2_%3.jpg")
            .arg( m_sourceBaseDirectory.path() )
            .arg( tileY, 4, 10, QLatin1Char('0'))
            .arg( tileX, 4, 10, QLatin1Char('0'));
    QImage tile;
    bool const loaded = tile.load( filename );
    if ( !loaded ) {
        m_nwwTileMissing.insert( tileId );
        //qDebug() << "Tile" << filename << "not found";
    } else {
        m_nwwTileCache.insert( tileId, new QImage( tile ));
        qDebug() << "Tile" << filename << "loaded and inserted in cache";
    }
    return QPair<QImage, bool>( tile, loaded );
}

inline double NasaWorldWindToOpenStreetMapConverter::osmPixelXtoLonRad( int const pixelX ) const
{
    double const pixelXd = static_cast<double>( pixelX );
    double const osmMapEdgeLengthPixeld = static_cast<double>( m_osmMapEdgeLengthPixel );
    return pixelXd * 2.0 * M_PI / osmMapEdgeLengthPixeld - M_PI;
}

inline double NasaWorldWindToOpenStreetMapConverter::osmPixelYtoLatRad( int const pixelY ) const
{
    double const pixelYd = static_cast<double>( pixelY );
    double const osmMapEdgeLengthPixeld = static_cast<double>( m_osmMapEdgeLengthPixel );
    double const latRad = -atan( sinh(( pixelYd - 0.5 * osmMapEdgeLengthPixeld ) * 2.0 * M_PI / osmMapEdgeLengthPixeld ));
    return latRad;
}

inline double NasaWorldWindToOpenStreetMapConverter::lonRadToNwwPixelX( double const lonRad ) const
{
    return static_cast<double>( m_nwwMapWidthPixel ) / ( 2.0 * M_PI ) * lonRad
            + 0.5 * static_cast<double>( m_nwwMapWidthPixel );
}

inline double NasaWorldWindToOpenStreetMapConverter::latRadToNwwPixelY( double const latRad ) const
{
    return static_cast<double>( m_nwwMapHeightPixel ) / M_PI * latRad
            + 0.5 * static_cast<double>( m_nwwMapHeightPixel );
}
<commit_msg>calcOsmTile: Also save tiles which are at least partly populated.<commit_after>#include "NasaWorldWindToOpenStreetMapConverter.h"

#include <QtCore/QDebug>
#include <QtCore/QString>
#include <cmath>

NasaWorldWindToOpenStreetMapConverter::NasaWorldWindToOpenStreetMapConverter( QObject * const parent )
    : QObject( parent ),
      m_osmTileEdgeLengthPixel( 256 ),
      m_nwwTileEdgeLengthPixel( 512 ),
      m_emptyPixel( qRgba( 0, 0, 0, 255 )),
      m_nwwTileLevel(),
      m_nwwMapWidthTiles(),
      m_nwwMapHeightTiles(),
      m_nwwMapWidthPixel(),
      m_nwwMapHeightPixel(),
      m_osmTileLevel(),
      m_osmMapEdgeLengthTiles(),
      m_osmMapEdgeLengthPixel()
{
}

void NasaWorldWindToOpenStreetMapConverter::setSourcePath( QDir const & sourcePath )
{
    if ( !sourcePath.exists() )
        qFatal("Source path does not exist.");
    m_sourceBaseDirectory = sourcePath;
}

void NasaWorldWindToOpenStreetMapConverter::setDestinationPath( QDir const & destinationPath )
{
    if ( !destinationPath.exists() ) {
        qDebug() << "Destination path " << destinationPath << "does not exist, creating.";
        destinationPath.mkpath( destinationPath.path() );
    }
    m_destinationBaseDirectory = destinationPath;
}

void NasaWorldWindToOpenStreetMapConverter::setNwwTileLevel( int const level )
{
    m_nwwTileLevel = level;
    m_nwwMapWidthTiles = 10 * pow( 2, m_nwwTileLevel );
    m_nwwMapHeightTiles = 5 * pow( 2, m_nwwTileLevel );
    m_nwwMapWidthPixel = m_nwwMapWidthTiles * m_nwwTileEdgeLengthPixel;
    m_nwwMapHeightPixel = m_nwwMapHeightTiles * m_nwwTileEdgeLengthPixel;
    qDebug() << "nwwTileLevel:" << m_nwwTileLevel
             << "\nnwwMapWidthTiles:" << m_nwwMapWidthTiles
             << "\nnwwMapHeightTiles:" << m_nwwMapHeightTiles
             << "\nnwwMapWidthPixel:" << m_nwwMapWidthPixel
             << "\nnwwMapHeightPixel:" << m_nwwMapHeightPixel;
}

void NasaWorldWindToOpenStreetMapConverter::setOsmTileLevel( int const level )
{
    m_osmTileLevel = level;
    m_osmMapEdgeLengthTiles = pow( 2, m_osmTileLevel );
    m_osmMapEdgeLengthPixel = m_osmMapEdgeLengthTiles * m_osmTileEdgeLengthPixel;
    qDebug() << "osmTileLevel:" << m_osmTileLevel
             << "\nosmMapEdgeLengthTiles:" << m_osmMapEdgeLengthTiles
             << "\nosmMapEdgeLengthPixel:" << m_osmMapEdgeLengthPixel;
}

void NasaWorldWindToOpenStreetMapConverter::start()
{
    int const tileX1 = 0; // 11:1114 12:1125;
    int const tileX2 = m_osmMapEdgeLengthTiles;
    int const tileY1 = 0;
    int const tileY2 = m_osmMapEdgeLengthTiles;

    for ( int tileX = tileX1; tileX < tileX2; ++tileX ) {
        QDir const tileDirectory = checkAndCreateDirectory( tileX );
        for ( int tileY = tileY1; tileY < tileY2; ++tileY ) {
            QImage const osmTile = calcOsmTile( tileX, tileY );

            // hack
            if ( osmTile.isNull() )
                continue;

            QString const filename = tileDirectory.path() + QString( "/%1.png" ).arg( tileY );
            bool const saved = osmTile.save( filename );
            if ( !saved )
                qFatal("Unable to save tile '%s'.", filename.toStdString().c_str() );
        }
    }
    emit finished();
}

void NasaWorldWindToOpenStreetMapConverter::testReprojection()
{
    qDebug() << "\nTesting osm pixel x -> lon[rad]";
    qDebug() << 0 << "->" << osmPixelXtoLonRad( 0 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel / 4 );
    qDebug() << m_osmMapEdgeLengthPixel / 2 << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel / 2 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 * 3 << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel / 4 * 3 );
    qDebug() << m_osmMapEdgeLengthPixel << "->" << osmPixelXtoLonRad( m_osmMapEdgeLengthPixel );

    qDebug() << "\nTesting osm pixel y -> lat[rad]";
    qDebug() << 0 << "->" << osmPixelYtoLatRad( 0 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel / 4 );
    qDebug() << m_osmMapEdgeLengthPixel / 2 << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel / 2 );
    qDebug() << m_osmMapEdgeLengthPixel / 4 * 3 << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel / 4 * 3 );
    qDebug() << m_osmMapEdgeLengthPixel << "->" << osmPixelYtoLatRad( m_osmMapEdgeLengthPixel );

    qDebug() << "\nTesting lon[rad] -> nww pixel x";
    qDebug() <<       -M_PI << "->" << lonRadToNwwPixelX( -M_PI );
    qDebug() << -M_PI / 2.0 << "->" << lonRadToNwwPixelX( -M_PI / 2.0 );
    qDebug() <<           0 << "->" << lonRadToNwwPixelX(     0 );
    qDebug() <<  M_PI / 2.0 << "->" << lonRadToNwwPixelX(  M_PI / 2.0 );
    qDebug() <<        M_PI << "->" << lonRadToNwwPixelX(  M_PI );

    qDebug() << "\nTesting lat[rad] -> nww pixel y";
    qDebug() <<  M_PI / 2.0 << "->" << latRadToNwwPixelY(  M_PI / 2.0 );
    qDebug() <<           0 << "->" << latRadToNwwPixelY(     0 );
    qDebug() << -M_PI / 2.0 << "->" << latRadToNwwPixelY( -M_PI / 2.0 );
}

QImage NasaWorldWindToOpenStreetMapConverter::calcOsmTile( int const tileX, int const tileY )
{
    qDebug() << "calcOsmTile( tileX=" << tileX << ", tileY=" << tileY << " )";
    int const basePixelX = tileX * m_osmTileEdgeLengthPixel;
    int const basePixelY = tileY * m_osmTileEdgeLengthPixel;

    QSize const tileSize( m_osmTileEdgeLengthPixel, m_osmTileEdgeLengthPixel );
    QImage tile( tileSize, QImage::Format_ARGB32 );
    bool notEmpty = false;

    for ( int y = 0; y < m_osmTileEdgeLengthPixel; ++y ) {
        int const pixelY = basePixelY + y;
        double const latRad = osmPixelYtoLatRad( pixelY );

        for ( int x = 0; x < m_osmTileEdgeLengthPixel; ++x ) {
            int const pixelX = basePixelX + x;
            double const lonRad = osmPixelXtoLonRad( pixelX );
            QRgb const color = nwwPixel( lonRad, latRad );

            if ( color != m_emptyPixel )
                notEmpty = true;

            tile.setPixel( x, y, color );
        }
    }
    return notEmpty ? tile : QImage();
}

QDir NasaWorldWindToOpenStreetMapConverter::checkAndCreateDirectory( int const tileX ) const
{
    QDir const tileDirectory( m_destinationBaseDirectory.path() + QString("/%1/%2").arg( m_osmTileLevel ).arg( tileX ));
    if ( !tileDirectory.exists() ) {
        bool const created = tileDirectory.mkpath( tileDirectory.path() );
        if ( !created )
            qFatal("Unable to create directory '%s'.", tileDirectory.path().toStdString().c_str() );
    }
    return tileDirectory;
}

QRgb NasaWorldWindToOpenStreetMapConverter::nwwPixel( double const lonRad, double const latRad )
{
    double const x = lonRadToNwwPixelX( lonRad );
    double const y = latRadToNwwPixelY( latRad );

    // for now, just round
    int const xr = round( x );
    int const yr = round( y );
    int const roundedTileId = ( xr << 16 ) + yr;
    if ( m_nwwTileMissing.contains( roundedTileId ))
        return m_emptyPixel;

    return nwwPixel( xr, yr );

    int const x1 = x;
    int const x2 = x1 + 1;
    int const y1 = y;
    int const y2 = y1 + 1;

    // first check if all tiles are missing
    int const topLeftTileId = (x1 << 16) + y2;
    int const topRightTileId = (x2 << 16) + y2;
    int const bottomLeftTileId = (x1 << 16) + y1;
    int const bottomRightTileId = (x2 << 16) + y1;
    if ( m_nwwTileMissing.contains( topLeftTileId ) && topLeftTileId == topRightTileId
         && topLeftTileId == bottomLeftTileId && topLeftTileId == bottomRightTileId )
        return m_emptyPixel;

    if ( m_nwwTileMissing.contains( topRightTileId )
         && m_nwwTileMissing.contains( bottomLeftTileId ) && m_nwwTileMissing.contains( bottomRightTileId ))
        return m_emptyPixel;

    QRgb const topLeftPixel = nwwPixel( x1, y2 );
    QRgb const topRightPixel = nwwPixel( x2, y2 );
    QRgb const bottomLeftPixel = nwwPixel( x1, y1 );
    QRgb const bottomRightPixel = nwwPixel( x2, y1 );

    // cheap hack to see if osm tiles look somehow ok
    if ( topLeftPixel != m_emptyPixel )
        return topLeftPixel;
    else if ( topRightPixel != m_emptyPixel )
        return topRightPixel;
    else if ( bottomLeftPixel != m_emptyPixel )
        return bottomLeftPixel;
    else if ( bottomRightPixel != m_emptyPixel )
        return bottomRightPixel;
    else
        return m_emptyPixel;

    //double const fractionalX = x - x1;
    //double const fractionalY = y - y1;
}

QRgb NasaWorldWindToOpenStreetMapConverter::nwwPixel( int const pixelX, int const pixelY )
{
    int const tileX = pixelX / m_nwwTileEdgeLengthPixel;
    int const tileY = pixelY / m_nwwTileEdgeLengthPixel;
    QPair<QImage, bool> tile = nwwTile( tileX, tileY );
    if ( !tile.second )
        return m_emptyPixel;
    else
        return tile.first.pixel( pixelX % m_nwwTileEdgeLengthPixel,
                                 m_nwwTileEdgeLengthPixel - pixelY % m_nwwTileEdgeLengthPixel - 1 );
}

QPair<QImage, bool> NasaWorldWindToOpenStreetMapConverter::nwwTile( int const tileX, int const tileY )
{
    int const tileId = (tileX << 16) + tileY;

    // first check cache
    QImage * const cachedTile = m_nwwTileCache.object( tileId );
    if ( cachedTile )
        return QPair<QImage, bool>( *cachedTile, true );

    // fast check if tile is missing, perhaps move into caller
    if ( m_nwwTileMissing.contains( tileId ))
        return QPair<QImage, bool>( QImage(), false );

    QString const filename = QString("%1/%2/%2_%3.jpg")
            .arg( m_sourceBaseDirectory.path() )
            .arg( tileY, 4, 10, QLatin1Char('0'))
            .arg( tileX, 4, 10, QLatin1Char('0'));
    QImage tile;
    bool const loaded = tile.load( filename );
    if ( !loaded ) {
        m_nwwTileMissing.insert( tileId );
        //qDebug() << "Tile" << filename << "not found";
    } else {
        m_nwwTileCache.insert( tileId, new QImage( tile ));
        qDebug() << "Tile" << filename << "loaded and inserted in cache";
    }
    return QPair<QImage, bool>( tile, loaded );
}

inline double NasaWorldWindToOpenStreetMapConverter::osmPixelXtoLonRad( int const pixelX ) const
{
    double const pixelXd = static_cast<double>( pixelX );
    double const osmMapEdgeLengthPixeld = static_cast<double>( m_osmMapEdgeLengthPixel );
    return pixelXd * 2.0 * M_PI / osmMapEdgeLengthPixeld - M_PI;
}

inline double NasaWorldWindToOpenStreetMapConverter::osmPixelYtoLatRad( int const pixelY ) const
{
    double const pixelYd = static_cast<double>( pixelY );
    double const osmMapEdgeLengthPixeld = static_cast<double>( m_osmMapEdgeLengthPixel );
    double const latRad = -atan( sinh(( pixelYd - 0.5 * osmMapEdgeLengthPixeld ) * 2.0 * M_PI / osmMapEdgeLengthPixeld ));
    return latRad;
}

inline double NasaWorldWindToOpenStreetMapConverter::lonRadToNwwPixelX( double const lonRad ) const
{
    return static_cast<double>( m_nwwMapWidthPixel ) / ( 2.0 * M_PI ) * lonRad
            + 0.5 * static_cast<double>( m_nwwMapWidthPixel );
}

inline double NasaWorldWindToOpenStreetMapConverter::latRadToNwwPixelY( double const latRad ) const
{
    return static_cast<double>( m_nwwMapHeightPixel ) / M_PI * latRad
            + 0.5 * static_cast<double>( m_nwwMapHeightPixel );
}
<|endoftext|>


<commit_before>#include <iostream>

#include "blockwisecc.h"
#include "test_utils.h"

#include <vigra/unittest.hxx>
#include <vigra/hdf5impex.hxx>

struct HDF5BlockedSourceTest {
void test() {
    using namespace vigra;
    typedef typename HDF5BlockedSource<3, float>::V V;

    HDF5File f("test.h5", HDF5File::Open);
    f.createDataset<3, float>("test", V(10,20,30), 0);
    f.close();

    HDF5BlockedSource<3, float> bs("test.h5", "test");
    shouldEqual(bs.shape(), V(10,20,30));

}
}; /* struct HDF5BlockedSourceTest */

struct HDF5BlockedSourceTestSuite : public vigra::test_suite {
    HDF5BlockedSourceTestSuite()
        : vigra::test_suite("HDF5BlockedSourceTestSuite")
    {
        add( testCase(&HDF5BlockedSourceTest::test) );
    }
};

int main(int argc, char ** argv) {
    HDF5BlockedSourceTestSuite test;
    int failed = test.run(vigra::testsToBeExecuted(argc, argv));
    std::cout << test.report() << std::endl;
    return (failed != 0);
}
<commit_msg>extend HDF5BlockedSource test<commit_after>#include <iostream>

#include "blockwisecc.h"
#include "test_utils.h"

#include <vigra/unittest.hxx>
#include <vigra/hdf5impex.hxx>

struct HDF5BlockedSourceTest {
void test() {
    using namespace vigra;
    typedef typename HDF5BlockedSource<3, float>::V V;

    HDF5File f("test.h5", HDF5File::Open);
    MultiArray<3, float> data(V(10,20,30));
    FillRandom<float, float*>::fillRandom(data.data(), data.data()+data.size());
    f.write<3, float>("test", data);
    f.close();

    HDF5BlockedSource<3, float> bs("test.h5", "test");
    shouldEqual(bs.shape(), V(10,20,30));

    MultiArray<3, float> r(data.shape());
    bool ret = bs.readBlock(Roi<3>(V(), data.shape()), r);
    should(ret);
    shouldEqualSequence(data.begin(), data.end(), r.begin());
}
}; /* struct HDF5BlockedSourceTest */

struct HDF5BlockedSourceTestSuite : public vigra::test_suite {
    HDF5BlockedSourceTestSuite()
        : vigra::test_suite("HDF5BlockedSourceTestSuite")
    {
        add( testCase(&HDF5BlockedSourceTest::test) );
    }
};

int main(int argc, char ** argv) {
    HDF5BlockedSourceTestSuite test;
    int failed = test.run(vigra::testsToBeExecuted(argc, argv));
    std::cout << test.report() << std::endl;
    return (failed != 0);
}
<|endoftext|>