<commit_before>#include "S_World.h"
#include "j1Input.h"
#include "SDL\include\SDL.h"
#include "j1Scene.h"
#include "p2Log.h"
#include "j1App.h"
#include "j1Map.h"
#include "j1Render.h"
#include "j1Textures.h"
#include "j1Pathfinding.h"
#include "j1App.h"
#include "j1Player.h"
#include "j1Camera.h"
#include "j1HUD.h"
#include "j1Enemy.h"
#include"j1Audio.h"
#include"j1GameStartMenuBack.h"
bool S_World::Start()
{
	scene_str = "Overworld";

	App->camera->Enable();
	App->hud->Enable();
	App->collision->Enable();
	App->map->Enable();
	App->player->Enable();
	App->object->Enable();

	//PAUSE FALSE
	App->player->paused = false;
	App->enemy->paused = false;
	App->collision->paused = false;
	App->pathfinding->paused = false;

	LOG("IM FUCKING STARTING!!");
	if (App->map->Load("tutorial map test.tmx") == true)

	{
		int w, h = 0;
		uchar* data = nullptr;
		if (App->map->CreateWalkabilityMap(w, h, &data))
			App->pathfinding->SetMap(w, h);

		for (int i = 0; i < App->object->V_Objects.size(); i++) {
			if (App->object->V_Objects[i]->collider_tiles.size() > 0) {
				App->object->CreateColliders(*App->object->V_Objects[i]);
			}
		}

		int w_two, h_two = 0;
		uchar* data_two = nullptr;
		if (App->map->CreateEnemyMap(w_two, h_two, &data_two)) {
			int w_three = 0;
			int h_three = 0;
			uchar* data_three = nullptr;
			if (App->map->CreateEnemyPathMap(w_three, h_three, &data_three)) {
				App->enemy->Enable();
			}
		}
			RELEASE_ARRAY(data);
			//App->map->CreateLogicMap();
	}

	App->audio->PlayMusic("audio/music/Sewers_Song.ogg", 1);
	App->audio->VolumeMusic(100);

	App->render->camera.x = 0;
	App->render->camera.y = 0;

	App->player->Link->pos = { 660,1400 };
	App->player->Zelda->pos = { 620,1400 };
	App->player->Link->logic_height = 1;
	App->player->Zelda->logic_height = 1;
	App->player->half_hearts_test_purpose = App->player->hearts_containers_test_purpose * 2;
	LOG("World Open");
	return false;
}

bool S_World::Update()
{
	//App->map->Draw();
	if (App->input->GetKey(SDL_SCANCODE_X) == KEY_DOWN) {
		App->player->loop_game_menu = true;
	}

	return false;
}
bool S_World::PostUpdate()
{

	if (App->player->loop_game_menu == true || App->player->half_hearts_test_purpose <= 0) {

		App->scene->ChangeScene(Scene_ID::Send);
		App->startmenuback->Freeze(false);
		App->player->loop_game_menu = false;
		App->player->half_hearts_test_purpose = App->player->hearts_containers_test_purpose * 2;
	}
	return true;

}
bool S_World::Clean()
{

	LOG("World Test Deleted");

	App->player->Disable();
	App->enemy->Disable();
	App->map->Disable();
	App->collision->Disable();
	App->hud->Disable();
	App->object->Disable();

	//std::list <TileSet*>::iterator temp = App->map->data.tilesets.begin();

	/*p2List_item<TileSet*>* temp = App->map->data.tilesets.start;
	while (temp != NULL) {
		App->tex->UnLoad(temp->data->texture);
		temp = temp->next;
	}*/

	return false;
}
<commit_msg>Change sa warudo name<commit_after>#include "S_World.h"
#include "j1Input.h"
#include "SDL\include\SDL.h"
#include "j1Scene.h"
#include "p2Log.h"
#include "j1App.h"
#include "j1Map.h"
#include "j1Render.h"
#include "j1Textures.h"
#include "j1Pathfinding.h"
#include "j1App.h"
#include "j1Player.h"
#include "j1Camera.h"
#include "j1HUD.h"
#include "j1Enemy.h"
#include"j1Audio.h"
#include"j1GameStartMenuBack.h"
bool S_World::Start()
{
	scene_str = "Castle Sewers";

	App->camera->Enable();
	App->hud->Enable();
	App->collision->Enable();
	App->map->Enable();
	App->player->Enable();
	App->object->Enable();

	//PAUSE FALSE
	App->player->paused = false;
	App->enemy->paused = false;
	App->collision->paused = false;
	App->pathfinding->paused = false;

	LOG("IM FUCKING STARTING!!");
	if (App->map->Load("tutorial map test.tmx") == true)

	{
		int w, h = 0;
		uchar* data = nullptr;
		if (App->map->CreateWalkabilityMap(w, h, &data))
			App->pathfinding->SetMap(w, h);

		for (int i = 0; i < App->object->V_Objects.size(); i++) {
			if (App->object->V_Objects[i]->collider_tiles.size() > 0) {
				App->object->CreateColliders(*App->object->V_Objects[i]);
			}
		}

		int w_two, h_two = 0;
		uchar* data_two = nullptr;
		if (App->map->CreateEnemyMap(w_two, h_two, &data_two)) {
			int w_three = 0;
			int h_three = 0;
			uchar* data_three = nullptr;
			if (App->map->CreateEnemyPathMap(w_three, h_three, &data_three)) {
				App->enemy->Enable();
			}
		}
			RELEASE_ARRAY(data);
			//App->map->CreateLogicMap();
	}

	App->audio->PlayMusic("audio/music/Sewers_Song.ogg", 1);
	App->audio->VolumeMusic(100);

	App->render->camera.x = 0;
	App->render->camera.y = 0;

	App->player->Link->pos = { 660,1400 };
	App->player->Zelda->pos = { 620,1400 };
	App->player->Link->logic_height = 1;
	App->player->Zelda->logic_height = 1;
	App->player->half_hearts_test_purpose = App->player->hearts_containers_test_purpose * 2;
	LOG("World Open");
	return false;
}

bool S_World::Update()
{
	//App->map->Draw();
	if (App->input->GetKey(SDL_SCANCODE_X) == KEY_DOWN) {
		App->player->loop_game_menu = true;
	}

	return false;
}
bool S_World::PostUpdate()
{

	if (App->player->loop_game_menu == true || App->player->half_hearts_test_purpose <= 0) {

		App->scene->ChangeScene(Scene_ID::Send);
		App->startmenuback->Freeze(false);
		App->player->loop_game_menu = false;
		App->player->half_hearts_test_purpose = App->player->hearts_containers_test_purpose * 2;
	}
	return true;

}
bool S_World::Clean()
{

	LOG("World Test Deleted");

	App->player->Disable();
	App->enemy->Disable();
	App->map->Disable();
	App->collision->Disable();
	App->hud->Disable();
	App->object->Disable();

	//std::list <TileSet*>::iterator temp = App->map->data.tilesets.begin();

	/*p2List_item<TileSet*>* temp = App->map->data.tilesets.start;
	while (temp != NULL) {
		App->tex->UnLoad(temp->data->texture);
		temp = temp->next;
	}*/

	return false;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "views/controls/textfield/gtk_views_entry.h"

#include "gfx/canvas_paint.h"
#include "base/utf_string_conversions.h"
#include "gfx/insets.h"
#include "gfx/skia_utils_gtk.h"
#include "views/controls/textfield/native_textfield_gtk.h"
#include "views/controls/textfield/textfield.h"

G_BEGIN_DECLS

G_DEFINE_TYPE(GtkViewsEntry, gtk_views_entry, GTK_TYPE_ENTRY)

static gint gtk_views_entry_expose_event(GtkWidget *widget,
                                         GdkEventExpose *event) {
  gint result = GTK_WIDGET_CLASS(gtk_views_entry_parent_class)->expose_event(
      widget, event);

  GtkEntry* entry = GTK_ENTRY(widget);
  views::NativeTextfieldGtk* host = GTK_VIEWS_ENTRY(widget)->host;

  // Internally GtkEntry creates an additional window (text_area) that the
  // text is drawn to. We only need paint after that window has painted.
  if (host && event->window == entry->text_area &&
      !host->textfield()->text_to_display_when_empty().empty() &&
      g_utf8_strlen(gtk_entry_get_text(entry), -1) == 0) {
    gfx::CanvasPaint canvas(event);
    if (!canvas.is_empty()) {
      gfx::Insets insets =
          views::NativeTextfieldGtk::GetEntryInnerBorder(entry);
      gfx::Font font = host->textfield()->font();
      const string16 text = host->textfield()->text_to_display_when_empty();
      canvas.DrawStringInt(
          UTF16ToWide(text), font,
          gfx::GdkColorToSkColor(widget->style->text[GTK_STATE_INSENSITIVE]),
          insets.left(), insets.top(),
          widget->allocation.width - insets.width(), font.height());
    }
  }

  return result;
}

static void gtk_views_entry_class_init(GtkViewsEntryClass* views_entry_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(views_entry_class);
  widget_class->expose_event = gtk_views_entry_expose_event;
}

static void gtk_views_entry_init(GtkViewsEntry* entry) {
  entry->host = NULL;
}

GtkWidget* gtk_views_entry_new(views::NativeTextfieldGtk* host) {
  gpointer entry = g_object_new(GTK_TYPE_VIEWS_ENTRY, NULL);
  GTK_VIEWS_ENTRY(entry)->host = host;
  return GTK_WIDGET(entry);
}

G_END_DECLS
<commit_msg>Fixes ordering of includes.<commit_after>// Copyright (c) 2010 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 "views/controls/textfield/gtk_views_entry.h"

#include "base/utf_string_conversions.h"
#include "gfx/canvas_paint.h"
#include "gfx/insets.h"
#include "gfx/skia_utils_gtk.h"
#include "views/controls/textfield/native_textfield_gtk.h"
#include "views/controls/textfield/textfield.h"

G_BEGIN_DECLS

G_DEFINE_TYPE(GtkViewsEntry, gtk_views_entry, GTK_TYPE_ENTRY)

static gint gtk_views_entry_expose_event(GtkWidget *widget,
                                         GdkEventExpose *event) {
  gint result = GTK_WIDGET_CLASS(gtk_views_entry_parent_class)->expose_event(
      widget, event);

  GtkEntry* entry = GTK_ENTRY(widget);
  views::NativeTextfieldGtk* host = GTK_VIEWS_ENTRY(widget)->host;

  // Internally GtkEntry creates an additional window (text_area) that the
  // text is drawn to. We only need paint after that window has painted.
  if (host && event->window == entry->text_area &&
      !host->textfield()->text_to_display_when_empty().empty() &&
      g_utf8_strlen(gtk_entry_get_text(entry), -1) == 0) {
    gfx::CanvasPaint canvas(event);
    if (!canvas.is_empty()) {
      gfx::Insets insets =
          views::NativeTextfieldGtk::GetEntryInnerBorder(entry);
      gfx::Font font = host->textfield()->font();
      const string16 text = host->textfield()->text_to_display_when_empty();
      canvas.DrawStringInt(
          UTF16ToWide(text), font,
          gfx::GdkColorToSkColor(widget->style->text[GTK_STATE_INSENSITIVE]),
          insets.left(), insets.top(),
          widget->allocation.width - insets.width(), font.height());
    }
  }

  return result;
}

static void gtk_views_entry_class_init(GtkViewsEntryClass* views_entry_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(views_entry_class);
  widget_class->expose_event = gtk_views_entry_expose_event;
}

static void gtk_views_entry_init(GtkViewsEntry* entry) {
  entry->host = NULL;
}

GtkWidget* gtk_views_entry_new(views::NativeTextfieldGtk* host) {
  gpointer entry = g_object_new(GTK_TYPE_VIEWS_ENTRY, NULL);
  GTK_VIEWS_ENTRY(entry)->host = host;
  return GTK_WIDGET(entry);
}

G_END_DECLS
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <move_basic/queued_action_server.h>
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>

class GoalQueueSuite : public ::testing::Test {
protected:
	virtual void SetUp() {
		resetFlags();
		ros::NodeHandle actionNh("");
		qserv.reset(new actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction> (actionNh, "queue_server", boost::bind(&GoalQueueSuite::executeCallback, this, _1)));
		cli.reset(new actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> ("queue_server", true)); // true -> don't need ros::spin()

		qserv->start();
	}

	virtual void TearDown() {
		// Kill the executeCallback if it is running
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); // Releases one waiting thread
		}
		qserv->shutdown();
	}

	void executeCallback(const move_base_msgs::MoveBaseGoalConstPtr &msg) {
		resetFlags();
		got_goal = true;
		received_goal = msg;
		while (true) {
			goal_preempted = qserv->isPreemptRequested() ? true : false;
			next_goal_available = qserv->isNewGoalAvailable() ? true : false;

			// Test fixture can continue
			execution = true;
			sleep_cv.notify_one();
			// Wait until signalled to end
			std::unique_lock<std::mutex> lk(execute_lock);
			execute_cv.wait(lk,
				//lambda function to wait on our bool variables
				[this](){return finish_executing || resume_executing;} // blocks only if lambda returns false
			);
			// execution = false;
			// We were requested to stop, so we stop
			if (finish_executing) {
				break;
			}
		}

		// Signal that we are done here
		std::lock_guard<std::mutex> lk(execute_done_lock);
		execute_done = true;
		execute_done_cv.notify_all();
	}

	// Helper function to signal the executeCallback to end
	void finishExecuting() {
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); //unlocks lambda waiting function in ExecuteCallback
		}

		// Wait for execute callback to actually finish
		std::unique_lock<std::mutex> lk2(execute_done_lock);
		execute_done_cv.wait(lk2, [this]() {return execute_done;}); // at the end of ExecuteCallback
	}

	// Helper function to signal the executeCallback to resume
	// This is useful for seeing if the callback code sees a preempt
	void resumeExecuting() {
		std::lock_guard<std::mutex> lk(execute_lock);
		resume_executing = true;
		execute_cv.notify_one();
	}

	// Helper function to wait to for flags to update in ExecuteCallback
	void sleepExecuting() {
		std::unique_lock<std::mutex> slk(sleep_lock);
		sleep_cv.wait(slk,
				[this](){return execution;}
			);
	}

	void resetFlags() {
		got_goal = false;
		goal_preempted = false;
		next_goal_available = false;
		received_goal = nullptr;

		// Signal flags
		execution = false;
		finish_executing = false;
		resume_executing = false;
		execute_done = false;
	}

	// Flags for assertions
	bool got_goal;
	bool goal_preempted;
	bool next_goal_available;
	move_base_msgs::MoveBaseGoalConstPtr received_goal;

	// Signaling variables
	bool execution;
	bool finish_executing;
	bool resume_executing;
	bool execute_done;
	std::mutex sleep_lock;
	std::mutex execute_lock;
	std::mutex execute_done_lock;
	std::condition_variable sleep_cv;
	std::condition_variable execute_cv;
	std::condition_variable execute_done_cv;

	std::unique_ptr<actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction>> qserv;
	std::unique_ptr<actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>> cli;
};

TEST_F(GoalQueueSuite, establishDuplex) {
	move_base_msgs::MoveBaseGoal goal;

	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();

 	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_FALSE(next_goal_available);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);
	finishExecuting();
}

// TODO: After cancel call do ros-spin and delay
TEST_F(GoalQueueSuite, addGoalWhileExecuting) {
	move_base_msgs::MoveBaseGoal goal;

	// First goal
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_FALSE(next_goal_available);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	resumeExecuting(); // TODO: execution always true!!

	// sleepExecuting();
	// EXPECT_TRUE(got_goal);
	// EXPECT_FALSE(goal_preempted);
	// ASSERT_TRUE(next_goal_available); // TODO: Why is this failling?

	// Cancelling the last goal - TODO: Doesnt work!
	cli->cancelGoal(); // Cancels the last goal sent
	ros::spinOnce();
	ros::Duration(1.0).sleep();
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);
 	finishExecuting(); // Finish 1st goal
	ros::Duration(3.0).sleep();
	// ASSERT_TRUE(goal_preempted); // TODO:  Why is this failling?
 	finishExecuting(); // Finish 2nd (canceled) goal
 	finishExecuting(); // Finish 1st goal
	ros::Duration(3.0).sleep();

	// New goal
	goal.target_pose.pose.position.x = 13.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_EQ(13.0, received_goal->target_pose.pose.position.x); // BUG: X=7 (from canceled goal)
	finishExecuting(); // Finish new goal

// 	- if another goal is received add it to the queue (DONE)
// 	- if the queue full, set the next goal as preempted - explicitly called! - so cancelling the next goal and adding new to the queue
// 	- start executing the new goal in queue (after the current)
}

TEST_F(GoalQueueSuite, goalPreempting) {
	move_base_msgs::MoveBaseGoal goal;

	// One goal -> Cancel request -> Stop
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	cli->cancelGoal();
	ros::spinOnce();
	resumeExecuting();
	// ros::spinOnce();
	sleepExecuting();
	// ASSERT_TRUE(goal_preempted);
	finishExecuting(); // Finish the goal
	ros::spinOnce();
	sleepExecuting();
// 	ASSERT_FALSE(qserv->isActive());

	// Two goals -> Cancel current goal -> Start executing the second
	// First goal
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	// ASSERT_TRUE(qserv->isActive());
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Cancelling the first goal - PITFALL
	cli->cancelGoal();
	ros::spinOnce();
	resumeExecuting();
	sleepExecuting();
	// ros::spinOnce();
	// ASSERT_TRUE(goal_preempted);
	// Finish the preempted goal
	finishExecuting(); // Finish 1st goal

	// "Second" goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	ASSERT_TRUE(got_goal);
	// ASSERT_EQ(7.0, received_goal->target_pose.pose.position.x); // call FINISH!
	finishExecuting(); // Finish 2nd goal

//	- if a cancel request is received for the current goal, set it as preempted (DONE)
//	- if there another goal, start executing it
//	- if no goal, stop (DONE)
}

TEST_F(GoalQueueSuite, goalCancelling) {
	move_base_msgs::MoveBaseGoal goal;
	goal.target_pose.pose.position.x = 3.0;

	// Two goals -> Cancel current goal -> Start executing the second
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();

	// Cancelling the second goal
	cli->cancelGoal();
	ros::spinOnce();
	resumeExecuting();
	// ros::spinOnce();
	sleepExecuting();
	//ASSERT_TRUE(goal_preempted); // TODO: Why is this failling?
	ASSERT_TRUE(qserv->isActive());
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);
	finishExecuting();
	//ASSERT_FALSE(qserv->isActive()); // TODO: Why is this failling?

// 	- if a cancel request on the "next_goal" received, remove it from the queue and set it as cancelled
}
// Two more TEST_F missing

int main(int argc, char **argv) {
    ros::init(argc, argv, "goal_queueing_test");
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Bugs.<commit_after>#include <gtest/gtest.h>
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <actionlib/client/terminal_state.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <move_basic/queued_action_server.h>
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>

class GoalQueueSuite : public ::testing::Test {
protected:
	virtual void SetUp() {
		resetFlags();
		ros::NodeHandle actionNh("");
		qserv.reset(new actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction> (actionNh, "queue_server", boost::bind(&GoalQueueSuite::executeCallback, this, _1)));
		cli.reset(new actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> ("queue_server", true)); // true -> don't need ros::spin()

		qserv->start();
	}

	virtual void TearDown() {
		// Kill the executeCallback if it is running
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); // Releases one waiting thread
		}
		qserv->shutdown();
	}

	void executeCallback(const move_base_msgs::MoveBaseGoalConstPtr &msg) {
		resetFlags();
		got_goal = true;
		received_goal = msg;
		while (true) {
			goal_preempted = qserv->isPreemptRequested() ? true : false;
			next_goal_available = qserv->isNewGoalAvailable() ? true : false;

			// Test fixture can continue
			execution = true;
			sleep_cv.notify_one();
			// Wait until signalled to end
			std::unique_lock<std::mutex> lk(execute_lock);
			execute_cv.wait(lk,
				//lambda function to wait on our bool variables
				[this](){return finish_executing || resume_executing;} // blocks only if lambda returns false
			);
			// execution = false;
			// We were requested to stop, so we stop
			if (finish_executing) {
				break;
			}
		}

		// Signal that we are done here
		std::lock_guard<std::mutex> lk(execute_done_lock);
		execute_done = true;
		execute_done_cv.notify_all();
	}

	// Helper function to signal the executeCallback to end
	void finishExecuting() {
		// New Scope so that lock_guard destructs and unlocks
		{
			std::lock_guard<std::mutex> lk1(execute_lock);
			finish_executing = true;
			execute_cv.notify_one(); //unlocks lambda waiting function in ExecuteCallback
		}

		// Wait for execute callback to actually finish
		std::unique_lock<std::mutex> lk2(execute_done_lock);
		execute_done_cv.wait(lk2, [this]() {return execute_done;}); // at the end of ExecuteCallback
	}

	// Helper function to signal the executeCallback to resume
	// This is useful for seeing if the callback code sees a preempt
	void resumeExecuting() {
		std::lock_guard<std::mutex> lk(execute_lock);
		resume_executing = true;
		execute_cv.notify_one();
	}

	// Helper function to wait to for flags to update in ExecuteCallback
	void sleepExecuting() {
		std::unique_lock<std::mutex> slk(sleep_lock);
		sleep_cv.wait(slk,
				[this](){return execution;}
			);
		// ros::Duration(1.0).sleep();
	 // 	execution = false; // After adding this, things dont work!
	}

	void resetFlags() {
		got_goal = false;
		goal_preempted = false;
		next_goal_available = false;
		received_goal = nullptr;

		// Signal flags
		execution = false;
		finish_executing = false;
		resume_executing = false;
		execute_done = false;
	}

	// Flags for assertions
	bool got_goal;
	bool goal_preempted;
	bool next_goal_available;
	move_base_msgs::MoveBaseGoalConstPtr received_goal;

	// Signaling variables
	bool execution;
	bool finish_executing;
	bool resume_executing;
	bool execute_done;
	std::mutex sleep_lock;
	std::mutex execute_lock;
	std::mutex execute_done_lock;
	std::condition_variable sleep_cv;
	std::condition_variable execute_cv;
	std::condition_variable execute_done_cv;

	std::unique_ptr<actionlib::QueuedActionServer<move_base_msgs::MoveBaseAction>> qserv;
	std::unique_ptr<actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction>> cli;
};

TEST_F(GoalQueueSuite, establishDuplex) {
	move_base_msgs::MoveBaseGoal goal;

	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();

 	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_FALSE(next_goal_available);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);
	finishExecuting();
}

// TODO: After cancel call do ros-spin and delay
TEST_F(GoalQueueSuite, addGoalWhileExecuting) {
	move_base_msgs::MoveBaseGoal goal;

	// First goal
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_FALSE(next_goal_available);
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
// 	ASSERT_TRUE(next_goal_available); // TODO: Why is this failling?

	// Cancelling the last goal - TODO: Doesnt work!
	cli->cancelGoal(); // Cancels the last goal sent
	ros::spinOnce();
	ros::Duration(1.0).sleep();
	EXPECT_EQ(3.0, received_goal->target_pose.pose.position.x);
 	finishExecuting(); // Finish 1st goal
	ros::Duration(3.0).sleep();
	// ASSERT_TRUE(goal_preempted); // TODO:  Why is this failling?
 	finishExecuting(); // Finish 2nd (canceled) goal
	ros::Duration(3.0).sleep();

	// New goal
	goal.target_pose.pose.position.x = 13.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	EXPECT_TRUE(got_goal);
	EXPECT_FALSE(goal_preempted);
	EXPECT_EQ(13.0, received_goal->target_pose.pose.position.x); // BUG: X=7 (from canceled goal)
	finishExecuting(); // Finish new goal

// 	- if another goal is received add it to the queue (DONE)
// 	- if the queue full, set the next goal as preempted - explicitly called! - so cancelling the next goal and adding new to the queue
// 	- start executing the new goal in queue (after the current)
}

/*
TEST_F(GoalQueueSuite, goalPreempting) {
	move_base_msgs::MoveBaseGoal goal;

	// One goal -> Cancel request -> Stop
	goal.target_pose.pose.position.x = 3.0;
	cli->sendGoal(goal);
	ros::spinOnce();
	sleepExecuting();
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	cli->cancelGoal();
	ros::spinOnce();
	resumeExecuting();
	// ros::spinOnce();
	sleepExecuting();
	// ASSERT_TRUE(goal_preempted);
	finishExecuting(); // Finish the goal
	ros::spinOnce();
	sleepExecuting();
// 	ASSERT_FALSE(qserv->isActive());

	// Two goals -> Cancel current goal -> Start executing the second
	// First goal
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	// ASSERT_TRUE(qserv->isActive());
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Cancelling the first goal - PITFALL
	cli->cancelGoal();
	ros::spinOnce();
	resumeExecuting();
	sleepExecuting();
	// ros::spinOnce();
	// ASSERT_TRUE(goal_preempted);
	// Finish the preempted goal
	finishExecuting(); // Finish 1st goal

	// "Second" goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	ASSERT_TRUE(got_goal);
	// ASSERT_EQ(7.0, received_goal->target_pose.pose.position.x); // call FINISH!
	finishExecuting(); // Finish 2nd goal

//	- if a cancel request is received for the current goal, set it as preempted (DONE)
//	- if there another goal, start executing it
//	- if no goal, stop (DONE)
}

TEST_F(GoalQueueSuite, goalCancelling) {
	move_base_msgs::MoveBaseGoal goal;
	goal.target_pose.pose.position.x = 3.0;

	// Two goals -> Cancel current goal -> Start executing the second
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();
	ASSERT_TRUE(got_goal);
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);

	// Second goal
	goal.target_pose.pose.position.x = 7.0;
	cli->sendGoal(goal);
	ros::spinOnce();

	sleepExecuting();

	// Cancelling the second goal
	cli->cancelGoal();
	ros::spinOnce();
	resumeExecuting();
	// ros::spinOnce();
	sleepExecuting();
	//ASSERT_TRUE(goal_preempted); // TODO: Why is this failling?
	ASSERT_TRUE(qserv->isActive());
	ASSERT_EQ(3.0, received_goal->target_pose.pose.position.x);
	finishExecuting();
	//ASSERT_FALSE(qserv->isActive()); // TODO: Why is this failling?

// 	- if a cancel request on the "next_goal" received, remove it from the queue and set it as cancelled
}
// Two more TEST_F missing
*/
int main(int argc, char **argv) {
    ros::init(argc, argv, "goal_queueing_test");
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "parser.h"

#include "pageTags.h"
#include "util/exception.h"
#include "util/minmax.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define STREQ(src, literal) (strncmp(src, literal, strlen(literal)) == 0)

#define WH ".wowhead.com/"
#define WW ".wowwiki.com/"

#define FLUSH flush(ptr)

void Parser::flush(const char* end) {
	int len = end - mNodeStart;
	EASSERT(len >= 0);
	if(len > 0) {
		addTextNode(mNodeStart, len);
		mNodeStart = end;
	}
}

void Parser::parse(const char* src) {
	const char* ptr = src;
	mNodeStart = ptr;
	while(*ptr) {
		// skip invalid utf-8 sequences.
		wchar_t w;
		int res = mbtowc(&w, ptr, 4);
		if(res <= 0) {
			FLUSH;
			ptr++;
			mNodeStart = ptr;
			continue;
		} else if(res > 1) {	// valid utf-8 beyond ascii
			ptr += res;
			continue;
		}

		if(STREQ(ptr, "http://")) {	// unescaped link
			FLUSH;
			ptr = parseUnescapedUrl(ptr);
			mNodeStart = ptr;
			continue;
		}

		char c = *ptr;
		ptr++;
		if(c == '[') {	// start tag
			while(*ptr == '[') {
				ptr++;
			}
			const char* endPtr = strchr(ptr, ']');
			if(!endPtr) {
				break;
			}
			flush(ptr-1);
			mNodeStart = ptr;
			parseTag(ptr, endPtr - ptr);
			ptr = endPtr + 1;
			mNodeStart = ptr;
		} else if(c == '\\' && *ptr == 'n') {
			flush(ptr-1);
			ptr++;
			mNodeStart = ptr;
			addLinebreakNode();
		}
	}
	FLUSH;
}

template<class Map>
bool Parser::pageTag(const char* type, size_t typeLen, const char* tag, size_t tagLen,
	Map& map)
{
	if(strncmp(type, tag, typeLen) != 0)
		return false;
	//printf("%*s tag: %.*s\n", (int)(typeLen-1), type, (int)tagLen, tag);
	const char* idString = tag + typeLen;
	size_t idLen = tagLen - typeLen;

	const char* space = (char*)memchr(idString, ' ', idLen);
	if(space)
		idLen = space - idString;

	map.load();
	addPageNode(map, type, idString, idLen);
	return true;
}

enum CompRes {
	crMatch,
	crMismatch,
	crIgnore,
};

static CompRes compareTag(const char* t, size_t tLen, const char* tag, size_t tagLen,
	bool& hasAttributes)
{
	bool match = strncmp(t, tag, tLen) == 0 &&
		(tagLen == tLen || (hasAttributes = isspace(tag[tLen])));
	if(!match)
		return crMismatch;
	return crMatch;
}

// intentional fallthrough
#define COMPARE_TAG(t, matchAction) { CompRes cr = compareTag(t, strlen(t), tag, len, hasAttributes);\
	switch(cr) {\
	case crIgnore: printf("Ignored tag: %s\n", t); return;\
	case crMatch: matchAction\
	case crMismatch: break;\
	} }

#define COMPLEX_TAG(t, type, dst, end) COMPARE_TAG(t, addTagNode(type, tag, len, strlen(t), dst, end); return;)
#define END_TAG(t) COMPARE_TAG(t, addEndTag(t); return;)
#define SIMPLE_TAG(t, type) COMPLEX_TAG(t, type, t, "/" t); END_TAG("/" t)
#define C_TAG(t, type, dst, end) COMPLEX_TAG(t, type, dst, end); END_TAG("/" t)
#define FORMATTING_TAG(t, type) COMPARE_TAG(t, addFormattingTag(tag, len, strlen(t), type); return;); END_TAG("/" t)

void Parser::parseTag(const char* tag, size_t len) {
	bool hasAttributes;
	//printf("tag: %i %.*s\n", tagState, (int)len, tag);
	FORMATTING_TAG("b", BOLD);
	FORMATTING_TAG("i", ITALIC);
	FORMATTING_TAG("small", SMALL);
	FORMATTING_TAG("s", SMALL);
	FORMATTING_TAG("u", UNDERLINED);
	SIMPLE_TAG("table", TABLE);
	SIMPLE_TAG("tr", NO_TYPE);
	SIMPLE_TAG("td", NO_TYPE);
	//SIMPLE_TAG("li", LIST_ITEM);
	COMPARE_TAG("li", addListItem(); return;);
	END_TAG("/li");
	SIMPLE_TAG("ul", LIST);
	SIMPLE_TAG("ol", LIST);

	if(!strncmp("url=", tag, 4) || !strncmp("url:", tag, 4) || !strncmp("url ", tag, 4)) {
		//printf("url tag: %i %.*s\n", tagState, (int)len, tag);
		const char* url = tag + 4;
		size_t urlLen = len - 4;
		parseUrl(url, urlLen);
		return;
	}
	C_TAG("url", ANCHOR, "a", "/a");

	if(strncmp("color=", tag, 6) == 0) {
		const char* idString = tag + 6;
		size_t idLen = len - 6;
		addColorTag(idString, idLen);
		return;
	}
	END_TAG("/color");

	// todo: code, quote

#define PAGE_TAG(name, map) if(pageTag(name "=", sizeof(name), tag, len, map)) return;

	PAGE_TAGS(PAGE_TAG);

	// Unknown tag.
	// Assume it is intended to be printed as plain text, with its brackets[].
	printf("unknown tag: %.*s\n", (int)len, tag);
	mNodeStart = tag-1;
	flush(tag+len+1);
}

#ifdef WIN32
#include <algorithm>
static const char* memmem(const char* a, size_t alen, const char* b, size_t blen) {
	const char* res = std::search(a, a+alen, b, b+blen);
	if(res >= a+alen)
		return NULL;
	return res;
}
#endif

static bool isUrlChar(char c) {
	//gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
	//sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
	return isalnum(c) || c == '_' || c == '#' || c == '?' || c == '/' || c == '-' ||
		c == '=' || c == '.' || c == ':' || c == '&' || c == '(' || c == ')' ||
		c == '%';
}
static bool isWowheadNonUrlChar(char c) {
	return c == '/' || c == '?' || c == '.' || c == '-';
}

void Parser::parseUrl(const char* url, size_t len) {
	// skip starting whitespace
	while(isspace(*url)) {
		len--;
		url++;
	}

	// check for start-quote mark.
	if(*url == '"') {
		url++;
		len--;
	}

	// check for whitespace.
	// skip whitespace and any data afterwards.
	const char* ptr = url;
	const char* end = url + len;
	while(ptr < end) {
		// also check for end-quote mark and the invalid start-tag marker.
		if(isspace(*ptr) || *ptr == '"' || *ptr == '[')
			break;
		ptr++;
	}
	len = ptr - url;

	// s/http://*.wowhead.com/
	const char* whf = (char*)memmem(url, len, WH, strlen(WH));
	if(whf) {
		const char* path = whf + strlen(WH);
		if(*path == '?')
			path += 1;
		size_t pathLen = len - (path - url);
		addWowfootUrlNode(path, pathLen);
		return;
	}
	// s/http://*.wowwiki.com/
	//printf("URL test: %*s\n", (int)len, url);
	const char* wwf = (char*)memmem(url, len, WW, strlen(WW));
	if(wwf) {
		const char* path = wwf + strlen(WW);
		size_t pathLen = len - (path - url);
		addWowpediaUrlNode(path, pathLen);
		return;
	}

	// old-style wowhead paths.
	if(strncmp(url, "/?", 2) == 0) {
		url += 2;
		len -= 2;
	}

	addUrlNode(url, len);
}

// returns new ptr.
const char* Parser::parseUnescapedUrl(const char* ptr) {
	const char* domain = ptr + 7;
	const char* slash = strchr(domain, '/');
	if(!slash)
		return domain;
	const char* path = slash + 1;

	// we can assume wowhead urls never have slashes '/',
	// or '?', except as the first character in the path.
	const char* subdomain = slash - (strlen(WH) - 1);
	//printf("sd: %s\n", subdomain);
	bool isWowhead = STREQ(subdomain, WH);
	if(isWowhead && *path == '?')
		path++;
	const char* end = path;
	while(isUrlChar(*end)) {
		if(isWowhead && isWowheadNonUrlChar(*end))
			break;
		end++;
	}
	size_t pathLen = end - path;
	size_t urlLen = end - ptr;
	//printf("uu: %i %.*s\n", isWowhead, urlLen, ptr);
	size_t len;
	if(isWowhead) {
		// write name of linked entity (item, object, spell, quest, et. al)
		// use PAGE_TAG code
#define UE_TAG(name, map) if(pageTag(name "=", sizeof(name), path, pathLen, map)) return end;
		PAGE_TAGS(UE_TAG);

		len = pathLen;
	} else {
		len = urlLen;
	}

	// wowwiki->wowpedia
	const char* wwf = (char*)memmem(ptr, urlLen, WW, strlen(WW));
	if(wwf) {
		addWowpediaUrlNode(path, pathLen);
		addStaticTextNode("http://www.wowpedia.org/");
		addTextNode(path, pathLen);
		addUrlEndNode();
		return end;
	}

	if(!isWowhead)
		path = ptr;

	addUrlNode(path, len);
	addTextNode(path, len);
	addUrlEndNode();
	return end;
}
<commit_msg>comments: url parsing '['.<commit_after>#include "parser.h"

#include "pageTags.h"
#include "util/exception.h"
#include "util/minmax.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define STREQ(src, literal) (strncmp(src, literal, strlen(literal)) == 0)

#define WH ".wowhead.com/"
#define WW ".wowwiki.com/"

#define FLUSH flush(ptr)

void Parser::flush(const char* end) {
	int len = end - mNodeStart;
	EASSERT(len >= 0);
	if(len > 0) {
		addTextNode(mNodeStart, len);
		mNodeStart = end;
	}
}

void Parser::parse(const char* src) {
	const char* ptr = src;
	mNodeStart = ptr;
	while(*ptr) {
		// skip invalid utf-8 sequences.
		wchar_t w;
		int res = mbtowc(&w, ptr, 4);
		if(res <= 0) {
			FLUSH;
			ptr++;
			mNodeStart = ptr;
			continue;
		} else if(res > 1) {	// valid utf-8 beyond ascii
			ptr += res;
			continue;
		}

		if(STREQ(ptr, "http://")) {	// unescaped link
			FLUSH;
			ptr = parseUnescapedUrl(ptr);
			mNodeStart = ptr;
			continue;
		}

		char c = *ptr;
		ptr++;
		if(c == '[') {	// start tag
			while(*ptr == '[') {
				ptr++;
			}
			const char* endPtr = strchr(ptr, ']');
			if(!endPtr) {
				break;
			}
			flush(ptr-1);
			mNodeStart = ptr;
			parseTag(ptr, endPtr - ptr);
			ptr = endPtr + 1;
			mNodeStart = ptr;
		} else if(c == '\\' && *ptr == 'n') {
			flush(ptr-1);
			ptr++;
			mNodeStart = ptr;
			addLinebreakNode();
		}
	}
	FLUSH;
}

template<class Map>
bool Parser::pageTag(const char* type, size_t typeLen, const char* tag, size_t tagLen,
	Map& map)
{
	if(strncmp(type, tag, typeLen) != 0)
		return false;
	//printf("%*s tag: %.*s\n", (int)(typeLen-1), type, (int)tagLen, tag);
	const char* idString = tag + typeLen;
	size_t idLen = tagLen - typeLen;

	const char* space = (char*)memchr(idString, ' ', idLen);
	if(space)
		idLen = space - idString;

	map.load();
	addPageNode(map, type, idString, idLen);
	return true;
}

enum CompRes {
	crMatch,
	crMismatch,
	crIgnore,
};

static CompRes compareTag(const char* t, size_t tLen, const char* tag, size_t tagLen,
	bool& hasAttributes)
{
	bool match = strncmp(t, tag, tLen) == 0 &&
		(tagLen == tLen || (hasAttributes = isspace(tag[tLen])));
	if(!match)
		return crMismatch;
	return crMatch;
}

// intentional fallthrough
#define COMPARE_TAG(t, matchAction) { CompRes cr = compareTag(t, strlen(t), tag, len, hasAttributes);\
	switch(cr) {\
	case crIgnore: printf("Ignored tag: %s\n", t); return;\
	case crMatch: matchAction\
	case crMismatch: break;\
	} }

#define COMPLEX_TAG(t, type, dst, end) COMPARE_TAG(t, addTagNode(type, tag, len, strlen(t), dst, end); return;)
#define END_TAG(t) COMPARE_TAG(t, addEndTag(t); return;)
#define SIMPLE_TAG(t, type) COMPLEX_TAG(t, type, t, "/" t); END_TAG("/" t)
#define C_TAG(t, type, dst, end) COMPLEX_TAG(t, type, dst, end); END_TAG("/" t)
#define FORMATTING_TAG(t, type) COMPARE_TAG(t, addFormattingTag(tag, len, strlen(t), type); return;); END_TAG("/" t)

void Parser::parseTag(const char* tag, size_t len) {
	bool hasAttributes;
	//printf("tag: %i %.*s\n", tagState, (int)len, tag);
	FORMATTING_TAG("b", BOLD);
	FORMATTING_TAG("i", ITALIC);
	FORMATTING_TAG("small", SMALL);
	FORMATTING_TAG("s", SMALL);
	FORMATTING_TAG("u", UNDERLINED);
	SIMPLE_TAG("table", TABLE);
	SIMPLE_TAG("tr", NO_TYPE);
	SIMPLE_TAG("td", NO_TYPE);
	//SIMPLE_TAG("li", LIST_ITEM);
	COMPARE_TAG("li", addListItem(); return;);
	END_TAG("/li");
	SIMPLE_TAG("ul", LIST);
	SIMPLE_TAG("ol", LIST);

	if(!strncmp("url=", tag, 4) || !strncmp("url:", tag, 4) || !strncmp("url ", tag, 4)) {
		//printf("url tag: %i %.*s\n", tagState, (int)len, tag);
		const char* url = tag + 4;
		size_t urlLen = len - 4;
		parseUrl(url, urlLen);
		return;
	}
	C_TAG("url", ANCHOR, "a", "/a");

	if(strncmp("color=", tag, 6) == 0) {
		const char* idString = tag + 6;
		size_t idLen = len - 6;
		addColorTag(idString, idLen);
		return;
	}
	END_TAG("/color");

	// todo: code, quote

#define PAGE_TAG(name, map) if(pageTag(name "=", sizeof(name), tag, len, map)) return;

	PAGE_TAGS(PAGE_TAG);

	// Unknown tag.
	// Assume it is intended to be printed as plain text, with its brackets[].
	printf("unknown tag: %.*s\n", (int)len, tag);
	mNodeStart = tag-1;
	flush(tag+len+1);
}

#ifdef WIN32
#include <algorithm>
static const char* memmem(const char* a, size_t alen, const char* b, size_t blen) {
	const char* res = std::search(a, a+alen, b, b+blen);
	if(res >= a+alen)
		return NULL;
	return res;
}
#endif

static bool isUrlChar(char c) {
	//gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
	//sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
	return isalnum(c) || c == '_' || c == '#' || c == '?' || c == '/' || c == '-' ||
		c == '=' || c == '.' || c == ':' || c == '&' || c == '(' || c == ')' ||
		c == '%';
}
static bool isWowheadNonUrlChar(char c) {
	return c == '/' || c == '?' || c == '.' || c == '-';
}

void Parser::parseUrl(const char* url, size_t len) {
	// skip starting whitespace
	while(isspace(*url)) {
		len--;
		url++;
	}

	// skip broken '['
	if(*url == '[') {
		url++;
		len--;
	}

	// check for start-quote mark.
	if(*url == '"') {
		url++;
		len--;
	}

	// check for whitespace.
	// skip whitespace and any data afterwards.
	const char* ptr = url;
	const char* end = url + len;
	while(ptr < end) {
		// also check for end-quote mark and the invalid start-tag marker.
		if(isspace(*ptr) || *ptr == '"' || *ptr == '[')
			break;
		ptr++;
	}
	len = ptr - url;

	// s/http://*.wowhead.com/
	const char* whf = (char*)memmem(url, len, WH, strlen(WH));
	if(whf) {
		const char* path = whf + strlen(WH);
		if(*path == '?')
			path += 1;
		size_t pathLen = len - (path - url);
		addWowfootUrlNode(path, pathLen);
		return;
	}
	// s/http://*.wowwiki.com/
	//printf("URL test: %*s\n", (int)len, url);
	const char* wwf = (char*)memmem(url, len, WW, strlen(WW));
	if(wwf) {
		const char* path = wwf + strlen(WW);
		size_t pathLen = len - (path - url);
		addWowpediaUrlNode(path, pathLen);
		return;
	}

	// old-style wowhead paths.
	if(strncmp(url, "/?", 2) == 0) {
		url += 2;
		len -= 2;
	}

	addUrlNode(url, len);
}

// returns new ptr.
const char* Parser::parseUnescapedUrl(const char* ptr) {
	const char* domain = ptr + 7;
	const char* slash = strchr(domain, '/');
	if(!slash)
		return domain;
	const char* path = slash + 1;

	// we can assume wowhead urls never have slashes '/',
	// or '?', except as the first character in the path.
	const char* subdomain = slash - (strlen(WH) - 1);
	//printf("sd: %s\n", subdomain);
	bool isWowhead = STREQ(subdomain, WH);
	if(isWowhead && *path == '?')
		path++;
	const char* end = path;
	while(isUrlChar(*end)) {
		if(isWowhead && isWowheadNonUrlChar(*end))
			break;
		end++;
	}
	size_t pathLen = end - path;
	size_t urlLen = end - ptr;
	//printf("uu: %i %.*s\n", isWowhead, urlLen, ptr);
	size_t len;
	if(isWowhead) {
		// write name of linked entity (item, object, spell, quest, et. al)
		// use PAGE_TAG code
#define UE_TAG(name, map) if(pageTag(name "=", sizeof(name), path, pathLen, map)) return end;
		PAGE_TAGS(UE_TAG);

		len = pathLen;
	} else {
		len = urlLen;
	}

	// wowwiki->wowpedia
	const char* wwf = (char*)memmem(ptr, urlLen, WW, strlen(WW));
	if(wwf) {
		addWowpediaUrlNode(path, pathLen);
		addStaticTextNode("http://www.wowpedia.org/");
		addTextNode(path, pathLen);
		addUrlEndNode();
		return end;
	}

	if(!isWowhead)
		path = ptr;

	addUrlNode(path, len);
	addTextNode(path, len);
	addUrlEndNode();
	return end;
}
<|endoftext|>


<commit_before>/********************************************************************
 * Copyright © 2016 Computational Molecular Biology Group,          *
 *                  Freie Universität Berlin (GER)                  *
 *                                                                  *
 * This file is part of ReaDDy.                                     *
 *                                                                  *
 * ReaDDy is free software: you can redistribute it and/or modify   *
 * it under the terms of the GNU Lesser General Public License as   *
 * published by the Free Software Foundation, either version 3 of   *
 * the License, or (at your option) any later version.              *
 *                                                                  *
 * This program is distributed in the hope that it will be useful,  *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
 * GNU Lesser General Public License for more details.              *
 *                                                                  *
 * You should have received a copy of the GNU Lesser General        *
 * Public License along with this program. If not, see              *
 * <http://www.gnu.org/licenses/>.                                  *
 ********************************************************************/

/**
 * << detailed description >>
 *
 * @file Utils.cpp
 * @brief << brief description >>
 * @author clonker
 * @date 20.07.17
 * @copyright GNU Lesser General Public License v3.0
 */

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <spdlog/fmt/ostr.h>
#include <readdy/io/File.h>

#include <readdy/model/observables/io/TrajectoryEntry.h>
#include <readdy/model/observables/io/Types.h>
#include <readdy/model/IOUtils.h>
#include <fstream>

namespace py = pybind11;
using rvp = py::return_value_policy;

using radiusmap = std::map<std::string, readdy::scalar>;

void
convert_xyz(const std::string &h5name, const std::string &trajName, const std::string &out, bool generateTcl = true, bool tclRuler = false,
            const radiusmap &radii = {}) {
    readdy::log::debug(R"(converting "{}" to "{}")", h5name, out);
    readdy::io::blosc_compression::initialize();

    readdy::io::File f(h5name, readdy::io::File::Action::OPEN, readdy::io::File::Flag::READ_ONLY);
    auto &rootGroup = f.getRootGroup();

    // get particle types from config
    std::vector<readdy::model::ioutils::ParticleTypeInfo> types;
    {
        auto config = rootGroup.subgroup("readdy/config");
        config.read("particle_types", types, readdy::model::ioutils::ParticleTypeInfoMemoryType(),
                    readdy::model::ioutils::ParticleTypeInfoFileType());
    }

    // map from type name to max number of particles in traj
    std::unordered_map<readdy::particle_type_type, std::size_t> maxCounts;
    for (const auto &type : types) {
        maxCounts[type.type_id] = 0;
        readdy::log::debug("got type {} with id {} and D {}", type.name, type.type_id, type.diffusion_constant);
    }

    auto traj = rootGroup.subgroup("readdy/trajectory/" + trajName);

    // limits
    std::vector<std::size_t> limits;
    traj.read("limits", limits, readdy::io::STDDataSetType<std::size_t>(),
              readdy::io::NativeDataSetType<std::size_t>());
    // records
    std::vector<readdy::model::observables::TrajectoryEntry> entries;
    readdy::model::observables::util::TrajectoryEntryMemoryType memoryType;
    readdy::model::observables::util::TrajectoryEntryFileType fileType;
    traj.read("records", entries, memoryType, fileType);

    std::unordered_map<readdy::particle_type_type, std::size_t> typeMapping(types.size());
    {
        std::size_t i = 0;
        for (const auto &type : types) {
            typeMapping[type.type_id] = i++;
        }
    }

    {
        std::vector<std::size_t> currentCounts(types.size());
        for (std::size_t i = 0; i < limits.size(); i += 2) {
            std::fill(currentCounts.begin(), currentCounts.end(), 0);

            auto begin = limits[i];
            auto end = limits[i + 1];

            for (auto it = entries.begin() + begin; it != entries.begin() + end; ++it) {
                currentCounts[typeMapping.at(it->typeId)]++;
            }

            for (const auto &e : typeMapping) {
                maxCounts[e.first] = std::max(currentCounts.at(e.second), maxCounts[e.first]);
            }
        }
    }

    readdy::log::debug("got particle counts:");
    for (const auto &e : maxCounts) {
        readdy::log::debug("\t type id {}: max {} particles", e.first, e.second);
    }

    std::size_t maxParticlesSum = 0;
    {
        for (const auto &e :maxCounts) {
            maxParticlesSum += e.second;
        }
    }

    readdy::log::debug("writing to xyz (n timesteps {})", limits.size() / 2);

    {
        std::fstream fs;
        fs.exceptions(std::fstream::failbit);
        fs.open(out, std::fstream::out | std::fstream::trunc);

        std::vector<std::size_t> currentCounts(types.size());
        std::vector<std::string> xyzPerType(types.size());
        for (std::size_t frame = 0; frame < limits.size(); frame += 2) {

            // number of atoms + comment line (empty)
            fs << maxParticlesSum << std::endl << std::endl;

            std::fill(currentCounts.begin(), currentCounts.end(), 0);
            std::fill(xyzPerType.begin(), xyzPerType.end(), "");

            auto begin = limits[frame];
            auto end = limits[frame + 1];

            for (auto it = entries.begin() + begin; it != entries.begin() + end; ++it) {
                currentCounts[typeMapping.at(it->typeId)]++;
                auto &currentXYZ = xyzPerType.at(typeMapping.at(it->typeId));
                currentXYZ += "type_" + std::to_string(it->typeId) + "\t" + std::to_string(it->pos.x) + "\t" +
                              std::to_string(it->pos.y) + "\t" + std::to_string(it->pos.z) + "\n";
            }

            for (const auto &mappingEntry : typeMapping) {
                auto nGhosts = maxCounts.at(mappingEntry.first) - currentCounts.at(mappingEntry.second);

                fs << xyzPerType.at(mappingEntry.second);
                for (int x = 0; x < nGhosts; ++x) {
                    fs << "type_" + std::to_string(mappingEntry.first) + "\t0\t0\t0\n";
                }
            }
        }

    }

    if (generateTcl) {
        readdy::log::debug("generating tcl script file {}.tcl", out);

        std::fstream fs;
        fs.exceptions(std::fstream::failbit);
        fs.open(out + ".tcl", std::fstream::out | std::fstream::trunc);

        fs << "mol delete top" << std::endl;
        fs << "mol load xyz " << out << std::endl;
        fs << "mol delrep 0 top" << std::endl;
        fs << "display resetview" << std::endl;

        if (tclRuler) {
            fs << "display projection orthographic" << std::endl;
            fs << "ruler grid" << std::endl;
        }

        std::size_t i = 0;
        for (const auto &t : types) {
            auto radius = static_cast<readdy::scalar>(1.0);
            {
                auto it = radii.find(t.name);
                if (it == radii.end()) {
                    readdy::log::warn("type {} had explicitly no specified radius, using 1.0", t.name);
                } else {
                    radius = it ->second;
                }
            }
            fs << "mol representation VDW " << std::to_string(radius * .7) << " 16.0" << std::endl;
            fs << "mol selection name type_" + std::to_string(t.type_id) << std::endl;
            fs << "mol color ColorID " << (i++) << std::endl;
            fs << "mol addrep top" << std::endl;
        }
        fs << "animate goto 0" << std::endl;
        fs << "color Display Background white" << std::endl;
        fs << "molinfo top set {center_matrix} {{{1 0 0 0}{0 1 0 0}{0 0 1 0}{0 0 0 1}}}" << std::endl;
    }

    readdy::log::debug("converting finished");
}

void exportUtils(py::module &m) {
    using namespace pybind11::literals;
    m.def("convert_xyz", &convert_xyz, "h5_file_name"_a, "traj_data_set_name"_a, "xyz_out_file_name"_a,
          "generate_tcl"_a = true, "tcl_with_grid"_a = false, "radii"_a = radiusmap{});
}<commit_msg>convert to readdyviewer<commit_after>/********************************************************************
 * Copyright © 2016 Computational Molecular Biology Group,          *
 *                  Freie Universität Berlin (GER)                  *
 *                                                                  *
 * This file is part of ReaDDy.                                     *
 *                                                                  *
 * ReaDDy is free software: you can redistribute it and/or modify   *
 * it under the terms of the GNU Lesser General Public License as   *
 * published by the Free Software Foundation, either version 3 of   *
 * the License, or (at your option) any later version.              *
 *                                                                  *
 * This program is distributed in the hope that it will be useful,  *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
 * GNU Lesser General Public License for more details.              *
 *                                                                  *
 * You should have received a copy of the GNU Lesser General        *
 * Public License along with this program. If not, see              *
 * <http://www.gnu.org/licenses/>.                                  *
 ********************************************************************/

/**
 * << detailed description >>
 *
 * @file Utils.cpp
 * @brief << brief description >>
 * @author clonker
 * @date 20.07.17
 * @copyright GNU Lesser General Public License v3.0
 */

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>

#include <fstream>

#include <spdlog/fmt/ostr.h>

#include <readdy/io/File.h>
#include <readdy/model/observables/io/TrajectoryEntry.h>
#include <readdy/model/observables/io/Types.h>
#include <readdy/model/IOUtils.h>

namespace py = pybind11;
using rvp = py::return_value_policy;

using radiusmap = std::map<std::string, readdy::scalar>;

py::tuple convert_readdy_viewer(const std::string &h5name, const std::string &trajName) {
    readdy::log::debug(R"(converting "{}" to readdy viewer format)", h5name);

    readdy::io::File f(h5name, readdy::io::File::Action::OPEN, readdy::io::File::Flag::READ_ONLY);
    auto &rootGroup = f.getRootGroup();

    // get particle types from config
    std::vector<readdy::model::ioutils::ParticleTypeInfo> types;
    {
        auto config = rootGroup.subgroup("readdy/config");
        config.read("particle_types", types, readdy::model::ioutils::ParticleTypeInfoMemoryType(),
                    readdy::model::ioutils::ParticleTypeInfoFileType());
    }

    auto traj = rootGroup.subgroup("readdy/trajectory/" + trajName);

    // limits
    std::vector<std::size_t> limits;
    traj.read("limits", limits, readdy::io::STDDataSetType<std::size_t>(), readdy::io::NativeDataSetType<std::size_t>());

    // records
    std::vector<readdy::model::observables::TrajectoryEntry> entries;
    readdy::model::observables::util::TrajectoryEntryMemoryType memoryType;
    readdy::model::observables::util::TrajectoryEntryFileType fileType;
    traj.read("records", entries, memoryType, fileType);

    auto n_frames = limits.size()/2;
    readdy::log::debug("got n frames: {}", n_frames);

    // map from type name to max number of particles in traj
    std::size_t max_n_particles_per_frame = 0;
    std::vector<std::size_t> shape_nppf {n_frames};
    py::array_t<std::size_t, py::array::c_style> n_particles_per_frame (shape_nppf);
    {
        auto ptr = n_particles_per_frame.mutable_data(0);

        for (std::size_t i = 0; i < limits.size(); i += 2) {
            auto len = limits[i + 1] - limits[i];
            ptr[i/2] = len;
            max_n_particles_per_frame = std::max(max_n_particles_per_frame, len);
        }
    }
    readdy::log::debug("got max n particles: {}", max_n_particles_per_frame);

    py::array_t<double, py::array::c_style> positions_arr {std::vector<std::size_t>{n_frames, max_n_particles_per_frame, 3}};
    py::array_t<std::size_t, py::array::c_style> types_arr {std::vector<std::size_t>{n_frames, max_n_particles_per_frame}};
    py::array_t<std::size_t, py::array::c_style> ids_arr {std::vector<std::size_t>{n_frames, max_n_particles_per_frame}};

    auto positions_ptr = positions_arr.mutable_unchecked();
    auto types_ptr = types_arr.mutable_unchecked();
    auto ids_ptr = ids_arr.mutable_unchecked();

    for (std::size_t i = 0; i < limits.size(); i += 2) {
        auto frame = i/2;
        auto begin = limits[i];
        auto end = limits[i+1];

        std::size_t p = 0;
        for (auto it = entries.begin() + begin; it != entries.begin() + end; ++it, ++p) {
            positions_ptr(frame, p, 0) = it->pos.x;
            positions_ptr(frame, p, 1) = it->pos.y;
            positions_ptr(frame, p, 2) = it->pos.z;
            types_ptr(frame, p) = it->typeId;
            ids_ptr(frame, p) = it->id;
        }
    }

    return py::make_tuple(n_particles_per_frame, positions_arr, types_arr, ids_arr);
}

void
convert_xyz(const std::string &h5name, const std::string &trajName, const std::string &out, bool generateTcl = true, bool tclRuler = false,
            const radiusmap &radii = {}) {
    readdy::log::debug(R"(converting "{}" to "{}")", h5name, out);
    readdy::io::blosc_compression::initialize();

    readdy::io::File f(h5name, readdy::io::File::Action::OPEN, readdy::io::File::Flag::READ_ONLY);
    auto &rootGroup = f.getRootGroup();

    // get particle types from config
    std::vector<readdy::model::ioutils::ParticleTypeInfo> types;
    {
        auto config = rootGroup.subgroup("readdy/config");
        config.read("particle_types", types, readdy::model::ioutils::ParticleTypeInfoMemoryType(),
                    readdy::model::ioutils::ParticleTypeInfoFileType());
    }

    // map from type name to max number of particles in traj
    std::unordered_map<readdy::particle_type_type, std::size_t> maxCounts;
    for (const auto &type : types) {
        maxCounts[type.type_id] = 0;
        readdy::log::debug("got type {} with id {} and D {}", type.name, type.type_id, type.diffusion_constant);
    }

    auto traj = rootGroup.subgroup("readdy/trajectory/" + trajName);

    // limits
    std::vector<std::size_t> limits;
    traj.read("limits", limits, readdy::io::STDDataSetType<std::size_t>(),
              readdy::io::NativeDataSetType<std::size_t>());
    // records
    std::vector<readdy::model::observables::TrajectoryEntry> entries;
    readdy::model::observables::util::TrajectoryEntryMemoryType memoryType;
    readdy::model::observables::util::TrajectoryEntryFileType fileType;
    traj.read("records", entries, memoryType, fileType);

    std::unordered_map<readdy::particle_type_type, std::size_t> typeMapping(types.size());
    {
        std::size_t i = 0;
        for (const auto &type : types) {
            typeMapping[type.type_id] = i++;
        }
    }

    {
        std::vector<std::size_t> currentCounts(types.size());
        for (std::size_t i = 0; i < limits.size(); i += 2) {
            std::fill(currentCounts.begin(), currentCounts.end(), 0);

            auto begin = limits[i];
            auto end = limits[i + 1];

            for (auto it = entries.begin() + begin; it != entries.begin() + end; ++it) {
                currentCounts[typeMapping.at(it->typeId)]++;
            }

            for (const auto &e : typeMapping) {
                maxCounts[e.first] = std::max(currentCounts.at(e.second), maxCounts[e.first]);
            }
        }
    }

    readdy::log::debug("got particle counts:");
    for (const auto &e : maxCounts) {
        readdy::log::debug("\t type id {}: max {} particles", e.first, e.second);
    }

    std::size_t maxParticlesSum = 0;
    {
        for (const auto &e :maxCounts) {
            maxParticlesSum += e.second;
        }
    }

    readdy::log::debug("writing to xyz (n timesteps {})", limits.size() / 2);

    {
        std::fstream fs;
        fs.exceptions(std::fstream::failbit);
        fs.open(out, std::fstream::out | std::fstream::trunc);

        std::vector<std::size_t> currentCounts(types.size());
        std::vector<std::string> xyzPerType(types.size());
        for (std::size_t frame = 0; frame < limits.size(); frame += 2) {

            // number of atoms + comment line (empty)
            fs << maxParticlesSum << std::endl << std::endl;

            std::fill(currentCounts.begin(), currentCounts.end(), 0);
            std::fill(xyzPerType.begin(), xyzPerType.end(), "");

            auto begin = limits[frame];
            auto end = limits[frame + 1];

            for (auto it = entries.begin() + begin; it != entries.begin() + end; ++it) {
                currentCounts[typeMapping.at(it->typeId)]++;
                auto &currentXYZ = xyzPerType.at(typeMapping.at(it->typeId));
                currentXYZ += "type_" + std::to_string(it->typeId) + "\t" + std::to_string(it->pos.x) + "\t" +
                              std::to_string(it->pos.y) + "\t" + std::to_string(it->pos.z) + "\n";
            }

            for (const auto &mappingEntry : typeMapping) {
                auto nGhosts = maxCounts.at(mappingEntry.first) - currentCounts.at(mappingEntry.second);

                fs << xyzPerType.at(mappingEntry.second);
                for (int x = 0; x < nGhosts; ++x) {
                    fs << "type_" + std::to_string(mappingEntry.first) + "\t0\t0\t0\n";
                }
            }
        }

    }

    if (generateTcl) {
        readdy::log::debug("generating tcl script file {}.tcl", out);

        std::fstream fs;
        fs.exceptions(std::fstream::failbit);
        fs.open(out + ".tcl", std::fstream::out | std::fstream::trunc);

        fs << "mol delete top" << std::endl;
        fs << "mol load xyz " << out << std::endl;
        fs << "mol delrep 0 top" << std::endl;
        fs << "display resetview" << std::endl;

        if (tclRuler) {
            fs << "display projection orthographic" << std::endl;
            fs << "ruler grid" << std::endl;
        }

        std::size_t i = 0;
        for (const auto &t : types) {
            auto radius = static_cast<readdy::scalar>(1.0);
            {
                auto it = radii.find(t.name);
                if (it == radii.end()) {
                    readdy::log::warn("type {} had explicitly no specified radius, using 1.0", t.name);
                } else {
                    radius = it ->second;
                }
            }
            fs << "mol representation VDW " << std::to_string(radius * .7) << " 16.0" << std::endl;
            fs << "mol selection name type_" + std::to_string(t.type_id) << std::endl;
            fs << "mol color ColorID " << (i++) << std::endl;
            fs << "mol addrep top" << std::endl;
        }
        fs << "animate goto 0" << std::endl;
        fs << "color Display Background white" << std::endl;
        fs << "molinfo top set {center_matrix} {{{1 0 0 0}{0 1 0 0}{0 0 1 0}{0 0 0 1}}}" << std::endl;
    }

    readdy::log::debug("converting finished");
}

void exportUtils(py::module &m) {
    using namespace pybind11::literals;
    m.def("convert_xyz", &convert_xyz, "h5_file_name"_a, "traj_data_set_name"_a, "xyz_out_file_name"_a,
          "generate_tcl"_a = true, "tcl_with_grid"_a = false, "radii"_a = radiusmap{});
    m.def("convert_readdyviewer", &convert_readdy_viewer, "h5_file_name"_a, "traj_data_set_name"_a);
}<|endoftext|>


<commit_before>// Copyright (c) 2011 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/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "chrome/browser/net/url_request_failed_dns_job.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "net/test/test_server.h"

class ErrorPageTest : public UITest {
 protected:
  bool WaitForTitleMatching(const std::wstring& title) {
    for (int i = 0; i < 10; ++i) {
      if (GetActiveTabTitle() == title)
        return true;
      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
    }
    EXPECT_EQ(title, GetActiveTabTitle());
    return false;
  }
};

TEST_F(ErrorPageTest, DNSError_Basic) {
  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);

  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
}

TEST_F(ErrorPageTest, DNSError_GoBack1) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.
  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));

  EXPECT_TRUE(GetActiveTab()->GoBack());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, DNSError_GoBack2) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.
  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title3.html"))));

  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoBackBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoBack());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.

  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title3.html"))));

  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoBackBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoBack());
  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoForwardBlockUntilNavigationsComplete(2));

  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
}

TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.

  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title3.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));

  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoBackBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoBack());
  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoForwardBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoForward());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))));
  EXPECT_TRUE(WaitForTitleMatching(L"Blah"));
}

TEST_F(ErrorPageTest, IFrameDNSError_GoBack) {
  // Test that a DNS error occuring in an iframe does not result in an
  // additional session history entry.

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))));

  EXPECT_TRUE(GetActiveTab()->GoBack());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, IFrameDNSError_GoBackAndForward) {
  // Test that a DNS error occuring in an iframe does not result in an
  // additional session history entry.

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))));

  EXPECT_TRUE(GetActiveTab()->GoBack());
  EXPECT_TRUE(GetActiveTab()->GoForward());

  EXPECT_TRUE(WaitForTitleMatching(L"Blah"));
}

// Checks that the Link Doctor is not loaded when we receive an actual 404 page.
TEST_F(ErrorPageTest, Page404) {
  NavigateToURLBlockUntilNavigationsComplete(
      URLRequestMockHTTPJob::GetMockUrl(
          FilePath(FILE_PATH_LITERAL("page404.html"))), 1);

  EXPECT_TRUE(WaitForTitleMatching(L"SUCCESS"));
}
<commit_msg>Replace an unnecessary "NavigateToURLBlockUntilNavigationsComplete" with "NavigateToURL" in ErrorPageTest.Page404<commit_after>// Copyright (c) 2011 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/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "chrome/browser/net/url_request_failed_dns_job.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "net/test/test_server.h"

class ErrorPageTest : public UITest {
 protected:
  bool WaitForTitleMatching(const std::wstring& title) {
    for (int i = 0; i < 10; ++i) {
      if (GetActiveTabTitle() == title)
        return true;
      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
    }
    EXPECT_EQ(title, GetActiveTabTitle());
    return false;
  }
};

TEST_F(ErrorPageTest, DNSError_Basic) {
  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);

  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
}

TEST_F(ErrorPageTest, DNSError_GoBack1) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.
  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));

  EXPECT_TRUE(GetActiveTab()->GoBack());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, DNSError_GoBack2) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.
  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title3.html"))));

  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoBackBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoBack());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, DNSError_GoBack2AndForward) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.

  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title3.html"))));

  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoBackBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoBack());
  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoForwardBlockUntilNavigationsComplete(2));

  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
}

TEST_F(ErrorPageTest, DNSError_GoBack2Forward2) {
  // Test that a DNS error occuring in the main frame does not result in an
  // additional session history entry.

  GURL test_url(URLRequestFailedDnsJob::kTestUrl);

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title3.html"))));
  // The first navigation should fail, and the second one should be the error
  // page.
  NavigateToURLBlockUntilNavigationsComplete(test_url, 2);
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));

  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoBackBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoBack());
  // The first navigation should fail, and the second one should be the error
  // page.
  EXPECT_TRUE(GetActiveTab()->GoForwardBlockUntilNavigationsComplete(2));
  EXPECT_TRUE(WaitForTitleMatching(L"Mock Link Doctor"));
  EXPECT_TRUE(GetActiveTab()->GoForward());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, IFrameDNSError_Basic) {
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))));
  EXPECT_TRUE(WaitForTitleMatching(L"Blah"));
}

TEST_F(ErrorPageTest, IFrameDNSError_GoBack) {
  // Test that a DNS error occuring in an iframe does not result in an
  // additional session history entry.

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))));

  EXPECT_TRUE(GetActiveTab()->GoBack());

  EXPECT_TRUE(WaitForTitleMatching(L"Title Of Awesomeness"));
}

TEST_F(ErrorPageTest, IFrameDNSError_GoBackAndForward) {
  // Test that a DNS error occuring in an iframe does not result in an
  // additional session history entry.

  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("title2.html"))));
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("iframe_dns_error.html"))));

  EXPECT_TRUE(GetActiveTab()->GoBack());
  EXPECT_TRUE(GetActiveTab()->GoForward());

  EXPECT_TRUE(WaitForTitleMatching(L"Blah"));
}

// Checks that the Link Doctor is not loaded when we receive an actual 404 page.
TEST_F(ErrorPageTest, Page404) {
  NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(
                    FilePath(FILE_PATH_LITERAL("page404.html"))));

  EXPECT_TRUE(WaitForTitleMatching(L"SUCCESS"));
}
<|endoftext|>


<commit_before><commit_msg>- undocumented feature (???): blinking feature exists in graphics modes, too.   The colors 0..7 appear in high intensity and the colors 8..15 blink using   low / high intensity. Blinking is not present in Bochs yet. For now, the 3rd   bit of the attribute will be inverted. - attribute controller mode control register: only a change of the internal   palette size bit should force a redraw - skip screen update if video is disabled<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2022 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "test/test_pivx.h"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(net_quorums_tests)

// Simplified copy of quorums_connections.h/cpp, GetQuorumRelayMembers function.
// (merely without the CDeterministicMNCPtr as it's not needed to test the algorithm)
std::set<uint256> GetQuorumRelayMembers(const std::vector<uint256>& mnList,
                                        unsigned int forMemberIndex)
{
    assert(forMemberIndex < mnList.size());

    // Special case
    if (mnList.size() == 2) {
        return {mnList[1 - forMemberIndex]};
    }

    // Relay to nodes at indexes (i+2^k)%n, where
    //   k: 0..max(1, floor(log2(n-1))-1)
    //   n: size of the quorum/ring
    std::set<uint256> r;
    int gap = 1;
    int gap_max = (int)mnList.size() - 1;
    int k = 0;
    while ((gap_max >>= 1) || k <= 1) {
        size_t idx = (forMemberIndex + gap) % mnList.size();
        r.emplace(mnList[idx]);
        gap <<= 1;
        k++;
    }
    return r;
}

std::vector<uint256> createMNList(unsigned int size)
{
    std::vector<uint256> mns;
    for (size_t i = 0; i < size; i++) {
        uint256 item;
        do { item = g_insecure_rand_ctx.rand256(); } while (std::find(mns.begin(), mns.end(), item) != mns.end());
        mns.emplace_back(item);
    }
    return mns;
}

void checkQuorumRelayMembers(const std::vector<uint256>& list, unsigned int expectedResSize)
{
    for (size_t i = 0; i < list.size(); i++) {
        const auto& set = GetQuorumRelayMembers(list, i);
        BOOST_CHECK_MESSAGE(set.size() == expectedResSize,
                            strprintf("size %d, expected ret size %d, ret size %d ", list.size(), expectedResSize, set.size()));
        BOOST_CHECK(set.count(list[i]) == 0);
    }
}

BOOST_FIXTURE_TEST_CASE(get_quorum_relay_members, BasicTestingSetup)
{
    // 1) Test special case of 2 members
    std::vector<uint256> list = createMNList(2);
    checkQuorumRelayMembers(list, 1);

    // 2) Test quorum sizes 3 to 1200
    list = createMNList(1200);
    size_t expectedRet = 2;
    for (size_t i = 3; i < 1201; i++) {
        std::vector<uint256> copyList = list;
        copyList.resize(i);
        if ((2 << expectedRet) < (int)i) expectedRet++;
        checkQuorumRelayMembers(copyList, expectedRet);
    }
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Refactor: remove code duplication in net_quorum_tests<commit_after>// Copyright (c) 2022 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "test/test_pivx.h"

#include "evo/deterministicmns.h"
#include "llmq/quorums_connections.h"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(net_quorums_tests)

std::vector<CDeterministicMNCPtr> createMNList(unsigned int size)
{
    std::vector<CDeterministicMNCPtr> mns;
    for (size_t i = 0; i < size; i++) {
        CDeterministicMN dmn(i);
        uint256 newProTxHash;
        do {
            newProTxHash = g_insecure_rand_ctx.rand256();
        } while (std::find_if(mns.begin(), mns.end(),
                [&newProTxHash](CDeterministicMNCPtr mn){ return mn->proTxHash == newProTxHash; }) != mns.end());
        dmn.proTxHash = newProTxHash;
        mns.emplace_back(std::make_shared<const CDeterministicMN>(dmn));
    }
    return mns;
}

void checkQuorumRelayMembers(const std::vector<CDeterministicMNCPtr>& list, unsigned int expectedResSize)
{
    for (size_t i = 0; i < list.size(); i++) {
        const auto& set = llmq::GetQuorumRelayMembers(list, i);
        BOOST_CHECK_MESSAGE(set.size() == expectedResSize,
                            strprintf("size %d, expected ret size %d, ret size %d ", list.size(), expectedResSize, set.size()));
        BOOST_CHECK(set.count(list[i]->proTxHash) == 0);
    }
}

BOOST_FIXTURE_TEST_CASE(get_quorum_relay_members, BasicTestingSetup)
{
    size_t list_size = 2000;    // n
    size_t relay_memb = 10;     // floor(log2(n-1))

    std::vector<CDeterministicMNCPtr> masternodes = createMNList(list_size);

    // Test quorum sizes 2000 to 2
    while (true) {
        checkQuorumRelayMembers(masternodes, relay_memb);

        masternodes.resize(--list_size);
        if (list_size == 1) break;
        // n=2 is a special case (1 relay member)
        // Otherwise relay members are 1 + max(1, floor(log2(n-1))-1)
        else if (list_size == 2 ||
                (list_size > 4 && (1 << relay_memb) >= (int)list_size)) relay_memb--;
    }
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#ifndef TEST__UNIT__LANG__PARSER__UTILITY_HPP
#define TEST__UNIT__LANG__PARSER__UTILITY_HPP

#include <gtest/gtest.h>
#include <iostream>
#include <fstream>
#include <istream>
#include <sstream>
#include <exception>
#include <stdexcept>

#include <boost/lexical_cast.hpp>

#include <stan/lang/ast.hpp>
#include <stan/lang/compiler.hpp>
#include <stan/lang/parser.hpp>
#include <stan/lang/generator.hpp>
#include <stan/lang/grammars/program_grammar.hpp>
#include <stan/lang/grammars/whitespace_grammar.hpp>
#include <stan/lang/grammars/expression_grammar.hpp>
#include <stan/lang/grammars/statement_grammar.hpp>
#include <stan/lang/grammars/var_decls_grammar.hpp>
#include <test/unit/util.hpp>

/** extract model name from filepath name
 * @param file_name  Name off model file
 */
std::string file_name_to_model_name(const std::string& name) {
  std::string name_copy = name;
  size_t last_bk = name_copy.find_last_of('\\');
  if (last_bk != std::string::npos)
    name_copy.erase(0,last_bk + 1);
  size_t last_fwd = name_copy.find_last_of('/');
  if (last_fwd != std::string::npos)
    name_copy.erase(0,last_fwd + 1);

  size_t last_dot = name_copy.find_last_of('.');
  if (last_dot != std::string::npos)
    name_copy.erase(last_dot,name_copy.size());

  name_copy += "_model";
  return name_copy;
}

/** test whether model with specified path name parses successfully
 *
 * @param file_name  Filepath of model file
 * @param msgs Expected error message (default: none)
 * @param allow_undefined Boolean to permit undefined functions (default: false)
 */
bool is_parsable(const std::string& file_name,
                 std::ostream* msgs = 0,
                 bool allow_undefined = false) {
  stan::lang::program prog;
  std::ifstream fs(file_name.c_str());
  std::string model_name = file_name_to_model_name(file_name);
  bool parsable
    = stan::lang::parse(msgs, fs, model_name, prog, allow_undefined);
  return parsable;
}

/** test whether model with specified name in path good parses successfully
 *
 * @param model_name Name of model to parse
 * @param folder Path to folder under src/test/test-models (default "good")
 * @param msgs Warning message
 */
bool is_parsable_folder(const std::string& model_name,
                        const std::string folder = "good",
                        std::ostream* msgs = 0) {
  std::string path("src/test/test-models/");
  path += folder;
  path += "/";
  path += model_name;
  path += ".stan";
  return is_parsable(path, msgs, false);
}

/** test that model with specified name in folder "good"
 *  parses without throwing an exception
 *
 * @param model_name Name of model to parse
 */
void test_parsable(const std::string& model_name) {
  {
    SCOPED_TRACE("parsing: " + model_name);
    EXPECT_TRUE(is_parsable_folder(model_name, "good"));
  }
}

/** test that model with specified name in folder "bad" throws
 * an exception containing the second arg as a substring
 *
 * @param model_name Name of model to parse
 * @param msg Substring of error message expected.
 */
void test_throws(const std::string& model_name, const std::string& error_msg) {
  std::stringstream msgs;
  try {
    is_parsable_folder(model_name, "bad", &msgs);
  } catch (const std::invalid_argument& e) {
    if (std::string(e.what()).find(error_msg) == std::string::npos
        && msgs.str().find(error_msg) == std::string::npos) {
      FAIL() << std::endl << "*********************************" << std::endl
             << "model name=" << model_name << std::endl
             << "*** EXPECTED: error_msg=" << error_msg << std::endl
             << "*** FOUND: e.what()=" << e.what() << std::endl
             << "*** FOUND: msgs.str()=" << msgs.str() << std::endl
             << "*********************************" << std::endl
             << std::endl;
    }
    return;
  }

  FAIL() << "model name=" << model_name
         << " is parsable and were expecting msg=" << error_msg
         << std::endl;
}

/**
 * Same as test_throws() but for two messages.
 */
void test_throws(const std::string& model_name,
                 const std::string& error_msg1,
                 const std::string& error_msg2) {
  test_throws(model_name, error_msg1);
  test_throws(model_name, error_msg2);
}

/**
 * Same as test_throws() but for three messages.
 */
void test_throws(const std::string& model_name,
                 const std::string& error_msg1,
                 const std::string& error_msg2,
                 const std::string& error_msg3) {
  test_throws(model_name, error_msg1);
  test_throws(model_name, error_msg2);
  test_throws(model_name, error_msg3);
}

/** test that model with specified name in good path parses
 * and returns a warning containing the second arg as a substring
 *
 * @param model_name Name of model to parse
 * @param msg Substring of warning message expected.
 */
void test_warning(const std::string& model_name,
                  const std::string& warning_msg) {
  std::stringstream msgs;
  EXPECT_TRUE(is_parsable_folder(model_name, "good", &msgs));
  bool found = msgs.str().find(warning_msg) != std::string::npos;
  EXPECT_TRUE(found) << std::endl
    << "FOUND: " << msgs.str()
    << std::endl
    << "EXPECTED (as substring): " << warning_msg
    << std::endl;
}

std::string model_to_cpp(const std::string& model_text) {
  std::string model_name = "foo";
  std::stringstream ss(model_text);
  std::stringstream msgs;
  stan::lang::program prog;
  bool parsable = stan::lang::parse(&msgs, ss, model_name, prog);
  EXPECT_TRUE(parsable);

  std::stringstream output;
  stan::lang::generate_cpp(prog, model_name, output);
  return output.str();
}

void expect_matches(int n,
                    const std::string& stan_code,
                    const std::string& target) {
  std::string model_cpp = model_to_cpp(stan_code);
  EXPECT_EQ(n, count_matches(target,model_cpp));
}

std::string get_file_name(const std::string& folder,
                          const std::string& model_name) {
  std::string path("src/test/test-models/");
  path += folder;
  path += "/";
  path += model_name;
  path += ".stan";
  return path;
}

void expect_match(const std::string& model_name,
                  const std::string& target,
                  bool allow_undefined = false) {
  std::stringstream msgs;
  std::string file_name = get_file_name("good", model_name);
  std::ifstream file_stream(file_name.c_str());
  std::stringstream cpp_out_stream;
  stan::lang::compile(&msgs, file_stream, cpp_out_stream,
                      model_name, allow_undefined);
  std::string cpp_out = cpp_out_stream.str();
  file_stream.close();
  EXPECT_TRUE(count_matches(target, cpp_out) > 0);
}

/**
 * Thest that model of specified name in test/test-models/good
 * has exactly the specified number of matches
 *
 * @param[in] model_name Name of model file.
 * @param[in] warning_msg Message to count.
 * @param[in] n Expected number of message occurrences.
 */
void test_num_warnings(const std::string& model_name,
                       const std::string& warning_msg,
                       int n) {
  std::stringstream msgs;
  EXPECT_TRUE(is_parsable_folder(model_name, "good", &msgs));
  EXPECT_EQ(n, count_matches(warning_msg, msgs.str()));
}

#endif
<commit_msg>Fixes #2154. Updating test<commit_after>#ifndef TEST_UNIT_LANG_PARSER_UTILITY_HPP
#define TEST_UNIT_LANG_PARSER_UTILITY_HPP

#include <gtest/gtest.h>
#include <iostream>
#include <fstream>
#include <istream>
#include <sstream>
#include <exception>
#include <stdexcept>

#include <boost/lexical_cast.hpp>

#include <stan/lang/ast.hpp>
#include <stan/lang/compiler.hpp>
#include <stan/lang/parser.hpp>
#include <stan/lang/generator.hpp>
#include <stan/lang/grammars/program_grammar.hpp>
#include <stan/lang/grammars/whitespace_grammar.hpp>
#include <stan/lang/grammars/expression_grammar.hpp>
#include <stan/lang/grammars/statement_grammar.hpp>
#include <stan/lang/grammars/var_decls_grammar.hpp>
#include <test/unit/util.hpp>

/** extract model name from filepath name
 * @param file_name  Name off model file
 */
std::string file_name_to_model_name(const std::string& name) {
  std::string name_copy = name;
  size_t last_bk = name_copy.find_last_of('\\');
  if (last_bk != std::string::npos)
    name_copy.erase(0,last_bk + 1);
  size_t last_fwd = name_copy.find_last_of('/');
  if (last_fwd != std::string::npos)
    name_copy.erase(0,last_fwd + 1);

  size_t last_dot = name_copy.find_last_of('.');
  if (last_dot != std::string::npos)
    name_copy.erase(last_dot,name_copy.size());

  name_copy += "_model";
  return name_copy;
}

/** test whether model with specified path name parses successfully
 *
 * @param file_name  Filepath of model file
 * @param msgs Expected error message (default: none)
 * @param allow_undefined Boolean to permit undefined functions (default: false)
 */
bool is_parsable(const std::string& file_name,
                 std::ostream* msgs = 0,
                 bool allow_undefined = false) {
  stan::lang::program prog;
  std::ifstream fs(file_name.c_str());
  std::string model_name = file_name_to_model_name(file_name);
  bool parsable
    = stan::lang::parse(msgs, fs, model_name, prog, allow_undefined);
  return parsable;
}

/** test whether model with specified name in path good parses successfully
 *
 * @param model_name Name of model to parse
 * @param folder Path to folder under src/test/test-models (default "good")
 * @param msgs Warning message
 */
bool is_parsable_folder(const std::string& model_name,
                        const std::string folder = "good",
                        std::ostream* msgs = 0) {
  std::string path("src/test/test-models/");
  path += folder;
  path += "/";
  path += model_name;
  path += ".stan";
  return is_parsable(path, msgs, false);
}

/** test that model with specified name in folder "good"
 *  parses without throwing an exception
 *
 * @param model_name Name of model to parse
 */
void test_parsable(const std::string& model_name) {
  {
    SCOPED_TRACE("parsing: " + model_name);
    EXPECT_TRUE(is_parsable_folder(model_name, "good"));
  }
}

/** test that model with specified name in folder "bad" throws
 * an exception containing the second arg as a substring
 *
 * @param model_name Name of model to parse
 * @param msg Substring of error message expected.
 */
void test_throws(const std::string& model_name, const std::string& error_msg) {
  std::stringstream msgs;
  try {
    is_parsable_folder(model_name, "bad", &msgs);
  } catch (const std::invalid_argument& e) {
    if (std::string(e.what()).find(error_msg) == std::string::npos
        && msgs.str().find(error_msg) == std::string::npos) {
      FAIL() << std::endl << "*********************************" << std::endl
             << "model name=" << model_name << std::endl
             << "*** EXPECTED: error_msg=" << error_msg << std::endl
             << "*** FOUND: e.what()=" << e.what() << std::endl
             << "*** FOUND: msgs.str()=" << msgs.str() << std::endl
             << "*********************************" << std::endl
             << std::endl;
    }
    return;
  }

  FAIL() << "model name=" << model_name
         << " is parsable and were expecting msg=" << error_msg
         << std::endl;
}

/**
 * Same as test_throws() but for two messages.
 */
void test_throws(const std::string& model_name,
                 const std::string& error_msg1,
                 const std::string& error_msg2) {
  test_throws(model_name, error_msg1);
  test_throws(model_name, error_msg2);
}

/**
 * Same as test_throws() but for three messages.
 */
void test_throws(const std::string& model_name,
                 const std::string& error_msg1,
                 const std::string& error_msg2,
                 const std::string& error_msg3) {
  test_throws(model_name, error_msg1);
  test_throws(model_name, error_msg2);
  test_throws(model_name, error_msg3);
}

/** test that model with specified name in good path parses
 * and returns a warning containing the second arg as a substring
 *
 * @param model_name Name of model to parse
 * @param msg Substring of warning message expected.
 */
void test_warning(const std::string& model_name,
                  const std::string& warning_msg) {
  std::stringstream msgs;
  EXPECT_TRUE(is_parsable_folder(model_name, "good", &msgs));
  bool found = msgs.str().find(warning_msg) != std::string::npos;
  EXPECT_TRUE(found) << std::endl
    << "FOUND: " << msgs.str()
    << std::endl
    << "EXPECTED (as substring): " << warning_msg
    << std::endl;
}

std::string model_to_cpp(const std::string& model_text) {
  std::string model_name = "foo";
  std::stringstream ss(model_text);
  std::stringstream msgs;
  stan::lang::program prog;
  bool parsable = stan::lang::parse(&msgs, ss, model_name, prog);
  EXPECT_TRUE(parsable);

  std::stringstream output;
  stan::lang::generate_cpp(prog, model_name, output);
  return output.str();
}

void expect_matches(int n,
                    const std::string& stan_code,
                    const std::string& target) {
  std::string model_cpp = model_to_cpp(stan_code);
  EXPECT_EQ(n, count_matches(target, model_cpp))
    << "looking for: " << target;
}

std::string get_file_name(const std::string& folder,
                          const std::string& model_name) {
  std::string path("src/test/test-models/");
  path += folder;
  path += "/";
  path += model_name;
  path += ".stan";
  return path;
}

void expect_match(const std::string& model_name,
                  const std::string& target,
                  bool allow_undefined = false) {
  std::stringstream msgs;
  std::string file_name = get_file_name("good", model_name);
  std::ifstream file_stream(file_name.c_str());
  std::stringstream cpp_out_stream;
  stan::lang::compile(&msgs, file_stream, cpp_out_stream,
                      model_name, allow_undefined);
  std::string cpp_out = cpp_out_stream.str();
  file_stream.close();
  EXPECT_TRUE(count_matches(target, cpp_out) > 0)
    << "looking for: " << target;
}

/**
 * Thest that model of specified name in test/test-models/good
 * has exactly the specified number of matches
 *
 * @param[in] model_name Name of model file.
 * @param[in] warning_msg Message to count.
 * @param[in] n Expected number of message occurrences.
 */
void test_num_warnings(const std::string& model_name,
                       const std::string& warning_msg,
                       int n) {
  std::stringstream msgs;
  EXPECT_TRUE(is_parsable_folder(model_name, "good", &msgs));
  EXPECT_EQ(n, count_matches(warning_msg, msgs.str()))
    << "looking for: " << warning_msg;
}
#endif

<|endoftext|>