<commit_before>/******************************************************************************
 * Copyright 2020 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/planning/learning_based/model_inference/trajectory_imitation_inference.h"

#include <string>
#include <utility>
#include <vector>

#include "cyber/common/log.h"
#include "modules/common/math/math_utils.h"
#include "modules/common/math/vec2d.h"
#include "modules/planning/learning_based/img_feature_renderer/birdview_img_feature_renderer.h"
#include "opencv2/opencv.hpp"

namespace apollo {
namespace planning {

TrajectoryConvRnnInference::TrajectoryConvRnnInference(
    const LearningModelInferenceTaskConfig& config)
    : ModelInference(config), device_(torch::kCPU) {
  LoadModel(config);
}

// TODO(Jinyun): evaluate whether use fake input in load model speed up the
// loading process
bool TrajectoryConvRnnInference::LoadModel(
    const LearningModelInferenceTaskConfig& config) {
  if (config.use_cuda() && torch::cuda::is_available()) {
    ADEBUG << "CUDA is available";
    device_ = torch::Device(torch::kCUDA);
  }
  model_ = torch::jit::load(config.model_file(), device_);
  torch::set_num_threads(1);
  return true;
}

bool TrajectoryConvRnnInference::Inference(
    LearningDataFrame* learning_data_frame) {
  const int past_points_size = learning_data_frame->adc_trajectory_point_size();
  if (past_points_size == 0) {
    AERROR << "No current trajectory point status";
    return false;
  }

  cv::Mat input_feature;
  if (!BirdviewImgFeatureRenderer::Instance()->RenderMultiChannelEnv(
          *learning_data_frame, &input_feature)) {
    AERROR << "Render multi-channel input image failed";
    return false;
  }
  cv::Mat input_feature_float;
  input_feature.convertTo(input_feature_float, CV_32F, 1.0 / 255);
  torch::Tensor input_feature_tensor =
      torch::from_blob(input_feature_float.data,
                       {1, input_feature_float.rows, input_feature_float.cols,
                        input_feature_float.channels()});
  input_feature_tensor = input_feature_tensor.permute({0, 3, 1, 2});
  for (int i = 0; i < input_feature_float.channels(); ++i) {
    input_feature_tensor[0][i] = input_feature_tensor[0][i].sub(0.5).div(0.5);
  }

  cv::Mat initial_point;
  if (!BirdviewImgFeatureRenderer::Instance()->RenderCurrentEgoPoint(
          *learning_data_frame, &initial_point)) {
    AERROR << "Render initial states image failed";
    return false;
  }
  cv::Mat initial_point_float;
  initial_point.convertTo(initial_point_float, CV_32F, 1.0 / 255);
  torch::Tensor initial_point_tensor =
      torch::from_blob(initial_point_float.data,
                       {1, initial_point_float.rows, initial_point_float.cols,
                        initial_point_float.channels()});
  initial_point_tensor = initial_point_tensor.permute({0, 3, 1, 2});

  cv::Mat initial_box;
  if (!BirdviewImgFeatureRenderer::Instance()->RenderCurrentEgoBox(
          *learning_data_frame, &initial_box)) {
    AERROR << "Render initial states image failed";
    return false;
  }
  cv::Mat initial_box_float;
  initial_box.convertTo(initial_box_float, CV_32F, 1.0 / 255);
  torch::Tensor initial_box_tensor =
      torch::from_blob(initial_box_float.data,
                       {1, initial_box_float.rows, initial_box_float.cols,
                        initial_box_float.channels()});
  initial_box_tensor = initial_box_tensor.permute({0, 3, 1, 2});

  std::vector<torch::jit::IValue> torch_inputs;
  torch_inputs.push_back(c10::ivalue::Tuple::create(
      {std::move(input_feature_tensor.to(device_)),
       std::move(initial_point_tensor.to(device_)),
       std::move(initial_box_tensor.to(device_))},
      c10::TupleType::create(
          std::vector<c10::TypePtr>(3, c10::TensorType::create()))));

  auto start_time = std::chrono::system_clock::now();
  at::Tensor torch_output_tensor = model_.forward(torch_inputs)
                                       .toTuple()
                                       ->elements()[2]
                                       .toTensor()
                                       .to(torch::kCPU);
  auto end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> diff = end_time - start_time;
  ADEBUG << "trajectory imitation model inference used time: "
         << diff.count() * 1000 << " ms.";

  const auto& cur_traj_point =
      learning_data_frame->adc_trajectory_point(past_points_size - 1);
  const double cur_time_sec = cur_traj_point.timestamp_sec();
  const auto& cur_path_point = cur_traj_point.trajectory_point().path_point();
  const double cur_x = cur_path_point.x();
  const double cur_y = cur_path_point.y();
  const double cur_heading = cur_path_point.theta();

  learning_data_frame->mutable_output()->clear_adc_future_trajectory_point();
  // TODO(Jinyun): move delta_t to conf or deduce it somehow
  const double delta_t = 0.2;
  auto torch_output = torch_output_tensor.accessor<float, 3>();
  for (int i = 0; i < torch_output_tensor.size(1); ++i) {
    const double dx = static_cast<double>(torch_output[0][i][0]);
    const double dy = static_cast<double>(torch_output[0][i][1]);
    const double dtheta = static_cast<double>(torch_output[0][i][2]);
    const double v = static_cast<double>(torch_output[0][i][3]);

    const double time_sec = cur_time_sec + delta_t * (i + 1);
    apollo::common::math::Vec2d offset(dx, dy);
    apollo::common::math::Vec2d rotated_offset = offset.rotate(cur_heading);
    const double x = cur_x + rotated_offset.x();
    const double y = cur_y + rotated_offset.y();
    const double heading =
        apollo::common::math::NormalizeAngle(dtheta + cur_heading);

    auto* traj_point = learning_data_frame->mutable_output()
                           ->add_adc_future_trajectory_point();
    traj_point->set_timestamp_sec(time_sec);
    traj_point->mutable_trajectory_point()->mutable_path_point()->set_x(x);
    traj_point->mutable_trajectory_point()->mutable_path_point()->set_y(y);
    traj_point->mutable_trajectory_point()->mutable_path_point()->set_theta(
        heading);
    traj_point->mutable_trajectory_point()->set_v(v);
    traj_point->mutable_trajectory_point()->set_relative_time(delta_t *
                                                              (i + 1));
  }

  return true;
}

}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: log time statisics in model inference<commit_after>/******************************************************************************
 * Copyright 2020 The Apollo Authors. All Rights Reserved.
 *
 * 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 "modules/planning/learning_based/model_inference/trajectory_imitation_inference.h"

#include <string>
#include <utility>
#include <vector>

#include "cyber/common/log.h"
#include "modules/common/math/math_utils.h"
#include "modules/common/math/vec2d.h"
#include "modules/planning/learning_based/img_feature_renderer/birdview_img_feature_renderer.h"
#include "opencv2/opencv.hpp"

namespace apollo {
namespace planning {

TrajectoryConvRnnInference::TrajectoryConvRnnInference(
    const LearningModelInferenceTaskConfig& config)
    : ModelInference(config), device_(torch::kCPU) {
  LoadModel(config);
}

// TODO(Jinyun): evaluate whether use fake input in load model speed up the
// loading process
bool TrajectoryConvRnnInference::LoadModel(
    const LearningModelInferenceTaskConfig& config) {
  if (config.use_cuda() && torch::cuda::is_available()) {
    ADEBUG << "CUDA is available";
    device_ = torch::Device(torch::kCUDA);
  }
  model_ = torch::jit::load(config.model_file(), device_);
  torch::set_num_threads(1);
  return true;
}

bool TrajectoryConvRnnInference::Inference(
    LearningDataFrame* learning_data_frame) {
  const int past_points_size = learning_data_frame->adc_trajectory_point_size();
  if (past_points_size == 0) {
    AERROR << "No current trajectory point status";
    return false;
  }

  auto input_renderering_start_time = std::chrono::system_clock::now();
  cv::Mat input_feature;
  if (!BirdviewImgFeatureRenderer::Instance()->RenderMultiChannelEnv(
          *learning_data_frame, &input_feature)) {
    AERROR << "Render multi-channel input image failed";
    return false;
  }
  cv::Mat initial_point;
  if (!BirdviewImgFeatureRenderer::Instance()->RenderCurrentEgoPoint(
          *learning_data_frame, &initial_point)) {
    AERROR << "Render initial states image failed";
    return false;
  }
  cv::Mat initial_box;
  if (!BirdviewImgFeatureRenderer::Instance()->RenderCurrentEgoBox(
          *learning_data_frame, &initial_box)) {
    AERROR << "Render initial states image failed";
    return false;
  }
  auto input_renderering_end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> rendering_diff =
      input_renderering_end_time - input_renderering_start_time;
  ADEBUG << "trajectory imitation model input renderer used time: "
         << rendering_diff.count() * 1000 << " ms.";

  auto input_prepration_start_time = std::chrono::system_clock::now();
  cv::Mat input_feature_float;
  input_feature.convertTo(input_feature_float, CV_32F, 1.0 / 255);
  torch::Tensor input_feature_tensor =
      torch::from_blob(input_feature_float.data,
                       {1, input_feature_float.rows, input_feature_float.cols,
                        input_feature_float.channels()});
  input_feature_tensor = input_feature_tensor.permute({0, 3, 1, 2});
  for (int i = 0; i < input_feature_float.channels(); ++i) {
    input_feature_tensor[0][i] = input_feature_tensor[0][i].sub(0.5).div(0.5);
  }
  cv::Mat initial_point_float;
  initial_point.convertTo(initial_point_float, CV_32F, 1.0 / 255);
  torch::Tensor initial_point_tensor =
      torch::from_blob(initial_point_float.data,
                       {1, initial_point_float.rows, initial_point_float.cols,
                        initial_point_float.channels()});
  initial_point_tensor = initial_point_tensor.permute({0, 3, 1, 2});
  cv::Mat initial_box_float;
  initial_box.convertTo(initial_box_float, CV_32F, 1.0 / 255);
  torch::Tensor initial_box_tensor =
      torch::from_blob(initial_box_float.data,
                       {1, initial_box_float.rows, initial_box_float.cols,
                        initial_box_float.channels()});
  initial_box_tensor = initial_box_tensor.permute({0, 3, 1, 2});

  std::vector<torch::jit::IValue> torch_inputs;
  torch_inputs.push_back(c10::ivalue::Tuple::create(
      {std::move(input_feature_tensor.to(device_)),
       std::move(initial_point_tensor.to(device_)),
       std::move(initial_box_tensor.to(device_))},
      c10::TupleType::create(
          std::vector<c10::TypePtr>(3, c10::TensorType::create()))));

  auto input_prepration_end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> prepration_diff =
      input_prepration_end_time - input_prepration_start_time;
  ADEBUG << "trajectory imitation model input prepration used time: "
         << prepration_diff.count() * 1000 << " ms.";

  auto inference_start_time = std::chrono::system_clock::now();
  at::Tensor torch_output_tensor = model_.forward(torch_inputs)
                                       .toTuple()
                                       ->elements()[2]
                                       .toTensor()
                                       .to(torch::kCPU);
  auto inference_end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> inference_diff =
      inference_end_time - inference_start_time;
  ADEBUG << "trajectory imitation model inference used time: "
         << inference_diff.count() * 1000 << " ms.";

  const auto& cur_traj_point =
      learning_data_frame->adc_trajectory_point(past_points_size - 1);
  const double cur_time_sec = cur_traj_point.timestamp_sec();
  const auto& cur_path_point = cur_traj_point.trajectory_point().path_point();
  const double cur_x = cur_path_point.x();
  const double cur_y = cur_path_point.y();
  const double cur_heading = cur_path_point.theta();

  learning_data_frame->mutable_output()->clear_adc_future_trajectory_point();
  // TODO(Jinyun): move delta_t to conf or deduce it somehow
  const double delta_t = 0.2;
  auto torch_output = torch_output_tensor.accessor<float, 3>();
  for (int i = 0; i < torch_output_tensor.size(1); ++i) {
    const double dx = static_cast<double>(torch_output[0][i][0]);
    const double dy = static_cast<double>(torch_output[0][i][1]);
    const double dtheta = static_cast<double>(torch_output[0][i][2]);
    const double v = static_cast<double>(torch_output[0][i][3]);

    const double time_sec = cur_time_sec + delta_t * (i + 1);
    apollo::common::math::Vec2d offset(dx, dy);
    apollo::common::math::Vec2d rotated_offset = offset.rotate(cur_heading);
    const double x = cur_x + rotated_offset.x();
    const double y = cur_y + rotated_offset.y();
    const double heading =
        apollo::common::math::NormalizeAngle(dtheta + cur_heading);

    auto* traj_point = learning_data_frame->mutable_output()
                           ->add_adc_future_trajectory_point();
    traj_point->set_timestamp_sec(time_sec);
    traj_point->mutable_trajectory_point()->mutable_path_point()->set_x(x);
    traj_point->mutable_trajectory_point()->mutable_path_point()->set_y(y);
    traj_point->mutable_trajectory_point()->mutable_path_point()->set_theta(
        heading);
    traj_point->mutable_trajectory_point()->set_v(v);
    traj_point->mutable_trajectory_point()->set_relative_time(delta_t *
                                                              (i + 1));
  }

  return true;
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/program_options.hpp>
#include "float-semiring.h"
#include "free-semiring.h"
#include "semilinSetExp.h"
#include "matrix.h"
#include "polynomial.h"
#include "newton.h"
#include "commutativeRExp.h"
#include "parser.h"

// group the equations to SCCs
template <typename SR>
std::vector<std::vector<std::pair<VarPtr, Polynomial<SR>>>> group_by_scc(std::vector<std::pair<VarPtr, Polynomial<SR>>> equations, bool graphviz_output)
{
	struct VertexProp {
		std::string name;   // used for graphviz output
		VarPtr var;         // var and rex combines the equations in the vertex
		Polynomial<SR> rex;
	};

	// create map of variables to [0..n]. this is used to enumerate important variables in a clean way from 0 to n during graph construction
	std::map<VarPtr, int> var_key;

	// build the graph
	boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, VertexProp> graph(equations.size());
	for(auto e_it = equations.begin(); e_it != equations.end(); ++e_it)
	{
		// if the variable is not yet in the map insert it together with the size of
		// the map. this way we get a unique identifier for the variable counting from 0 to n
		if(var_key.find(e_it->first) == var_key.end())
			var_key.insert(var_key.begin(), std::pair<VarPtr,int>(e_it->first,var_key.size()));
		int a = var_key.find(e_it->first)->second; // variable key
		graph[a].var = e_it->first; // store VarPtr to the vertex
		graph[a].name = e_it->first->string(); // store the name to the vertex
		graph[a].rex = e_it->second; // store the regular expression to the vertex

		auto v = e_it->second.get_variables(); // all variables of this rule;
		for(auto v_it = v.begin(); v_it != v.end(); ++v_it)
		{
			if(var_key.find(*v_it) == var_key.end()) // variable is not yet in the map
				var_key.insert(var_key.begin(), std::pair<VarPtr,int>(*v_it,var_key.size()));
			int b = var_key.find(*v_it)->second; // variable key
			boost::add_edge(a, b, graph);
		}
	} // graph is complete

	if(graphviz_output)
	{
		// output the created graph to graph.dot
		boost::dynamic_properties dp;
		dp.property("label", boost::get(&VertexProp::name, graph)); // vertex name is the name of the equation
		dp.property("node_id", get(boost::vertex_index, graph)); // this is needed
		std::ofstream outf("graph.dot");
		boost::write_graphviz_dp(outf, graph, dp);
	}

	// calculate strong connected components and store them in 'component'
	std::vector<int> component(boost::num_vertices(graph));
	boost::strong_components(graph,&component[0]);

	// group neccessary equations together
	int num_comp = *std::max_element(component.begin(), component.end()) + 1; // find the number of components
	std::vector<std::vector<std::pair<VarPtr,Polynomial<SR>>>> grouped_equations;
	grouped_equations.resize(num_comp);

	// iterate over all vertices (0 to n)
	// collect the necessary variables + equations for every component
	for (unsigned int j = 0; j != component.size(); ++j)
	{
		//std::cout << j << ", " << graph[j].var << " is in component " << component[j] << std::endl;
		grouped_equations[component[j]].push_back(std::pair<VarPtr,Polynomial<SR>>(graph[j].var, graph[j].rex));
	}

	return grouped_equations;
}

// apply the newton method to the given input
template <typename SR>
std::map<VarPtr, SR> apply_newton(std::vector<std::pair<VarPtr, Polynomial<SR>>> equations, bool scc, bool iteration_flag, int iterations, bool graphviz_output)
{
	// TODO: sanity checks on the input!

	// generate an instance of the newton solver
	Newton<SR> newton;

	// if we use the scc method, group the equations
	// the outer vector contains SCCs starting with a bottom SCC at 0
	std::vector<std::vector<std::pair<VarPtr,Polynomial<SR>>>> equations2;
	if(scc)
	{
		auto tmp = group_by_scc(equations, graphviz_output);
		equations2.insert(equations2.begin(), tmp.begin(), tmp.end());
	}
	else if (!scc)
	{
		equations2.push_back(equations);
	}

	// this holds the solution
	std::map<VarPtr, SR> solution;

	// the same loop is used for both the scc and the non-scc variant
	// in the non-scc variant, we just run once through the loop
	//for(auto it1 = equations2.begin(); it != equations2.end(); ++it)
	for(unsigned int j = 0; j != equations2.size(); ++j)
	{
		// use the solutions to get rid of variables in the remaining equations
		// does nothing in the first round
		std::vector<std::pair<VarPtr, Polynomial<SR>>> tmp1;
		for(auto it = equations2[j].begin(); it != equations2[j].end(); ++it)
		{ // it = (VarPtr, Polynomial[SR])
			auto tmp2 = it->second.partial_eval(solution);
			tmp1.push_back(std::pair<VarPtr, Polynomial<SR>>(it->first, tmp2));
		}
		// replace old equations with simplified ones
		equations2[j] = tmp1;

		// dynamic iterations
		if(!iteration_flag)
			iterations = equations2[j].size();

		// do some real work here
		std::map<VarPtr, SR> result = newton.solve_fixpoint(equations2[j], iterations);

		// copy the results into the solution map
		solution.insert(result.begin(), result.end());
	}

	return solution;
}

template <typename SR>
std::string result_string(std::map<VarPtr,SR> result)
{
	std::stringstream ss;
	for(auto r_it = result.begin(); r_it != result.end(); ++r_it)
		ss << r_it->first << " == " << r_it->second << std::endl;
	return ss.str();
}

int main(int argc, char* argv[])
{
	namespace po = boost::program_options;

	po::options_description desc("Allowed options");
	desc.add_options()
		( "scc", "apply newton method iteratively to strongly connected components of the equation graph" )
		( "help,h", "print this help message" )
		( "iterations,i", po::value<int>(), "specify the number of newton iterations. default is optimal number" )
		//( "verbose", "enable verbose output" )
		//( "debug", "enable debug output" )
		( "file,f", po::value<std::string>(), "input file" )
		( "float", "float semiring" )
		( "rexp", "commutative regular expression semiring" )
		( "graphviz", "create the file graph.dot with the equation graph" )
		;
	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	if(vm.count("help"))
	{
		std::cout << desc << std::endl;
		return 0;
	}

	int iterations=0;
	if(vm.count("iterations"))
		iterations = vm["iterations"].as<int>();

	// check if we can do something useful
	if(!vm.count("float") && !vm.count("rexp")) // check for all compatible parameters
		return 0;

	std::vector<std::string> input;
	std::string line;
	if(vm.count("file"))
	{
		// we are reading the input from the given file
		std::ifstream file;
		file.open(vm["file"].as<std::string>(), std::ifstream::in);
		while(std::getline(file, line))
			input.push_back(line);
	}
	else
	{
		// we are reading from stdin
		while(std::getline(std::cin, line))
			input.push_back(line);
	}

	// join the input into one string
	std::string input_all = std::accumulate(input.begin(), input.end(), std::string(""));

	Parser p;

	if(vm.count("rexp"))
	{
		// parse the input into a list of (Var → Polynomial[SR])
		std::vector<std::pair<VarPtr, Polynomial<CommutativeRExp>>> equations(p.rexp_parser(input_all));
		if(equations.empty()) return -1;

		for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
		{
			std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
		}

		// apply the newton method to the equations
		auto result = apply_newton<CommutativeRExp>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
		std::cout << result_string(result) << std::endl;
	}
	else if(vm.count("float"))
	{
		std::vector<std::pair<VarPtr, Polynomial<FloatSemiring>>> equations(p.float_parser(input_all));
		if(equations.empty()) return -1;

		for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
		{
			std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
		}

		auto result = apply_newton<FloatSemiring>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
		std::cout << result_string(result) << std::endl;
	}

	return 0;
}
<commit_msg>now clang++ is able to compile the project (but output is different. seems to be different multiset order)<commit_after>#include <iostream>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/program_options.hpp>
#include "float-semiring.h"
#include "free-semiring.h"
#include "semilinSetExp.h"
#include "matrix.h"
#include "polynomial.h"
#include "newton.h"
#include "commutativeRExp.h"
#include "parser.h"

template <typename SR>
struct VertexProp {
	std::string name;   // used for graphviz output
	VarPtr var;         // var and rex combines the equations in the vertex
	Polynomial<SR> rex;
};

// group the equations to SCCs
template <typename SR>
std::vector<std::vector<std::pair<VarPtr, Polynomial<SR>>>> group_by_scc(std::vector<std::pair<VarPtr, Polynomial<SR>>> equations, bool graphviz_output)
{
	// create map of variables to [0..n]. this is used to enumerate important variables in a clean way from 0 to n during graph construction
	std::map<VarPtr, int> var_key;

	// build the graph
	boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, VertexProp<SR>> graph(equations.size());
	for(auto e_it = equations.begin(); e_it != equations.end(); ++e_it)
	{
		// if the variable is not yet in the map insert it together with the size of
		// the map. this way we get a unique identifier for the variable counting from 0 to n
		if(var_key.find(e_it->first) == var_key.end())
			var_key.insert(var_key.begin(), std::pair<VarPtr,int>(e_it->first,var_key.size()));
		int a = var_key.find(e_it->first)->second; // variable key
		graph[a].var = e_it->first; // store VarPtr to the vertex
		graph[a].name = e_it->first->string(); // store the name to the vertex
		graph[a].rex = e_it->second; // store the regular expression to the vertex

		auto v = e_it->second.get_variables(); // all variables of this rule;
		for(auto v_it = v.begin(); v_it != v.end(); ++v_it)
		{
			if(var_key.find(*v_it) == var_key.end()) // variable is not yet in the map
				var_key.insert(var_key.begin(), std::pair<VarPtr,int>(*v_it,var_key.size()));
			int b = var_key.find(*v_it)->second; // variable key
			boost::add_edge(a, b, graph);
		}
	} // graph is complete

	if(graphviz_output)
	{
		// output the created graph to graph.dot
		boost::dynamic_properties dp;
		dp.property("label", boost::get(&VertexProp<SR>::name, graph)); // vertex name is the name of the equation
		dp.property("node_id", get(boost::vertex_index, graph)); // this is needed
		std::ofstream outf("graph.dot");
		boost::write_graphviz_dp(outf, graph, dp);
	}

	// calculate strong connected components and store them in 'component'
	std::vector<int> component(boost::num_vertices(graph));
	boost::strong_components(graph,&component[0]);

	// group neccessary equations together
	int num_comp = *std::max_element(component.begin(), component.end()) + 1; // find the number of components
	std::vector<std::vector<std::pair<VarPtr,Polynomial<SR>>>> grouped_equations;
	grouped_equations.resize(num_comp);

	// iterate over all vertices (0 to n)
	// collect the necessary variables + equations for every component
	for (unsigned int j = 0; j != component.size(); ++j)
	{
		//std::cout << j << ", " << graph[j].var << " is in component " << component[j] << std::endl;
		grouped_equations[component[j]].push_back(std::pair<VarPtr,Polynomial<SR>>(graph[j].var, graph[j].rex));
	}

	return grouped_equations;
}

// apply the newton method to the given input
template <typename SR>
std::map<VarPtr, SR> apply_newton(std::vector<std::pair<VarPtr, Polynomial<SR>>> equations, bool scc, bool iteration_flag, int iterations, bool graphviz_output)
{
	// TODO: sanity checks on the input!

	// generate an instance of the newton solver
	Newton<SR> newton;

	// if we use the scc method, group the equations
	// the outer vector contains SCCs starting with a bottom SCC at 0
	std::vector<std::vector<std::pair<VarPtr,Polynomial<SR>>>> equations2;
	if(scc)
	{
		auto tmp = group_by_scc(equations, graphviz_output);
		equations2.insert(equations2.begin(), tmp.begin(), tmp.end());
	}
	else if (!scc)
	{
		equations2.push_back(equations);
	}

	// this holds the solution
	std::map<VarPtr, SR> solution;

	// the same loop is used for both the scc and the non-scc variant
	// in the non-scc variant, we just run once through the loop
	//for(auto it1 = equations2.begin(); it != equations2.end(); ++it)
	for(unsigned int j = 0; j != equations2.size(); ++j)
	{
		// use the solutions to get rid of variables in the remaining equations
		// does nothing in the first round
		std::vector<std::pair<VarPtr, Polynomial<SR>>> tmp1;
		for(auto it = equations2[j].begin(); it != equations2[j].end(); ++it)
		{ // it = (VarPtr, Polynomial[SR])
			auto tmp2 = it->second.partial_eval(solution);
			tmp1.push_back(std::pair<VarPtr, Polynomial<SR>>(it->first, tmp2));
		}
		// replace old equations with simplified ones
		equations2[j] = tmp1;

		// dynamic iterations
		if(!iteration_flag)
			iterations = equations2[j].size();

		// do some real work here
		std::map<VarPtr, SR> result = newton.solve_fixpoint(equations2[j], iterations);

		// copy the results into the solution map
		solution.insert(result.begin(), result.end());
	}

	return solution;
}

template <typename SR>
std::string result_string(std::map<VarPtr,SR> result)
{
	std::stringstream ss;
	for(auto r_it = result.begin(); r_it != result.end(); ++r_it)
		ss << r_it->first << " == " << r_it->second << std::endl;
	return ss.str();
}

int main(int argc, char* argv[])
{
	namespace po = boost::program_options;

	po::options_description desc("Allowed options");
	desc.add_options()
		( "scc", "apply newton method iteratively to strongly connected components of the equation graph" )
		( "help,h", "print this help message" )
		( "iterations,i", po::value<int>(), "specify the number of newton iterations. default is optimal number" )
		//( "verbose", "enable verbose output" )
		//( "debug", "enable debug output" )
		( "file,f", po::value<std::string>(), "input file" )
		( "float", "float semiring" )
		( "rexp", "commutative regular expression semiring" )
		( "graphviz", "create the file graph.dot with the equation graph" )
		;
	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	if(vm.count("help"))
	{
		std::cout << desc << std::endl;
		return 0;
	}

	int iterations=0;
	if(vm.count("iterations"))
		iterations = vm["iterations"].as<int>();

	// check if we can do something useful
	if(!vm.count("float") && !vm.count("rexp")) // check for all compatible parameters
		return 0;

	std::vector<std::string> input;
	std::string line;
	if(vm.count("file"))
	{
		// we are reading the input from the given file
		std::ifstream file;
		file.open(vm["file"].as<std::string>(), std::ifstream::in);
		while(std::getline(file, line))
			input.push_back(line);
	}
	else
	{
		// we are reading from stdin
		while(std::getline(std::cin, line))
			input.push_back(line);
	}

	// join the input into one string
	std::string input_all = std::accumulate(input.begin(), input.end(), std::string(""));

	Parser p;

	if(vm.count("rexp"))
	{
		// parse the input into a list of (Var → Polynomial[SR])
		std::vector<std::pair<VarPtr, Polynomial<CommutativeRExp>>> equations(p.rexp_parser(input_all));
		if(equations.empty()) return -1;

		for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
		{
			std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
		}

		// apply the newton method to the equations
		auto result = apply_newton<CommutativeRExp>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
		std::cout << result_string(result) << std::endl;
	}
	else if(vm.count("float"))
	{
		std::vector<std::pair<VarPtr, Polynomial<FloatSemiring>>> equations(p.float_parser(input_all));
		if(equations.empty()) return -1;

		for(auto eq_it = equations.begin(); eq_it != equations.end(); ++eq_it)
		{
			std::cout << "* " << eq_it->first << " → " << eq_it->second << std::endl;
		}

		auto result = apply_newton<FloatSemiring>(equations, vm.count("scc"), vm.count("iterations"), iterations, vm.count("graphviz"));
		std::cout << result_string(result) << std::endl;
	}

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include "float-semiring.h"
#include "free-semiring.h"
#include "semilinSetExp.h"
#include "matrix.h"
#include "polynomial.h"
#include "newton.h"
#include "commutativeRExp.h"

void test_addition()
{
	FloatSemiring first(0.5);
	FloatSemiring second(0.3);
	FloatSemiring result = first + second;
	std::cout << "- float semiring addition: " << std::endl;
	std::cout << first << " + " << second << " = " << result << std::endl;
}

void test_multiplication()
{
	FloatSemiring first(0.5);
	FloatSemiring second(0.3);
	FloatSemiring result = first * second;
	std::cout << "- float semiring multiplication: " << std::endl;
	std::cout << first << " * " << second << " = " << result << std::endl;
}

void test_variables()
{
	Var var1;
	Var var2;
	std::cout << "- variables:" << std::endl;
	std::cout << var1 << "," << var2 << std::endl;
}

void test_monomials()
{
	std::cout << "- monomials:" << std::endl;
	Monomial<FloatSemiring> mon1(FloatSemiring(5),{Var("x"),Var("x"),Var("y")});
	Monomial<FloatSemiring> mon2(FloatSemiring(2),{Var("y"), Var("x")});
	Monomial<FloatSemiring> res1 = mon1 + mon1;
	Monomial<FloatSemiring> res2 = mon1 * mon2;
	std::cout << mon1 << " + " << mon1 << " = " << res1 << std::endl;
	std::cout << mon1 << " * " << mon2 << " = " << res2 << std::endl;
	std::cout << "derivative of " << mon1 << " = " << mon1.derivative(Var("x")) << std::endl;
}

Polynomial<FloatSemiring> get_first_polynomial()
{
	// define new polynomial 2xx+7y
	return Polynomial<FloatSemiring>(
			{	Monomial<FloatSemiring>(FloatSemiring(2),{Var("x"),Var("x")}),
				Monomial<FloatSemiring>(FloatSemiring(7),{Var("z")}) });
}

Polynomial<FloatSemiring> get_second_polynomial()
{
	// define new polynomial 5xx+3xy+6yy
	return Polynomial<FloatSemiring>(
			{	Monomial<FloatSemiring>(FloatSemiring(5),{Var("x"),Var("x")}),
				Monomial<FloatSemiring>(FloatSemiring(3),{Var("x"),Var("y")}),
				Monomial<FloatSemiring>(FloatSemiring(6),{Var("y"),Var("y")})});
}

void test_polynomial_addition()
{
	Polynomial<FloatSemiring> first = get_first_polynomial();
	Polynomial<FloatSemiring> second = get_second_polynomial();
	Polynomial<FloatSemiring> result = first + second;
	std::cout << "- polynomial addition:" << std::endl;
	std::cout << first << " + " << second << " = " << result << std::endl;
}

void test_polynomial_multiplication()
{
	Polynomial<FloatSemiring> first = get_first_polynomial();
	Polynomial<FloatSemiring> second = get_second_polynomial();
	Polynomial<FloatSemiring> result = first * second;
	std::cout << "- polynomial multiplication:" << std::endl;
	std::cout << first << " * " << second << " = " << result << std::endl;
}

std::map<Var,FloatSemiring> get_variable_values()
{
	std::map<Var,FloatSemiring> values;
	values.insert(values.begin(), std::pair<Var,FloatSemiring>(Var("x"),FloatSemiring(5)));
	values.insert(values.begin(), std::pair<Var,FloatSemiring>(Var("y"),FloatSemiring(4)));
	values.insert(values.begin(), std::pair<Var,FloatSemiring>(Var("z"),FloatSemiring(0)));
	return values;
}

void test_polynomial_evaluation()
{
	Polynomial<FloatSemiring> polynomial = get_second_polynomial();
	std::map<Var,FloatSemiring> values = get_variable_values();
	FloatSemiring result = polynomial.eval(values);
	std::cout << "- polynomial evaluation:" << std::endl;
	std::cout << polynomial << " at {x=5, y=4, z=0} = " << result << std::endl;
}

Matrix<FloatSemiring> get_first_matrix()
{
	FloatSemiring elems[] = {
		FloatSemiring(0.5), FloatSemiring(0.9),
		FloatSemiring(0.2), FloatSemiring(0.1)};
	return Matrix<FloatSemiring>(2,2,std::vector<FloatSemiring>(elems, elems+4));
}

Matrix<FloatSemiring> get_second_matrix()
{
	FloatSemiring elems[] = {
		FloatSemiring(0.3), FloatSemiring(0.1),
		FloatSemiring(0.7), FloatSemiring(0.2)};
	return Matrix<FloatSemiring>(2,2,std::vector<FloatSemiring>(elems, elems+4));
}

Matrix<FreeSemiring> get_star_test_matrix()
{
/*	FloatSemiring elems[] = {
		FloatSemiring(0.6), FloatSemiring(0.1), FloatSemiring(0.1),
		FloatSemiring(0.1), FloatSemiring(0.4), FloatSemiring(0.1),
		FloatSemiring(0.1), FloatSemiring(0.1), FloatSemiring(0.3)};
	return Matrix<FloatSemiring>(3,3,std::vector<FloatSemiring>(elems, elems+9));
*/
	FreeSemiring elems[]  = {
		FreeSemiring(Var("a")),
		FreeSemiring(Var("b")),
		FreeSemiring(Var("c")),
		FreeSemiring(Var("d")) };
	return Matrix<FreeSemiring>(2,2,std::vector<FreeSemiring>(elems, elems+4));
}

void test_matrix_addition()
{
	Matrix<FloatSemiring> first = get_first_matrix();
	Matrix<FloatSemiring> second = get_second_matrix();
	Matrix<FloatSemiring> result = first + second;
	std::cout << "- matrix addition:" << std::endl;
	std::cout << first << " + " << std::endl << second << " = " << std::endl << result;
}

void test_matrix_multiplication()
{
	Matrix<FloatSemiring> first = get_first_matrix();
	Matrix<FloatSemiring> second = get_second_matrix();
	Matrix<FloatSemiring> result = first * second;
	std::cout << "- matrix multiplication:" << std::endl;
	std::cout << first << " * " << std::endl << second << " = " << std::endl << result;
}

void test_matrix_transpose()
{
	Matrix<FloatSemiring> matrix = get_first_matrix();
	Matrix<FloatSemiring> result = matrix.transpose();
	std::cout << "- matrix transpose:" << std::endl;
	std::cout << matrix << " transposed " << std::endl << result;
}

void test_matrix_star()
{
	auto matrix = get_star_test_matrix();
	auto result = matrix.star();
	std::cout << "- matrix star:" << std::endl;
	std::cout << matrix << " the matrix star of this is: " << std::endl << result;
}

void test_jacobian()
{
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	variables.push_back(Var("y"));
	variables.push_back(Var("z"));
	std::vector<Polynomial<FloatSemiring> > polynomials;
	polynomials.push_back(get_first_polynomial());
	polynomials.push_back(get_second_polynomial());
	Matrix<Polynomial<FloatSemiring> > jacobian = Polynomial<FloatSemiring>::jacobian(polynomials, variables);
	std::cout << "- jacobian (x,y,z) of " << std::endl;
	std::cout << polynomials.at(0) << std::endl << polynomials.at(1) << std::endl << " = " << std::endl << jacobian << std::endl;
}

void test_polynomial_matrix_evaluation()
{
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	variables.push_back(Var("y"));
	variables.push_back(Var("z"));
	std::vector<Polynomial<FloatSemiring> > polynomials;
	polynomials.push_back(get_first_polynomial());
	polynomials.push_back(get_second_polynomial());
	Matrix<Polynomial<FloatSemiring> > polynomial_matrix = Polynomial<FloatSemiring>::jacobian(polynomials, variables);
	std::map<Var,FloatSemiring> values = get_variable_values();
	Matrix<FloatSemiring> result = Polynomial<FloatSemiring>::eval(polynomial_matrix, values);
	std::cout << "- polynomial matrix evaluation" << std::endl;
	std::cout << polynomial_matrix << " at {x=5, y=4, z=0} = " << std::endl << result;
}

void test_freesemiring()
{
	std::cout << "- free semiring" << std::endl;
	FreeSemiring term1 = FreeSemiring(Var("a"));
	FreeSemiring term2 = FreeSemiring(Var("b"));
	std::cout << "some terms: " <<  term1 << " and " << term2 << std::endl;
	FreeSemiring termAdd = term1 + term2;
	FreeSemiring termMul = term1 * term2;
	std::cout << "addition&multiplication&star: " << (termAdd*termMul.star()) << std::endl;
}

void test_polynomial_to_freesemiring()
{
	std::cout << "- polynomial to free semiring conversion" <<std::endl;
	Polynomial<FloatSemiring> poly = get_first_polynomial();
	auto valuation = new std::unordered_map<FloatSemiring, FreeSemiring, FloatSemiring>();
	FreeSemiring elem = poly.make_free(valuation);
	for(auto v_it = valuation->begin(); v_it != valuation->end(); ++v_it)
	{
		std::cout << "valuation: " << v_it->first << " → " << v_it->second << std::endl;
	}
	std::cout << "polynomial: " << poly << std::endl;
	std::cout << "free semiring: " << elem << std::endl;
}

std::vector<Polynomial<FloatSemiring> > get_newton_test_polynomials()
{
	std::vector<Polynomial<FloatSemiring> > polynomials;

	// define new polynomial 0.4xy+0.6
	Polynomial<FloatSemiring> f1 = Polynomial<FloatSemiring>({
		Monomial<FloatSemiring>(FloatSemiring(0.4), {Var("x"),Var("y")}),
		Monomial<FloatSemiring>(FloatSemiring(0.6), {}) });

	// define new polynomial 0.3yz+0.4yx+0.3
	Polynomial<FloatSemiring> f2 = Polynomial<FloatSemiring>({
		Monomial<FloatSemiring>(FloatSemiring(0.3), {Var("y"),Var("z")}),
		Monomial<FloatSemiring>(FloatSemiring(0.4), {Var("y"),Var("x")}),
		Monomial<FloatSemiring>(FloatSemiring(0.3), {}) });

	// define new polynomial 0.3x+0.7
	Polynomial<FloatSemiring> f3 =  Polynomial<FloatSemiring>({
		Monomial<FloatSemiring>(FloatSemiring(0.3), {Var("x")}),
		Monomial<FloatSemiring>(FloatSemiring(0.7), {}) });
	polynomials.push_back(f1);
	polynomials.push_back(f2);
	polynomials.push_back(f3);

	return polynomials;
}

void test_newton()
{
	/*
	Newton<FloatSemiring> newton;
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	variables.push_back(Var("y"));
	variables.push_back(Var("z"));
	std::cout << "- newton (float):" << std::endl;
	std::vector<Polynomial<FloatSemiring> > polynomials = get_newton_test_polynomials();
	Matrix<FloatSemiring> result = newton.solve_fixpoint(polynomials, variables, 2);
	std::cout << result << std::endl;

*/

/*
	Newton<FreeSemiring> newton;
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	std::cout << "- newton (free-SR):" << std::endl;

	std::vector<Polynomial<FreeSemiring> > polynomials;
	Polynomial<FreeSemiring> f1 = Polynomial<FreeSemiring>({
		Monomial<FreeSemiring>(FreeSemiring(Var("a")), {Var("x"),Var("x")}),
		Monomial<FreeSemiring>(FreeSemiring(Var("c")), {}) });

	polynomials.push_back(f1);

	Matrix<FreeSemiring> result = newton.solve_fixpoint(polynomials, variables, 2);
	std::cout << result << std::endl;
	*/

	Newton<SemilinSetExp> newton;
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	std::cout << "- newton (counting-SR):" << std::endl;

	std::vector<Polynomial<SemilinSetExp> > polynomials;
	Polynomial<SemilinSetExp> f1 = Polynomial<SemilinSetExp>({
		Monomial<SemilinSetExp>(SemilinSetExp(Var("a")), {Var("x"),Var("x")}),
		Monomial<SemilinSetExp>(SemilinSetExp(Var("c")), {}) });

	polynomials.push_back(f1);

	Matrix<SemilinSetExp> result = newton.solve_fixpoint(polynomials, variables, 2);
	std::cout << result << std::endl;

}

int main(int argc, char* argv[])
{
	std::cout << "testing..." << std::endl;
	//test_addition();
	//test_multiplication();
	//test_variables();
	//test_monomials();
	//test_polynomial_addition();
	//test_polynomial_multiplication();
	//test_polynomial_evaluation();
	//test_matrix_addition();
	//test_matrix_multiplication();
	//test_matrix_transpose();
	//test_matrix_star();
	//test_jacobian();
	//test_polynomial_matrix_evaluation();
	//test_freesemiring();
	//test_polynomial_to_freesemiring();
	//test_newton();

	return 0;
}
<commit_msg>new testcase (in main)<commit_after>#include <iostream>
#include "float-semiring.h"
#include "free-semiring.h"
//#include "semilinSetExp.h"
#include "matrix.h"
#include "polynomial.h"
#include "newton.h"
#include "commutativeRExp.h"

void test_addition()
{
	FloatSemiring first(0.5);
	FloatSemiring second(0.3);
	FloatSemiring result = first + second;
	std::cout << "- float semiring addition: " << std::endl;
	std::cout << first << " + " << second << " = " << result << std::endl;
}

void test_multiplication()
{
	FloatSemiring first(0.5);
	FloatSemiring second(0.3);
	FloatSemiring result = first * second;
	std::cout << "- float semiring multiplication: " << std::endl;
	std::cout << first << " * " << second << " = " << result << std::endl;
}

void test_variables()
{
	Var var1;
	Var var2;
	std::cout << "- variables:" << std::endl;
	std::cout << var1 << "," << var2 << std::endl;
}

void test_monomials()
{
	std::cout << "- monomials:" << std::endl;
	Monomial<FloatSemiring> mon1(FloatSemiring(5),{Var("x"),Var("x"),Var("y")});
	Monomial<FloatSemiring> mon2(FloatSemiring(2),{Var("y"), Var("x")});
	Monomial<FloatSemiring> res1 = mon1 + mon1;
	Monomial<FloatSemiring> res2 = mon1 * mon2;
	std::cout << mon1 << " + " << mon1 << " = " << res1 << std::endl;
	std::cout << mon1 << " * " << mon2 << " = " << res2 << std::endl;
	std::cout << "derivative of " << mon1 << " = " << mon1.derivative(Var("x")) << std::endl;
}

Polynomial<FloatSemiring> get_first_polynomial()
{
	// define new polynomial 2xx+7y
	return Polynomial<FloatSemiring>(
			{	Monomial<FloatSemiring>(FloatSemiring(2),{Var("x"),Var("x")}),
				Monomial<FloatSemiring>(FloatSemiring(7),{Var("z")}) });
}

Polynomial<FloatSemiring> get_second_polynomial()
{
	// define new polynomial 5xx+3xy+6yy
	return Polynomial<FloatSemiring>(
			{	Monomial<FloatSemiring>(FloatSemiring(5),{Var("x"),Var("x")}),
				Monomial<FloatSemiring>(FloatSemiring(3),{Var("x"),Var("y")}),
				Monomial<FloatSemiring>(FloatSemiring(6),{Var("y"),Var("y")})});
}

void test_polynomial_addition()
{
	Polynomial<FloatSemiring> first = get_first_polynomial();
	Polynomial<FloatSemiring> second = get_second_polynomial();
	Polynomial<FloatSemiring> result = first + second;
	std::cout << "- polynomial addition:" << std::endl;
	std::cout << first << " + " << second << " = " << result << std::endl;
}

void test_polynomial_multiplication()
{
	Polynomial<FloatSemiring> first = get_first_polynomial();
	Polynomial<FloatSemiring> second = get_second_polynomial();
	Polynomial<FloatSemiring> result = first * second;
	std::cout << "- polynomial multiplication:" << std::endl;
	std::cout << first << " * " << second << " = " << result << std::endl;
}

std::map<Var,FloatSemiring> get_variable_values()
{
	std::map<Var,FloatSemiring> values;
	values.insert(values.begin(), std::pair<Var,FloatSemiring>(Var("x"),FloatSemiring(5)));
	values.insert(values.begin(), std::pair<Var,FloatSemiring>(Var("y"),FloatSemiring(4)));
	values.insert(values.begin(), std::pair<Var,FloatSemiring>(Var("z"),FloatSemiring(0)));
	return values;
}

void test_polynomial_evaluation()
{
	Polynomial<FloatSemiring> polynomial = get_second_polynomial();
	std::map<Var,FloatSemiring> values = get_variable_values();
	FloatSemiring result = polynomial.eval(values);
	std::cout << "- polynomial evaluation:" << std::endl;
	std::cout << polynomial << " at {x=5, y=4, z=0} = " << result << std::endl;
}

Matrix<FloatSemiring> get_first_matrix()
{
	FloatSemiring elems[] = {
		FloatSemiring(0.5), FloatSemiring(0.9),
		FloatSemiring(0.2), FloatSemiring(0.1)};
	return Matrix<FloatSemiring>(2,2,std::vector<FloatSemiring>(elems, elems+4));
}

Matrix<FloatSemiring> get_second_matrix()
{
	FloatSemiring elems[] = {
		FloatSemiring(0.3), FloatSemiring(0.1),
		FloatSemiring(0.7), FloatSemiring(0.2)};
	return Matrix<FloatSemiring>(2,2,std::vector<FloatSemiring>(elems, elems+4));
}

Matrix<FreeSemiring> get_star_test_matrix()
{
/*	FloatSemiring elems[] = {
		FloatSemiring(0.6), FloatSemiring(0.1), FloatSemiring(0.1),
		FloatSemiring(0.1), FloatSemiring(0.4), FloatSemiring(0.1),
		FloatSemiring(0.1), FloatSemiring(0.1), FloatSemiring(0.3)};
	return Matrix<FloatSemiring>(3,3,std::vector<FloatSemiring>(elems, elems+9));
*/
	FreeSemiring elems[]  = {
		FreeSemiring(Var("a")),
		FreeSemiring(Var("b")),
		FreeSemiring(Var("c")),
		FreeSemiring(Var("d")) };
	return Matrix<FreeSemiring>(2,2,std::vector<FreeSemiring>(elems, elems+4));
}

void test_matrix_addition()
{
	Matrix<FloatSemiring> first = get_first_matrix();
	Matrix<FloatSemiring> second = get_second_matrix();
	Matrix<FloatSemiring> result = first + second;
	std::cout << "- matrix addition:" << std::endl;
	std::cout << first << " + " << std::endl << second << " = " << std::endl << result;
}

void test_matrix_multiplication()
{
	Matrix<FloatSemiring> first = get_first_matrix();
	Matrix<FloatSemiring> second = get_second_matrix();
	Matrix<FloatSemiring> result = first * second;
	std::cout << "- matrix multiplication:" << std::endl;
	std::cout << first << " * " << std::endl << second << " = " << std::endl << result;
}

void test_matrix_transpose()
{
	Matrix<FloatSemiring> matrix = get_first_matrix();
	Matrix<FloatSemiring> result = matrix.transpose();
	std::cout << "- matrix transpose:" << std::endl;
	std::cout << matrix << " transposed " << std::endl << result;
}

void test_matrix_star()
{
	auto matrix = get_star_test_matrix();
	auto result = matrix.star();
	std::cout << "- matrix star:" << std::endl;
	std::cout << matrix << " the matrix star of this is: " << std::endl << result;
}

void test_jacobian()
{
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	variables.push_back(Var("y"));
	variables.push_back(Var("z"));
	std::vector<Polynomial<FloatSemiring> > polynomials;
	polynomials.push_back(get_first_polynomial());
	polynomials.push_back(get_second_polynomial());
	Matrix<Polynomial<FloatSemiring> > jacobian = Polynomial<FloatSemiring>::jacobian(polynomials, variables);
	std::cout << "- jacobian (x,y,z) of " << std::endl;
	std::cout << polynomials.at(0) << std::endl << polynomials.at(1) << std::endl << " = " << std::endl << jacobian << std::endl;
}

void test_polynomial_matrix_evaluation()
{
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	variables.push_back(Var("y"));
	variables.push_back(Var("z"));
	std::vector<Polynomial<FloatSemiring> > polynomials;
	polynomials.push_back(get_first_polynomial());
	polynomials.push_back(get_second_polynomial());
	Matrix<Polynomial<FloatSemiring> > polynomial_matrix = Polynomial<FloatSemiring>::jacobian(polynomials, variables);
	std::map<Var,FloatSemiring> values = get_variable_values();
	Matrix<FloatSemiring> result = Polynomial<FloatSemiring>::eval(polynomial_matrix, values);
	std::cout << "- polynomial matrix evaluation" << std::endl;
	std::cout << polynomial_matrix << " at {x=5, y=4, z=0} = " << std::endl << result;
}

void test_freesemiring()
{
	std::cout << "- free semiring" << std::endl;
	FreeSemiring term1 = FreeSemiring(Var("a"));
	FreeSemiring term2 = FreeSemiring(Var("b"));
	std::cout << "some terms: " <<  term1 << " and " << term2 << std::endl;
	FreeSemiring termAdd = term1 + term2;
	FreeSemiring termMul = term1 * term2;
	std::cout << "addition&multiplication&star: " << (termAdd*termMul.star()) << std::endl;
}

void test_polynomial_to_freesemiring()
{
	std::cout << "- polynomial to free semiring conversion" <<std::endl;
	Polynomial<FloatSemiring> poly = get_first_polynomial();
	auto valuation = new std::unordered_map<FloatSemiring, FreeSemiring, FloatSemiring>();
	FreeSemiring elem = poly.make_free(valuation);
	for(auto v_it = valuation->begin(); v_it != valuation->end(); ++v_it)
	{
		std::cout << "valuation: " << v_it->first << " → " << v_it->second << std::endl;
	}
	std::cout << "polynomial: " << poly << std::endl;
	std::cout << "free semiring: " << elem << std::endl;
}

std::vector<Polynomial<FloatSemiring> > get_newton_test_polynomials()
{
	std::vector<Polynomial<FloatSemiring> > polynomials;

	// define new polynomial 0.4xy+0.6
	Polynomial<FloatSemiring> f1 = Polynomial<FloatSemiring>({
		Monomial<FloatSemiring>(FloatSemiring(0.4), {Var("x"),Var("y")}),
		Monomial<FloatSemiring>(FloatSemiring(0.6), {}) });

	// define new polynomial 0.3yz+0.4yx+0.3
	Polynomial<FloatSemiring> f2 = Polynomial<FloatSemiring>({
		Monomial<FloatSemiring>(FloatSemiring(0.3), {Var("y"),Var("z")}),
		Monomial<FloatSemiring>(FloatSemiring(0.4), {Var("y"),Var("x")}),
		Monomial<FloatSemiring>(FloatSemiring(0.3), {}) });

	// define new polynomial 0.3x+0.7
	Polynomial<FloatSemiring> f3 =  Polynomial<FloatSemiring>({
		Monomial<FloatSemiring>(FloatSemiring(0.3), {Var("x")}),
		Monomial<FloatSemiring>(FloatSemiring(0.7), {}) });
	polynomials.push_back(f1);
	polynomials.push_back(f2);
	polynomials.push_back(f3);

	return polynomials;
}

void test_newton()
{
	/*
	Newton<FloatSemiring> newton;
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	variables.push_back(Var("y"));
	variables.push_back(Var("z"));
	std::cout << "- newton (float):" << std::endl;
	std::vector<Polynomial<FloatSemiring> > polynomials = get_newton_test_polynomials();
	Matrix<FloatSemiring> result = newton.solve_fixpoint(polynomials, variables, 2);
	std::cout << result << std::endl;

*/

/*
	Newton<FreeSemiring> newton;
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	std::cout << "- newton (free-SR):" << std::endl;

	std::vector<Polynomial<FreeSemiring> > polynomials;
	Polynomial<FreeSemiring> f1 = Polynomial<FreeSemiring>({
		Monomial<FreeSemiring>(FreeSemiring(Var("a")), {Var("x"),Var("x")}),
		Monomial<FreeSemiring>(FreeSemiring(Var("c")), {}) });

	polynomials.push_back(f1);

	Matrix<FreeSemiring> result = newton.solve_fixpoint(polynomials, variables, 2);
	std::cout << result << std::endl;
	*/

	Newton<CommutativeRExp> newton;
	std::vector<Var> variables;
	variables.push_back(Var("x"));
	variables.push_back(Var("y"));
	variables.push_back(Var("z"));
	std::cout << "- newton (counting-SR):" << std::endl;

	std::vector<Polynomial<CommutativeRExp> > polynomials;
	// define new polynomial axy+b
	Polynomial<CommutativeRExp> f1 = Polynomial<CommutativeRExp>({
		Monomial<CommutativeRExp>(CommutativeRExp(Var("a")), {Var("x"),Var("y")}),
		Monomial<CommutativeRExp>(CommutativeRExp(Var("b")), {}) });

	// define new polynomial cyz+dyx+e
	Polynomial<CommutativeRExp> f2 = Polynomial<CommutativeRExp>({
		Monomial<CommutativeRExp>(CommutativeRExp(Var("c")), {Var("y"),Var("z")}),
		Monomial<CommutativeRExp>(CommutativeRExp(Var("d")), {Var("y"),Var("x")}),
		Monomial<CommutativeRExp>(CommutativeRExp(Var("e")), {}) });

	// define new polynomial fx+g
	Polynomial<CommutativeRExp> f3 =  Polynomial<CommutativeRExp>({
		Monomial<CommutativeRExp>(CommutativeRExp(Var("f")), {Var("x")}),
		Monomial<CommutativeRExp>(CommutativeRExp(Var("g")), {}) });
	polynomials.push_back(f1);
	polynomials.push_back(f2);
	polynomials.push_back(f3);

	Matrix<CommutativeRExp> result = newton.solve_fixpoint(polynomials, variables, 3);
	std::cout << result << std::endl;

}

int main(int argc, char* argv[])
{
	std::cout << "testing..." << std::endl;
	//test_addition();
	//test_multiplication();
	//test_variables();
	//test_monomials();
	//test_polynomial_addition();
	//test_polynomial_multiplication();
	//test_polynomial_evaluation();
	//test_matrix_addition();
	//test_matrix_multiplication();
	//test_matrix_transpose();
	//test_matrix_star();
	//test_jacobian();
	//test_polynomial_matrix_evaluation();
	//test_freesemiring();
	//test_polynomial_to_freesemiring();
	test_newton();

	return 0;
}
<|endoftext|>


<commit_before>#include <string>

#include <re2/re2.h>
#include "cre2.h"

#define TO_OPT(opt) (reinterpret_cast<RE2::Options *>(opt))

cre2_options *cre2_opt_new(void) {
    return reinterpret_cast<void*>(new RE2::Options());
}

void cre2_opt_delete(cre2_options *opt) {
    delete TO_OPT(opt);
}

#define OPT_bool(name)  \
void cre2_opt_##name(cre2_options *opt, int flag) {  \
    TO_OPT(opt)->set_##name(bool(flag));             \
}

OPT_bool(posix_syntax)
OPT_bool(longest_match)
OPT_bool(log_errors)
OPT_bool(literal)
OPT_bool(never_nl)
OPT_bool(case_sensitive)
OPT_bool(perl_classes)
OPT_bool(word_boundary)
OPT_bool(one_line)

#undef OPT_BOOL

void cre2_opt_encoding(cre2_options *opt, encoding_t enc) {
    switch (enc) {
        case CRE2_UTF8:
            TO_OPT(opt)->set_encoding(RE2::Options::EncodingUTF8);
            break;
        case CRE2_Latin1:
            TO_OPT(opt)->set_encoding(RE2::Options::EncodingLatin1);
            break;
    }
}

void cre2_opt_max_mem(cre2_options *opt, int m) {
    TO_OPT(opt)->set_max_mem(m);
}

#define TO_RE2(re)       (reinterpret_cast<RE2 *>(re))
#define TO_CONST_RE2(re) (reinterpret_cast<const RE2 *>(re))

cre2 *cre2_new(const char *pattern, const cre2_options *opt) {
    return reinterpret_cast<void*>(
        new RE2(pattern, *reinterpret_cast<const RE2::Options *>(opt)));
}

void cre2_delete(cre2 *re) {
    delete TO_RE2(re);
}

int cre2_error_code(const cre2 *re) {
    return int(TO_CONST_RE2(re)->error_code());
}

char *cre2_error_string(const cre2 *re) {
    return strdup(TO_CONST_RE2(re)->error().c_str());
}

char *cre2_error_arg(const cre2 *re) {
    return strdup(TO_CONST_RE2(re)->error_arg().c_str());
}

int cre2_num_capturing_groups(const cre2 *re) {
    return TO_CONST_RE2(re)->NumberOfCapturingGroups();
}

int cre2_program_size(const cre2 *re) {
    return TO_CONST_RE2(re)->ProgramSize();
}

int cre2_match(
    const cre2 *re
  , const char *text
  , int startpos
  , int endpos
  , anchor_t anchor
  , struct string_piece *match
  , int nmatch) {

    // FIXME: exceptions?
    re2::StringPiece *match_re2 = new re2::StringPiece[nmatch];

    RE2::Anchor anchor_re2;
    switch (anchor) {
        case CRE2_UNANCHORED:
            anchor_re2 = RE2::UNANCHORED;   break;
        case CRE2_ANCHOR_START:
            anchor_re2 = RE2::ANCHOR_START; break;
        case CRE2_ANCHOR_BOTH:
            anchor_re2 = RE2::ANCHOR_BOTH;  break;
    }

    bool ret = TO_CONST_RE2(re)
        ->Match(text, startpos, endpos, anchor_re2, match_re2, nmatch);

    if (ret) {
        for (int i=0; i<nmatch; i++) {
            match[i].data   = match_re2[i].data();
            match[i].length = match_re2[i].length();
        }
    }

    delete [] match_re2;

    return int(ret);
}
<commit_msg>initialize anchor_re2<commit_after>#include <string>

#include <re2/re2.h>
#include "cre2.h"

#define TO_OPT(opt) (reinterpret_cast<RE2::Options *>(opt))

cre2_options *cre2_opt_new(void) {
    return reinterpret_cast<void*>(new RE2::Options());
}

void cre2_opt_delete(cre2_options *opt) {
    delete TO_OPT(opt);
}

#define OPT_bool(name)  \
void cre2_opt_##name(cre2_options *opt, int flag) {  \
    TO_OPT(opt)->set_##name(bool(flag));             \
}

OPT_bool(posix_syntax)
OPT_bool(longest_match)
OPT_bool(log_errors)
OPT_bool(literal)
OPT_bool(never_nl)
OPT_bool(case_sensitive)
OPT_bool(perl_classes)
OPT_bool(word_boundary)
OPT_bool(one_line)

#undef OPT_BOOL

void cre2_opt_encoding(cre2_options *opt, encoding_t enc) {
    switch (enc) {
        case CRE2_UTF8:
            TO_OPT(opt)->set_encoding(RE2::Options::EncodingUTF8);
            break;
        case CRE2_Latin1:
            TO_OPT(opt)->set_encoding(RE2::Options::EncodingLatin1);
            break;
    }
}

void cre2_opt_max_mem(cre2_options *opt, int m) {
    TO_OPT(opt)->set_max_mem(m);
}

#define TO_RE2(re)       (reinterpret_cast<RE2 *>(re))
#define TO_CONST_RE2(re) (reinterpret_cast<const RE2 *>(re))

cre2 *cre2_new(const char *pattern, const cre2_options *opt) {
    return reinterpret_cast<void*>(
        new RE2(pattern, *reinterpret_cast<const RE2::Options *>(opt)));
}

void cre2_delete(cre2 *re) {
    delete TO_RE2(re);
}

int cre2_error_code(const cre2 *re) {
    return int(TO_CONST_RE2(re)->error_code());
}

char *cre2_error_string(const cre2 *re) {
    return strdup(TO_CONST_RE2(re)->error().c_str());
}

char *cre2_error_arg(const cre2 *re) {
    return strdup(TO_CONST_RE2(re)->error_arg().c_str());
}

int cre2_num_capturing_groups(const cre2 *re) {
    return TO_CONST_RE2(re)->NumberOfCapturingGroups();
}

int cre2_program_size(const cre2 *re) {
    return TO_CONST_RE2(re)->ProgramSize();
}

int cre2_match(
    const cre2 *re
  , const char *text
  , int startpos
  , int endpos
  , anchor_t anchor
  , struct string_piece *match
  , int nmatch) {

    // FIXME: exceptions?
    re2::StringPiece *match_re2 = new re2::StringPiece[nmatch];

    RE2::Anchor anchor_re2 = RE2::UNANCHORED;
    switch (anchor) {
        case CRE2_ANCHOR_START:
            anchor_re2 = RE2::ANCHOR_START; break;
        case CRE2_ANCHOR_BOTH:
            anchor_re2 = RE2::ANCHOR_BOTH;  break;
    }

    bool ret = TO_CONST_RE2(re)
        ->Match(text, startpos, endpos, anchor_re2, match_re2, nmatch);

    if (ret) {
        for (int i=0; i<nmatch; i++) {
            match[i].data   = match_re2[i].data();
            match[i].length = match_re2[i].length();
        }
    }

    delete [] match_re2;

    return int(ret);
}
<|endoftext|>


<commit_before>/* Copyright (c) 2015 Cornell University
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdio.h>
#include <assert.h>

#include "SonicUserRequest.h"
#include "SonicUserIndication.h"

#define NUMBER_OF_TESTS 1

static SonicUserRequestProxy *device = 0;
//static sem_t wait_log;

class SonicUser : public SonicUserIndicationWrapper
{
public:
  virtual void dtp_read_version_resp(uint32_t a) {
    fprintf(stderr, "read version %d\n", a);
  }

  virtual void dtp_read_delay_resp(uint8_t p, uint32_t a) {
    fprintf(stderr, "read delay(%d) %d\n", p, a);
  }
  virtual void dtp_read_state_resp(uint8_t p, uint32_t a) {
    fprintf(stderr, "read state(%d) %d\n", p, a);
  }
  virtual void dtp_read_error_resp(uint8_t p, uint64_t a) {
    fprintf(stderr, "read error(%d) %ld\n", p, a);
  }
  virtual void dtp_read_cnt_resp(uint64_t a) {
    fprintf(stderr, "readCycleCount(%lx)\n", a);
  }
  virtual void dtp_logger_read_cnt_resp(uint8_t a, uint64_t b, uint64_t c, uint64_t d) {
	fprintf(stderr, "read from port(%d) local_cnt(%lx) msg1(%lx) msg2(%lx)\n", a, b, c, d);
  }
  virtual void dtp_read_local_cnt_resp(uint8_t p, uint64_t a) {
	fprintf(stderr, "read from port(%d) local_cnt(%lx)\n", p, a);
  }
  virtual void dtp_read_global_cnt_resp(uint64_t a) {
	fprintf(stderr, "read global_cnt(%lx)\n", a);
  }
  virtual void dtp_read_beacon_interval_resp(uint8_t p, uint32_t a) {
	fprintf(stderr, "read from port(%d) local_cnt(%x)\n", p, a);
  }
  virtual void dtp_debug_rcvd_msg_resp(uint8_t p, uint32_t a, uint32_t b, uint32_t c) {
	fprintf(stderr, "read from port(%d) enq1(%x) enq2(%x) deq(%x)\n", p, a, b, c);
  }
  virtual void dtp_debug_sent_msg_resp(uint8_t p, uint32_t a, uint32_t b, uint32_t c) {
	fprintf(stderr, "read from port(%d) enq(%x) deq1(%x) deq2(%x)\n", p, a, b, c);
  }
  virtual void dtp_debug_rcvd_err_resp(uint8_t p, uint32_t a) {
	fprintf(stderr, "read from port(%d) err(%x)\n", p, a);
  }
  virtual void dtp_get_mode_resp(uint8_t a) {
	fprintf(stderr, "read from mode(%x)\n", a);
  }

  SonicUser(unsigned int id) : SonicUserIndicationWrapper(id) {}
};

int main(int argc, const char **argv)
{
	uint32_t count = 100;
	SonicUser indication(IfcNames_SonicUserIndicationH2S);
	device = new SonicUserRequestProxy(IfcNames_SonicUserRequestS2H);
	device->pint.busyType = BUSY_SPIN;   /* spin until request portal 'notFull' */

	device->dtp_reset(32);
    device->dtp_get_mode();
	device->dtp_read_version();

	fprintf(stderr, "Main::about to go to sleep\n");
	while(true){
		for (int i=0; i<1; i++) {
			device->dtp_read_delay(i);
			device->dtp_read_state(i);
			device->dtp_read_error(i);
			device->dtp_read_cnt(i);
		}
		sleep(1);
		for (int i=0; i<4; i++) {
			device->dtp_logger_write_cnt(i, count);
		}
		for (int i=0; i<4; i++) {
			device->dtp_logger_read_cnt(i);
		}
		count ++;
		sleep(1);
	}
}
<commit_msg>fixed test-dtp<commit_after>/* Copyright (c) 2015 Cornell University
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <stdio.h>
#include <assert.h>

#include "DtpUserRequest.h"
#include "DtpUserIndication.h"

#define NUMBER_OF_TESTS 1

static DtpUserRequestProxy *device = 0;
//static sem_t wait_log;

class DtpUser : public DtpUserIndicationWrapper
{
public:
  virtual void dtp_read_version_resp(uint32_t a) {
    fprintf(stderr, "read version %d\n", a);
  }

  virtual void dtp_read_delay_resp(uint8_t p, uint32_t a) {
    fprintf(stderr, "read delay(%d) %d\n", p, a);
  }
  virtual void dtp_read_state_resp(uint8_t p, uint32_t a) {
    fprintf(stderr, "read state(%d) %d\n", p, a);
  }
  virtual void dtp_read_error_resp(uint8_t p, uint64_t a) {
    fprintf(stderr, "read error(%d) %ld\n", p, a);
  }
  virtual void dtp_read_cnt_resp(uint64_t a) {
    fprintf(stderr, "readCycleCount(%lx)\n", a);
  }
  virtual void dtp_logger_read_cnt_resp(uint8_t a, uint64_t b, uint64_t c, uint64_t d) {
	fprintf(stderr, "read from port(%d) local_cnt(%lx) msg1(%lx) msg2(%lx)\n", a, b, c, d);
  }
  virtual void dtp_read_local_cnt_resp(uint8_t p, uint64_t a) {
	fprintf(stderr, "read from port(%d) local_cnt(%lx)\n", p, a);
  }
  virtual void dtp_read_global_cnt_resp(uint64_t a) {
	fprintf(stderr, "read global_cnt(%lx)\n", a);
  }
  virtual void dtp_read_beacon_interval_resp(uint8_t p, uint32_t a) {
	fprintf(stderr, "read from port(%d) local_cnt(%x)\n", p, a);
  }
  virtual void dtp_debug_rcvd_msg_resp(uint8_t p, uint32_t a, uint32_t b, uint32_t c) {
	fprintf(stderr, "read from port(%d) enq1(%x) enq2(%x) deq(%x)\n", p, a, b, c);
  }
  virtual void dtp_debug_sent_msg_resp(uint8_t p, uint32_t a, uint32_t b, uint32_t c) {
	fprintf(stderr, "read from port(%d) enq(%x) deq1(%x) deq2(%x)\n", p, a, b, c);
  }
  virtual void dtp_debug_rcvd_err_resp(uint8_t p, uint32_t a) {
	fprintf(stderr, "read from port(%d) err(%x)\n", p, a);
  }
  virtual void dtp_get_mode_resp(uint8_t a) {
	fprintf(stderr, "read from mode(%x)\n", a);
  }

  DtpUser(unsigned int id) : DtpUserIndicationWrapper(id) {}
};

int main(int argc, const char **argv)
{
	uint32_t count = 100;
	DtpUser indication(IfcNames_DtpUserIndicationH2S);
	device = new DtpUserRequestProxy(IfcNames_DtpUserRequestS2H);
	device->pint.busyType = BUSY_SPIN;   /* spin until request portal 'notFull' */

	device->dtp_reset(32);
    device->dtp_get_mode();
	device->dtp_read_version();

	fprintf(stderr, "Main::about to go to sleep\n");
	while(true){
		for (int i=0; i<1; i++) {
			device->dtp_read_delay(i);
			device->dtp_read_state(i);
			device->dtp_read_error(i);
			device->dtp_read_cnt(i);
		}
		sleep(1);
		for (int i=0; i<4; i++) {
			device->dtp_logger_write_cnt(i, count);
		}
		for (int i=0; i<4; i++) {
			device->dtp_logger_read_cnt(i);
		}
		count ++;
		sleep(1);
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/scoped_temp_dir.h"
#include "base/test/thread_test_helper.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/in_process_webkit/indexed_db_context.h"
#include "content/browser/in_process_webkit/webkit_context.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/public/common/content_switches.h"
#include "webkit/database/database_util.h"
#include "webkit/quota/mock_special_storage_policy.h"
#include "webkit/quota/quota_manager.h"
#include "webkit/quota/special_storage_policy.h"

using content::BrowserThread;
using quota::QuotaManager;
using webkit_database::DatabaseUtil;

// This browser test is aimed towards exercising the IndexedDB bindings and
// the actual implementation that lives in the browser side (in_process_webkit).
class IndexedDBBrowserTest : public InProcessBrowserTest {
 public:
  IndexedDBBrowserTest() {
    EnableDOMAutomation();
  }

  GURL testUrl(const FilePath& file_path) {
    const FilePath kTestDir(FILE_PATH_LITERAL("indexeddb"));
    return ui_test_utils::GetTestUrl(kTestDir, file_path);
  }

  void SimpleTest(const GURL& test_url, bool incognito = false) {
    // The test page will perform tests on IndexedDB, then navigate to either
    // a #pass or #fail ref.
    Browser* the_browser = incognito ? CreateIncognitoBrowser() : browser();

    LOG(INFO) << "Navigating to URL and blocking.";
    ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
        the_browser, test_url, 2);
    LOG(INFO) << "Navigation done.";
    std::string result = the_browser->GetSelectedWebContents()->GetURL().ref();
    if (result != "pass") {
      std::string js_result;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
          the_browser->GetSelectedWebContents()->GetRenderViewHost(), L"",
          L"window.domAutomationController.send(getLog())", &js_result));
      FAIL() << "Failed: " << js_result;
    }
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTestIncognito) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))),
             true /* incognito */);
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorPrefetch) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_prefetch.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_IndexTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_KeyPathTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionGetTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_get_test.html"))));
}

#if defined(OS_WIN)
// http://crbug.com/104306
#define KeyTypesTest FLAKY_KeyTypesTest
#endif
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, KeyTypesTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_types_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_ObjectStoreTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("object_store_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DatabaseTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("database_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_TransactionTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_DoesntHangTest) {
  SimpleTest(testUrl(FilePath(
      FILE_PATH_LITERAL("transaction_run_forever.html"))));
  ui_test_utils::CrashTab(browser()->GetSelectedWebContents());
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug84933Test) {
  const GURL url = testUrl(FilePath(FILE_PATH_LITERAL("bug_84933.html")));

  // Just navigate to the URL. Test will crash if it fails.
  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 1);
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug106883Test) {
  const GURL url = testUrl(FilePath(FILE_PATH_LITERAL("bug_106883.html")));

  // Just navigate to the URL. Test will crash if it fails.
  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 1);
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug109187Test) {
  const GURL url = testUrl(FilePath(FILE_PATH_LITERAL("bug_109187.html")));

  // Just navigate to the URL. Test will crash if it fails.
  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 1);
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearLocalState) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  FilePath protected_path;
  FilePath unprotected_path;

  // Create the scope which will ensure we run the destructor of the webkit
  // context which should trigger the clean up.
  {
    TestingProfile profile;

    // Test our assumptions about what is protected and what is not.
    const GURL kProtectedOrigin("chrome-extension://foo/");
    const GURL kUnprotectedOrigin("http://foo/");
    quota::SpecialStoragePolicy* policy = profile.GetSpecialStoragePolicy();
    ASSERT_TRUE(policy->IsStorageProtected(kProtectedOrigin));
    ASSERT_FALSE(policy->IsStorageProtected(kUnprotectedOrigin));

    // Create some indexedDB paths.
    // With the levelDB backend, these are directories.
    WebKitContext *webkit_context = profile.GetWebKitContext();
    IndexedDBContext* idb_context = webkit_context->indexed_db_context();
    idb_context->set_data_path_for_testing(temp_dir.path());
    protected_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kProtectedOrigin));
    unprotected_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kUnprotectedOrigin));
    ASSERT_TRUE(file_util::CreateDirectory(protected_path));
    ASSERT_TRUE(file_util::CreateDirectory(unprotected_path));

    // Setup to clear all unprotected origins on exit.
    webkit_context->set_clear_local_state_on_exit(true);
  }

  // Make sure we wait until the destructor has run.
  scoped_refptr<base::ThreadTestHelper> helper(
      new base::ThreadTestHelper(
          BrowserThread::GetMessageLoopProxyForThread(
              BrowserThread::WEBKIT_DEPRECATED)));
  ASSERT_TRUE(helper->Run());

  ASSERT_TRUE(file_util::DirectoryExists(protected_path));
  ASSERT_FALSE(file_util::DirectoryExists(unprotected_path));
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearSessionOnlyDatabases) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  FilePath normal_path;
  FilePath session_only_path;

  // Create the scope which will ensure we run the destructor of the webkit
  // context which should trigger the clean up.
  {
    TestingProfile profile;

    const GURL kNormalOrigin("http://normal/");
    const GURL kSessionOnlyOrigin("http://session-only/");
    scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
        new quota::MockSpecialStoragePolicy;
    special_storage_policy->AddSessionOnly(kSessionOnlyOrigin);

    // Create some indexedDB paths.
    // With the levelDB backend, these are directories.
    WebKitContext *webkit_context = profile.GetWebKitContext();
    IndexedDBContext* idb_context = webkit_context->indexed_db_context();

    // Override the storage policy with our own.
    idb_context->special_storage_policy_ = special_storage_policy;
    idb_context->set_data_path_for_testing(temp_dir.path());

    normal_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kNormalOrigin));
    session_only_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kSessionOnlyOrigin));
    ASSERT_TRUE(file_util::CreateDirectory(normal_path));
    ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
  }

  // Make sure we wait until the destructor has run.
  scoped_refptr<base::ThreadTestHelper> helper(
      new base::ThreadTestHelper(
          BrowserThread::GetMessageLoopProxyForThread(
              BrowserThread::WEBKIT_DEPRECATED)));
  ASSERT_TRUE(helper->Run());

  EXPECT_TRUE(file_util::DirectoryExists(normal_path));
  EXPECT_FALSE(file_util::DirectoryExists(session_only_path));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, SaveSessionState) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  FilePath normal_path;
  FilePath session_only_path;

  // Create the scope which will ensure we run the destructor of the webkit
  // context.
  {
    TestingProfile profile;

    const GURL kNormalOrigin("http://normal/");
    const GURL kSessionOnlyOrigin("http://session-only/");
    scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
        new quota::MockSpecialStoragePolicy;
    special_storage_policy->AddSessionOnly(kSessionOnlyOrigin);

    // Create some indexedDB paths.
    // With the levelDB backend, these are directories.
    WebKitContext *webkit_context = profile.GetWebKitContext();
    IndexedDBContext* idb_context = webkit_context->indexed_db_context();

    // Override the storage policy with our own.
    idb_context->special_storage_policy_ = special_storage_policy;
    idb_context->set_clear_local_state_on_exit(true);
    idb_context->set_data_path_for_testing(temp_dir.path());

    // Save session state. This should bypass the destruction-time deletion.
    idb_context->SaveSessionState();

    normal_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kNormalOrigin));
    session_only_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kSessionOnlyOrigin));
    ASSERT_TRUE(file_util::CreateDirectory(normal_path));
    ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
  }

  // Make sure we wait until the destructor has run.
  scoped_refptr<base::ThreadTestHelper> helper(
      new base::ThreadTestHelper(
          BrowserThread::GetMessageLoopProxyForThread(
              BrowserThread::WEBKIT_DEPRECATED)));
  ASSERT_TRUE(helper->Run());

  // No data was cleared because of SaveSessionState.
  EXPECT_TRUE(file_util::DirectoryExists(normal_path));
  EXPECT_TRUE(file_util::DirectoryExists(session_only_path));
}

class IndexedDBBrowserTestWithLowQuota : public IndexedDBBrowserTest {
 public:
  virtual void SetUpOnMainThread() {
    const int kInitialQuotaKilobytes = 5000;
    const int kTemporaryStorageQuotaMaxSize = kInitialQuotaKilobytes
        * 1024 * QuotaManager::kPerHostTemporaryPortion;
    SetTempQuota(
        kTemporaryStorageQuotaMaxSize, browser()->profile()->GetQuotaManager());
  }

  static void SetTempQuota(int64 bytes, scoped_refptr<QuotaManager> qm) {
    if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
      BrowserThread::PostTask(
          BrowserThread::IO, FROM_HERE,
          base::Bind(&IndexedDBBrowserTestWithLowQuota::SetTempQuota, bytes,
                     qm));
      return;
    }
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    qm->SetTemporaryGlobalOverrideQuota(bytes, quota::QuotaCallback());
    // Don't return until the quota has been set.
    scoped_refptr<base::ThreadTestHelper> helper(
        new base::ThreadTestHelper(
            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)));
    ASSERT_TRUE(helper->Run());
  }

};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithLowQuota, FAILS_QuotaTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("quota_test.html"))));
}

class IndexedDBBrowserTestWithGCExposed : public IndexedDBBrowserTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed,
                       DatabaseCallbacksTest) {
  SimpleTest(
      testUrl(FilePath(FILE_PATH_LITERAL("database_callbacks_first.html"))));
}
<commit_msg>Mark IndexeDBBrowserTestWithLowQuota.QuotaTest test as DISABLED.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/scoped_temp_dir.h"
#include "base/test/thread_test_helper.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/in_process_webkit/indexed_db_context.h"
#include "content/browser/in_process_webkit/webkit_context.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/public/common/content_switches.h"
#include "webkit/database/database_util.h"
#include "webkit/quota/mock_special_storage_policy.h"
#include "webkit/quota/quota_manager.h"
#include "webkit/quota/special_storage_policy.h"

using content::BrowserThread;
using quota::QuotaManager;
using webkit_database::DatabaseUtil;

// This browser test is aimed towards exercising the IndexedDB bindings and
// the actual implementation that lives in the browser side (in_process_webkit).
class IndexedDBBrowserTest : public InProcessBrowserTest {
 public:
  IndexedDBBrowserTest() {
    EnableDOMAutomation();
  }

  GURL testUrl(const FilePath& file_path) {
    const FilePath kTestDir(FILE_PATH_LITERAL("indexeddb"));
    return ui_test_utils::GetTestUrl(kTestDir, file_path);
  }

  void SimpleTest(const GURL& test_url, bool incognito = false) {
    // The test page will perform tests on IndexedDB, then navigate to either
    // a #pass or #fail ref.
    Browser* the_browser = incognito ? CreateIncognitoBrowser() : browser();

    LOG(INFO) << "Navigating to URL and blocking.";
    ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
        the_browser, test_url, 2);
    LOG(INFO) << "Navigation done.";
    std::string result = the_browser->GetSelectedWebContents()->GetURL().ref();
    if (result != "pass") {
      std::string js_result;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
          the_browser->GetSelectedWebContents()->GetRenderViewHost(), L"",
          L"window.domAutomationController.send(getLog())", &js_result));
      FAIL() << "Failed: " << js_result;
    }
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTestIncognito) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))),
             true /* incognito */);
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorPrefetch) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_prefetch.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_IndexTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_KeyPathTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionGetTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_get_test.html"))));
}

#if defined(OS_WIN)
// http://crbug.com/104306
#define KeyTypesTest FLAKY_KeyTypesTest
#endif
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, KeyTypesTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_types_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_ObjectStoreTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("object_store_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DatabaseTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("database_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_TransactionTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// Flaky: http://crbug.com/70773
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_DoesntHangTest) {
  SimpleTest(testUrl(FilePath(
      FILE_PATH_LITERAL("transaction_run_forever.html"))));
  ui_test_utils::CrashTab(browser()->GetSelectedWebContents());
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug84933Test) {
  const GURL url = testUrl(FilePath(FILE_PATH_LITERAL("bug_84933.html")));

  // Just navigate to the URL. Test will crash if it fails.
  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 1);
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug106883Test) {
  const GURL url = testUrl(FilePath(FILE_PATH_LITERAL("bug_106883.html")));

  // Just navigate to the URL. Test will crash if it fails.
  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 1);
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug109187Test) {
  const GURL url = testUrl(FilePath(FILE_PATH_LITERAL("bug_109187.html")));

  // Just navigate to the URL. Test will crash if it fails.
  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 1);
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearLocalState) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  FilePath protected_path;
  FilePath unprotected_path;

  // Create the scope which will ensure we run the destructor of the webkit
  // context which should trigger the clean up.
  {
    TestingProfile profile;

    // Test our assumptions about what is protected and what is not.
    const GURL kProtectedOrigin("chrome-extension://foo/");
    const GURL kUnprotectedOrigin("http://foo/");
    quota::SpecialStoragePolicy* policy = profile.GetSpecialStoragePolicy();
    ASSERT_TRUE(policy->IsStorageProtected(kProtectedOrigin));
    ASSERT_FALSE(policy->IsStorageProtected(kUnprotectedOrigin));

    // Create some indexedDB paths.
    // With the levelDB backend, these are directories.
    WebKitContext *webkit_context = profile.GetWebKitContext();
    IndexedDBContext* idb_context = webkit_context->indexed_db_context();
    idb_context->set_data_path_for_testing(temp_dir.path());
    protected_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kProtectedOrigin));
    unprotected_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kUnprotectedOrigin));
    ASSERT_TRUE(file_util::CreateDirectory(protected_path));
    ASSERT_TRUE(file_util::CreateDirectory(unprotected_path));

    // Setup to clear all unprotected origins on exit.
    webkit_context->set_clear_local_state_on_exit(true);
  }

  // Make sure we wait until the destructor has run.
  scoped_refptr<base::ThreadTestHelper> helper(
      new base::ThreadTestHelper(
          BrowserThread::GetMessageLoopProxyForThread(
              BrowserThread::WEBKIT_DEPRECATED)));
  ASSERT_TRUE(helper->Run());

  ASSERT_TRUE(file_util::DirectoryExists(protected_path));
  ASSERT_FALSE(file_util::DirectoryExists(unprotected_path));
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearSessionOnlyDatabases) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  FilePath normal_path;
  FilePath session_only_path;

  // Create the scope which will ensure we run the destructor of the webkit
  // context which should trigger the clean up.
  {
    TestingProfile profile;

    const GURL kNormalOrigin("http://normal/");
    const GURL kSessionOnlyOrigin("http://session-only/");
    scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
        new quota::MockSpecialStoragePolicy;
    special_storage_policy->AddSessionOnly(kSessionOnlyOrigin);

    // Create some indexedDB paths.
    // With the levelDB backend, these are directories.
    WebKitContext *webkit_context = profile.GetWebKitContext();
    IndexedDBContext* idb_context = webkit_context->indexed_db_context();

    // Override the storage policy with our own.
    idb_context->special_storage_policy_ = special_storage_policy;
    idb_context->set_data_path_for_testing(temp_dir.path());

    normal_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kNormalOrigin));
    session_only_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kSessionOnlyOrigin));
    ASSERT_TRUE(file_util::CreateDirectory(normal_path));
    ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
  }

  // Make sure we wait until the destructor has run.
  scoped_refptr<base::ThreadTestHelper> helper(
      new base::ThreadTestHelper(
          BrowserThread::GetMessageLoopProxyForThread(
              BrowserThread::WEBKIT_DEPRECATED)));
  ASSERT_TRUE(helper->Run());

  EXPECT_TRUE(file_util::DirectoryExists(normal_path));
  EXPECT_FALSE(file_util::DirectoryExists(session_only_path));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, SaveSessionState) {
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());

  FilePath normal_path;
  FilePath session_only_path;

  // Create the scope which will ensure we run the destructor of the webkit
  // context.
  {
    TestingProfile profile;

    const GURL kNormalOrigin("http://normal/");
    const GURL kSessionOnlyOrigin("http://session-only/");
    scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy =
        new quota::MockSpecialStoragePolicy;
    special_storage_policy->AddSessionOnly(kSessionOnlyOrigin);

    // Create some indexedDB paths.
    // With the levelDB backend, these are directories.
    WebKitContext *webkit_context = profile.GetWebKitContext();
    IndexedDBContext* idb_context = webkit_context->indexed_db_context();

    // Override the storage policy with our own.
    idb_context->special_storage_policy_ = special_storage_policy;
    idb_context->set_clear_local_state_on_exit(true);
    idb_context->set_data_path_for_testing(temp_dir.path());

    // Save session state. This should bypass the destruction-time deletion.
    idb_context->SaveSessionState();

    normal_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kNormalOrigin));
    session_only_path = idb_context->GetIndexedDBFilePath(
        DatabaseUtil::GetOriginIdentifier(kSessionOnlyOrigin));
    ASSERT_TRUE(file_util::CreateDirectory(normal_path));
    ASSERT_TRUE(file_util::CreateDirectory(session_only_path));
  }

  // Make sure we wait until the destructor has run.
  scoped_refptr<base::ThreadTestHelper> helper(
      new base::ThreadTestHelper(
          BrowserThread::GetMessageLoopProxyForThread(
              BrowserThread::WEBKIT_DEPRECATED)));
  ASSERT_TRUE(helper->Run());

  // No data was cleared because of SaveSessionState.
  EXPECT_TRUE(file_util::DirectoryExists(normal_path));
  EXPECT_TRUE(file_util::DirectoryExists(session_only_path));
}

class IndexedDBBrowserTestWithLowQuota : public IndexedDBBrowserTest {
 public:
  virtual void SetUpOnMainThread() {
    const int kInitialQuotaKilobytes = 5000;
    const int kTemporaryStorageQuotaMaxSize = kInitialQuotaKilobytes
        * 1024 * QuotaManager::kPerHostTemporaryPortion;
    SetTempQuota(
        kTemporaryStorageQuotaMaxSize, browser()->profile()->GetQuotaManager());
  }

  static void SetTempQuota(int64 bytes, scoped_refptr<QuotaManager> qm) {
    if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
      BrowserThread::PostTask(
          BrowserThread::IO, FROM_HERE,
          base::Bind(&IndexedDBBrowserTestWithLowQuota::SetTempQuota, bytes,
                     qm));
      return;
    }
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    qm->SetTemporaryGlobalOverrideQuota(bytes, quota::QuotaCallback());
    // Don't return until the quota has been set.
    scoped_refptr<base::ThreadTestHelper> helper(
        new base::ThreadTestHelper(
            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)));
    ASSERT_TRUE(helper->Run());
  }

};

// No longer testable with file: URL: http://crbug.com/104748
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithLowQuota, DISABLED_QuotaTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("quota_test.html"))));
}

class IndexedDBBrowserTestWithGCExposed : public IndexedDBBrowserTest {
 public:
  virtual void SetUpCommandLine(CommandLine* command_line) {
    command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed,
                       DatabaseCallbacksTest) {
  SimpleTest(
      testUrl(FilePath(FILE_PATH_LITERAL("database_callbacks_first.html"))));
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2017 Couchbase, Inc.
 *
 *   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 "executors.h"

#include "engine_wrapper.h"
#include "utilities.h"
#include <daemon/mcbp.h>
#include <memcached/protocol_binary.h>

void dcp_buffer_acknowledgement_executor(Cookie& cookie) {
    auto ret = cookie.swapAiostat(ENGINE_SUCCESS);

    auto& connection = cookie.getConnection();
    if (ret == ENGINE_SUCCESS) {
        ret = mcbp::haveDcpPrivilege(cookie);

        if (ret == ENGINE_SUCCESS) {
            const auto& header = cookie.getRequest();
            const auto* req = reinterpret_cast<
                    const protocol_binary_request_dcp_buffer_acknowledgement*>(
                    &header);

            uint32_t bbytes;
            memcpy(&bbytes, &req->message.body.buffer_bytes, 4);
            ret = dcpBufferAcknowledgement(cookie,
                                           header.getOpaque(),
                                           header.getVBucket(),
                                           ntohl(bbytes));
        }
    }

    ret = connection.remapErrorCode(ret);
    switch (ret) {
    case ENGINE_SUCCESS:
        connection.setState(StateMachine::State::new_cmd);
        break;

    case ENGINE_DISCONNECT:
        connection.setState(StateMachine::State::closing);
        break;

    case ENGINE_EWOULDBLOCK:
        cookie.setEwouldblock(true);
        break;

    default:
        cookie.sendResponse(cb::engine_errc(ret));
    }
}
<commit_msg>Refactor: Prepare dcp_buffer_acknowledgement_executor for Frame Extras<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2017 Couchbase, Inc.
 *
 *   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 "executors.h"

#include "engine_wrapper.h"
#include "utilities.h"
#include <daemon/mcbp.h>
#include <memcached/protocol_binary.h>

void dcp_buffer_acknowledgement_executor(Cookie& cookie) {
    auto ret = cookie.swapAiostat(ENGINE_SUCCESS);

    auto& connection = cookie.getConnection();
    if (ret == ENGINE_SUCCESS) {
        ret = mcbp::haveDcpPrivilege(cookie);

        if (ret == ENGINE_SUCCESS) {
            auto& req = cookie.getRequest(Cookie::PacketContent::Full);
            auto extras = req.getExtdata();
            uint32_t bytes =
                    ntohl(*reinterpret_cast<const uint32_t*>(extras.data()));
            ret = dcpBufferAcknowledgement(
                    cookie, req.getOpaque(), req.getVBucket(), bytes);
        }
    }

    ret = connection.remapErrorCode(ret);
    switch (ret) {
    case ENGINE_SUCCESS:
        connection.setState(StateMachine::State::new_cmd);
        break;

    case ENGINE_DISCONNECT:
        connection.setState(StateMachine::State::closing);
        break;

    case ENGINE_EWOULDBLOCK:
        cookie.setEwouldblock(true);
        break;

    default:
        cookie.sendResponse(cb::engine_errc(ret));
    }
}
<|endoftext|>