<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include <rapicorn.hh>

namespace {
using namespace Rapicorn;

class ListStore : public virtual BaseObject, public virtual DataListContainer {
  vector<Any> rows_;
protected:
  typedef Aida::Signal<void (const UpdateRequest&)> UpdateSignal;
public:
  explicit ListStore ();
  int      count     () const;                          ///< Obtain the number of rows provided by this model.
  Any      row       (int n) const;                     ///< Read-out row @a n. In-order read outs are generally fastest.
  void     clear     ();                                ///< Remove all rows from the ListModel.
  void     insert    (int n, const Any &aseq);          ///< Insert row @a n.
  void     insert    (int n, const AnySeq &aseqseq);    ///< Insert multiple rows at @a n.
  void     update    (int n, const Any &aseq);          ///< Reassign data to row @a n.
  void     remove    (int n, int length);               ///< Remove @a length rows starting at @a n.
  virtual ~ListStore ();
  UpdateSignal sig_updates; ///< Notify about insertion, changes and deletion of a specific row range.
};

ListStore::ListStore()
{}

ListStore::~ListStore()
{
  clear();
}

int
ListStore::count () const
{
  return rows_.size();
}

Any
ListStore::row (int r) const
{
  return_unless (r >= 0 && r < count(), Any());
  return rows_[r];
}

void
ListStore::clear ()
{
  if (rows_.size())
    remove (0, rows_.size());
}

void
ListStore::insert (int first, const Any &any)
{
  assert_return (first >= 0 && first <= count());
  rows_.insert (rows_.begin() + first, any);
  sig_updates.emit (UpdateRequest (UPDATE_INSERTION, UpdateSpan (first, 1)));
  ApplicationH::the().test_counter_get();
}

void
ListStore::insert (int first, const AnySeq &aseq)
{
  assert_return (first >= 0 && first <= count());
  for (size_t i = 0; i < aseq.size(); i++)
    rows_.insert (rows_.begin() + i, aseq[i]);
  sig_updates.emit (UpdateRequest (UPDATE_INSERTION, UpdateSpan (first, aseq.size())));
  ApplicationH::the().test_counter_get();
}

void
ListStore::update (int first, const Any &any)
{
  assert_return (first >= 0 && first < count());
  rows_[first] = any;
  sig_updates.emit (UpdateRequest (UPDATE_CHANGE, UpdateSpan (first, 1)));
  ApplicationH::the().test_counter_get();
}

void
ListStore::remove (int start, int length)
{
  return_unless (start >= 0 && start < count());
  return_unless (length >= 0);
  return_unless (start + length <= count());
  rows_.erase (rows_.begin() + start, rows_.begin() + start + length);
  sig_updates.emit (UpdateRequest (UPDATE_DELETION, UpdateSpan (start, 1)));
  ApplicationH::the().test_counter_get();
}

} // anon
<commit_msg>TESTS: derive ListStore from just ReferenceCountable and DataListContainer<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include <rapicorn.hh>

namespace {
using namespace Rapicorn;

class ListStore : public virtual ReferenceCountable, public virtual DataListContainer {
  vector<Any> rows_;
protected:
  typedef Aida::Signal<void (const UpdateRequest&)> UpdateSignal;
public:
  explicit ListStore ();
  int      count     () const;                          ///< Obtain the number of rows provided by this model.
  Any      row       (int n) const;                     ///< Read-out row @a n. In-order read outs are generally fastest.
  void     clear     ();                                ///< Remove all rows from the ListModel.
  void     insert    (int n, const Any &aseq);          ///< Insert row @a n.
  void     insert    (int n, const AnySeq &aseqseq);    ///< Insert multiple rows at @a n.
  void     update    (int n, const Any &aseq);          ///< Reassign data to row @a n.
  void     remove    (int n, int length);               ///< Remove @a length rows starting at @a n.
  virtual ~ListStore ();
  UpdateSignal sig_updates; ///< Notify about insertion, changes and deletion of a specific row range.
};

ListStore::ListStore()
{}

ListStore::~ListStore()
{
  clear();
}

int
ListStore::count () const
{
  return rows_.size();
}

Any
ListStore::row (int r) const
{
  return_unless (r >= 0 && r < count(), Any());
  return rows_[r];
}

void
ListStore::clear ()
{
  if (rows_.size())
    remove (0, rows_.size());
}

void
ListStore::insert (int first, const Any &any)
{
  assert_return (first >= 0 && first <= count());
  rows_.insert (rows_.begin() + first, any);
  sig_updates.emit (UpdateRequest (UPDATE_INSERTION, UpdateSpan (first, 1)));
  ApplicationH::the().test_counter_get();
}

void
ListStore::insert (int first, const AnySeq &aseq)
{
  assert_return (first >= 0 && first <= count());
  for (size_t i = 0; i < aseq.size(); i++)
    rows_.insert (rows_.begin() + i, aseq[i]);
  sig_updates.emit (UpdateRequest (UPDATE_INSERTION, UpdateSpan (first, aseq.size())));
  ApplicationH::the().test_counter_get();
}

void
ListStore::update (int first, const Any &any)
{
  assert_return (first >= 0 && first < count());
  rows_[first] = any;
  sig_updates.emit (UpdateRequest (UPDATE_CHANGE, UpdateSpan (first, 1)));
  ApplicationH::the().test_counter_get();
}

void
ListStore::remove (int start, int length)
{
  return_unless (start >= 0 && start < count());
  return_unless (length >= 0);
  return_unless (start + length <= count());
  rows_.erase (rows_.begin() + start, rows_.begin() + start + length);
  sig_updates.emit (UpdateRequest (UPDATE_DELETION, UpdateSpan (start, 1)));
  ApplicationH::the().test_counter_get();
}

} // anon
<|endoftext|>


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

#include <iostream>
#include <utf8.h>
#include <test.h>

////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
  UnitTest t (6);

  std::string ascii_text = "This is a test";
  std::string utf8_text  = "más sábado miércoles";

  std::string ascii_text_color = "This is a test";
  std::string utf8_text_color  = "más sábado miércoles";

  // TODO unsigned int utf8_codepoint (const std::string&);
  // TODO unsigned int utf8_next_char (const std::string&, std::string::size_type&);
  // TODO std::string utf8_character (unsigned int);
  // TODO int utf8_sequence (unsigned int);

  // unsigned int utf8_length (const std::string&);
  t.is (utf8_length (ascii_text), 14, "ASCII utf8_length");
  t.is (utf8_length (utf8_text),  20, "UTF8 utf8_length");

  // unsigned int utf8_text_length (const std::string&);
  t.is (utf8_text_length (ascii_text_color), 14, "ASCII utf8_text_length");
  t.is (utf8_text_length (utf8_text_color),  20, "UTF8 utf8_text_length");

  // const std::string utf8_substr (const std::string&, unsigned int, unsigned int length = 0);
  t.is (utf8_substr (ascii_text, 0, 2), "Th", "ASCII utf8_substr");
  t.is (utf8_substr (utf8_text, 0, 2),  "má", "UTF8 utf8_substr");

  return 0;
}

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

#include <iostream>
#include <utf8.h>
#include <test.h>

////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
  UnitTest t (6);

  std::string ascii_text = "This is a test";
  std::string utf8_text  = "más sábado miércoles";

  std::string ascii_text_color = "This is a test";
  std::string utf8_text_color  = "más sábado miércoles";

  // TODO unsigned int utf8_codepoint (const std::string&);
  // TODO unsigned int utf8_next_char (const std::string&, std::string::size_type&);
  // TODO std::string utf8_character (unsigned int);
  // TODO int utf8_sequence (unsigned int);

  // unsigned int utf8_length (const std::string&);
  t.is ((int) utf8_length (ascii_text), 14, "ASCII utf8_length");
  t.is ((int) utf8_length (utf8_text),  20, "UTF8 utf8_length");

  // unsigned int utf8_text_length (const std::string&);
  t.is ((int) utf8_text_length (ascii_text_color), 14, "ASCII utf8_text_length");
  t.is ((int) utf8_text_length (utf8_text_color),  20, "UTF8 utf8_text_length");

  // const std::string utf8_substr (const std::string&, unsigned int, unsigned int length = 0);
  t.is (utf8_substr (ascii_text, 0, 2), "Th", "ASCII utf8_substr");
  t.is (utf8_substr (utf8_text, 0, 2),  "má", "UTF8 utf8_substr");

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<|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/basictypes.h"
#include "base/compiler_specific.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/models/tree_node_model.h"

namespace ui {

class TreeNodeModelTest : public testing::Test, public TreeModelObserver {
 public:
  TreeNodeModelTest()
      : added_count_(0),
        removed_count_(0),
        changed_count_(0) {}

  void AssertObserverCount(int added_count,
                           int removed_count,
                           int changed_count) {
    ASSERT_EQ(added_count, added_count_);
    ASSERT_EQ(removed_count, removed_count_);
    ASSERT_EQ(changed_count, changed_count_);
  }

  void ClearCounts() {
    added_count_ = removed_count_ = changed_count_ = 0;
  }

  // Begin TreeModelObserver implementation.
  virtual void TreeNodesAdded(TreeModel* model,
                              TreeModelNode* parent,
                              int start,
                              int count) OVERRIDE {
    added_count_++;
  }
  virtual void TreeNodesRemoved(TreeModel* model,
                                TreeModelNode* parent,
                                int start,
                                int count) OVERRIDE {
    removed_count_++;
  }
  virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node) OVERRIDE {
    changed_count_++;
  }
  // End TreeModelObserver implementation.

 private:
  int added_count_;
  int removed_count_;
  int changed_count_;

  DISALLOW_COPY_AND_ASSIGN(TreeNodeModelTest);
};

// Verify if the model is properly adding a new node in the tree and
// notifying the observers.
// The tree looks like this:
// root
// |-- child1
// |   |-- foo1
// |   |-- foo2
// +-- child2
TEST_F(TreeNodeModelTest, AddNode) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);
  model.AddObserver(this);
  ClearCounts();

  // Create the first root child.
  TreeNodeWithValue<int>* child1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 1"), 1);
  model.Add(root, child1, 0);

  AssertObserverCount(1, 0, 0);

  // Add two nodes under the |child1|.
  TreeNodeWithValue<int>* foo1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo1"), 3);
  TreeNodeWithValue<int>* foo2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo2"), 4);
  child1->Add(foo1, 0);
  child1->Add(foo2, 1);

  // Create the second root child.
  TreeNodeWithValue<int>* child2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 2"), 2);
  root->Add(child2, 1);

  // Check if there is two nodes under the root.
  ASSERT_EQ(2, model.GetChildCount(root));

  // Check if there is two nodes under |child1|.
  ASSERT_EQ(2, model.GetChildCount(child1));

  // Check if there is none nodes under |child2|.
  ASSERT_EQ(0, model.GetChildCount(child2));
}

// Verify if the model is properly removing a node from the tree
// and notifying the observers.
TEST_F(TreeNodeModelTest, RemoveNode) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);
  model.AddObserver(this);
  ClearCounts();

  // Create the first child node.
  TreeNodeWithValue<int>* child1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 1"), 1);

  // And add it to the root node.
  root->Add(child1, 0);

  ASSERT_EQ(1, model.GetChildCount(root));

  // Now remove the |child1| from root and release the memory.
  delete model.Remove(root, child1);

  AssertObserverCount(0, 1, 0);

  ASSERT_EQ(0, model.GetChildCount(root));
}

// Verify if the nodes added under the root are all deleted when calling
// RemoveAll. Note that is responsability of the caller to free the memory
// of the nodes removed after RemoveAll is called.
// The tree looks like this:
// root
// |-- child1
// |   |-- foo
// |       |-- bar0
// |       |-- bar1
// |       |-- bar2
// |-- child2
// +-- child3
TEST_F(TreeNodeModelTest, RemoveAllNodes) {
  TreeNodeWithValue<int> root;

  TreeNodeWithValue<int> child1;
  TreeNodeWithValue<int> child2;
  TreeNodeWithValue<int> child3;

  root.Add(&child1, 0);
  root.Add(&child2, 1);
  root.Add(&child3, 2);

  TreeNodeWithValue<int>* foo = new TreeNodeWithValue<int>(2);
  child1.Add(foo, 0);

  // Add some nodes to |foo|.
  for (int i = 0; i < 3; ++i)
    foo->Add(new TreeNodeWithValue<int>(i), i);

  ASSERT_EQ(3, root.child_count());
  ASSERT_EQ(1, child1.child_count());
  ASSERT_EQ(3, foo->child_count());

  // Now remove the child nodes from root.
  root.RemoveAll();

  ASSERT_EQ(0, root.child_count());
  ASSERT_TRUE(root.empty());

  ASSERT_EQ(1, child1.child_count());
  ASSERT_EQ(3, foo->child_count());
}

// Verify if the model returns correct indexes for the specified nodes.
// The tree looks like this:
// root
// |-- child1
// |   |-- foo1
// +-- child2
TEST_F(TreeNodeModelTest, GetIndexOf) {
  TreeNodeWithValue<int> root;

  TreeNodeWithValue<int>* child1 = new TreeNodeWithValue<int>(1);
  root.Add(child1, 0);

  TreeNodeWithValue<int>* child2 = new TreeNodeWithValue<int>(2);
  root.Add(child2, 1);

  TreeNodeWithValue<int>* foo1 = new TreeNodeWithValue<int>(0);
  child1->Add(foo1, 0);

  ASSERT_EQ(-1, root.GetIndexOf(&root));
  ASSERT_EQ(0, root.GetIndexOf(child1));
  ASSERT_EQ(1, root.GetIndexOf(child2));
  ASSERT_EQ(-1, root.GetIndexOf(foo1));

  ASSERT_EQ(-1, child1->GetIndexOf(&root));
  ASSERT_EQ(-1, child1->GetIndexOf(child1));
  ASSERT_EQ(-1, child1->GetIndexOf(child2));
  ASSERT_EQ(0, child1->GetIndexOf(foo1));

  ASSERT_EQ(-1, child2->GetIndexOf(&root));
  ASSERT_EQ(-1, child2->GetIndexOf(child2));
  ASSERT_EQ(-1, child2->GetIndexOf(child1));
  ASSERT_EQ(-1, child2->GetIndexOf(foo1));
}

// Verify whether a specified node has or not an ancestor.
// The tree looks like this:
// root
// |-- child1
// |-- child2
TEST_F(TreeNodeModelTest, HasAncestor) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);

  TreeNodeWithValue<int>* child1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 1"), 0);
  model.Add(root, child1, 0);

  TreeNodeWithValue<int>* child2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 2"), 1);
  model.Add(root, child2, 1);

  ASSERT_TRUE(root->HasAncestor(root));
  ASSERT_FALSE(root->HasAncestor(child1));
  ASSERT_TRUE(child1->HasAncestor(root));
  ASSERT_FALSE(child1->HasAncestor(child2));
  ASSERT_FALSE(child2->HasAncestor(child1));
}

// The tree looks like this:
// root
// |-- child1
// |   |-- child2
// |       |-- child3
// |-- foo1
// |   |-- foo2
// |       |-- foo3
// |   |-- foo4
// +-- bar1
//
// The TotalNodeCount of root is:   9
// The TotalNodeCount of child1 is: 3
// The TotalNodeCount of bar1 is:   1
// And so on...
// The purpose here is to verify if the function returns the total of nodes
// under the specifed node correctly. The count should include the node it self.
TEST_F(TreeNodeModelTest, GetTotalNodeCount) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);

  TreeNodeWithValue<int>* child1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child1"), 1);
  TreeNodeWithValue<int>* child2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child2"), 2);
  TreeNodeWithValue<int>* child3 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child3"), 3);
  TreeNodeWithValue<int>* foo1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo1"), 4);
  TreeNodeWithValue<int>* foo2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo2"), 5);
  TreeNodeWithValue<int>* foo3 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo3"), 6);
  TreeNodeWithValue<int>* foo4 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo4"), 7);
  TreeNodeWithValue<int>* bar1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("bar1"), 8);

  model.Add(root, child1, 0);
  model.Add(child1, child2, 0);
  model.Add(child2, child3, 0);

  model.Add(root, foo1, 1);
  model.Add(foo1, foo2, 0);
  model.Add(foo1, foo4, 1);
  model.Add(foo2, foo3, 0);

  model.Add(root, bar1, 0);

  ASSERT_EQ(9, root->GetTotalNodeCount());
  ASSERT_EQ(3, child1->GetTotalNodeCount());
  ASSERT_EQ(1, bar1->GetTotalNodeCount());
  ASSERT_EQ(2, foo2->GetTotalNodeCount());
}

// Makes sure that we are notified when the node is renamed,
// also makes sure the node is properly renamed.
TEST_F(TreeNodeModelTest, SetTitle) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);
  model.AddObserver(this);
  ClearCounts();

  const string16 title(ASCIIToUTF16("root2"));
  model.SetTitle(root, title);
  AssertObserverCount(0, 0, 1);
  EXPECT_EQ(title, root->GetTitle());
}

TEST_F(TreeNodeModelTest, BasicOperations) {
  TreeNodeWithValue<int>* root = new TreeNodeWithValue<int>(0);
  EXPECT_EQ(0, root->child_count());

  TreeNodeWithValue<int>* child1 = new TreeNodeWithValue<int>(1);
  root->Add(child1, root->child_count());
  EXPECT_EQ(1, root->child_count());
  EXPECT_EQ(root, child1->parent());

  TreeNodeWithValue<int>* child2 = new TreeNodeWithValue<int>(1);
  root->Add(child2, root->child_count());
  EXPECT_EQ(2, root->child_count());
  EXPECT_EQ(child1->parent(), child2->parent());

  root->Remove(child2);
  EXPECT_EQ(1, root->child_count());
  EXPECT_EQ(NULL, child2->parent());
  delete child2;

  delete root->Remove(child1);
  EXPECT_EQ(0, root->child_count());

  delete root;
}

TEST_F(TreeNodeModelTest, IsRoot) {
  TreeNodeWithValue<int> root;
  EXPECT_TRUE(root.is_root());

  TreeNodeWithValue<int>* child1 = new TreeNodeWithValue<int>(1);
  root.Add(child1, root.child_count());
  EXPECT_FALSE(child1->is_root());
}

}  // namespace ui
<commit_msg>ui/base/models: Rewrite the TreeNodeModelTest.HasAncestor unittest.<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/basictypes.h"
#include "base/compiler_specific.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/models/tree_node_model.h"

namespace ui {

class TreeNodeModelTest : public testing::Test, public TreeModelObserver {
 public:
  TreeNodeModelTest()
      : added_count_(0),
        removed_count_(0),
        changed_count_(0) {}

  void AssertObserverCount(int added_count,
                           int removed_count,
                           int changed_count) {
    ASSERT_EQ(added_count, added_count_);
    ASSERT_EQ(removed_count, removed_count_);
    ASSERT_EQ(changed_count, changed_count_);
  }

  void ClearCounts() {
    added_count_ = removed_count_ = changed_count_ = 0;
  }

  // Begin TreeModelObserver implementation.
  virtual void TreeNodesAdded(TreeModel* model,
                              TreeModelNode* parent,
                              int start,
                              int count) OVERRIDE {
    added_count_++;
  }
  virtual void TreeNodesRemoved(TreeModel* model,
                                TreeModelNode* parent,
                                int start,
                                int count) OVERRIDE {
    removed_count_++;
  }
  virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node) OVERRIDE {
    changed_count_++;
  }
  // End TreeModelObserver implementation.

 private:
  int added_count_;
  int removed_count_;
  int changed_count_;

  DISALLOW_COPY_AND_ASSIGN(TreeNodeModelTest);
};

// Verify if the model is properly adding a new node in the tree and
// notifying the observers.
// The tree looks like this:
// root
// |-- child1
// |   |-- foo1
// |   |-- foo2
// +-- child2
TEST_F(TreeNodeModelTest, AddNode) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);
  model.AddObserver(this);
  ClearCounts();

  // Create the first root child.
  TreeNodeWithValue<int>* child1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 1"), 1);
  model.Add(root, child1, 0);

  AssertObserverCount(1, 0, 0);

  // Add two nodes under the |child1|.
  TreeNodeWithValue<int>* foo1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo1"), 3);
  TreeNodeWithValue<int>* foo2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo2"), 4);
  child1->Add(foo1, 0);
  child1->Add(foo2, 1);

  // Create the second root child.
  TreeNodeWithValue<int>* child2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 2"), 2);
  root->Add(child2, 1);

  // Check if there is two nodes under the root.
  ASSERT_EQ(2, model.GetChildCount(root));

  // Check if there is two nodes under |child1|.
  ASSERT_EQ(2, model.GetChildCount(child1));

  // Check if there is none nodes under |child2|.
  ASSERT_EQ(0, model.GetChildCount(child2));
}

// Verify if the model is properly removing a node from the tree
// and notifying the observers.
TEST_F(TreeNodeModelTest, RemoveNode) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);
  model.AddObserver(this);
  ClearCounts();

  // Create the first child node.
  TreeNodeWithValue<int>* child1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child 1"), 1);

  // And add it to the root node.
  root->Add(child1, 0);

  ASSERT_EQ(1, model.GetChildCount(root));

  // Now remove the |child1| from root and release the memory.
  delete model.Remove(root, child1);

  AssertObserverCount(0, 1, 0);

  ASSERT_EQ(0, model.GetChildCount(root));
}

// Verify if the nodes added under the root are all deleted when calling
// RemoveAll. Note that is responsability of the caller to free the memory
// of the nodes removed after RemoveAll is called.
// The tree looks like this:
// root
// |-- child1
// |   |-- foo
// |       |-- bar0
// |       |-- bar1
// |       |-- bar2
// |-- child2
// +-- child3
TEST_F(TreeNodeModelTest, RemoveAllNodes) {
  TreeNodeWithValue<int> root;

  TreeNodeWithValue<int> child1;
  TreeNodeWithValue<int> child2;
  TreeNodeWithValue<int> child3;

  root.Add(&child1, 0);
  root.Add(&child2, 1);
  root.Add(&child3, 2);

  TreeNodeWithValue<int>* foo = new TreeNodeWithValue<int>(2);
  child1.Add(foo, 0);

  // Add some nodes to |foo|.
  for (int i = 0; i < 3; ++i)
    foo->Add(new TreeNodeWithValue<int>(i), i);

  ASSERT_EQ(3, root.child_count());
  ASSERT_EQ(1, child1.child_count());
  ASSERT_EQ(3, foo->child_count());

  // Now remove the child nodes from root.
  root.RemoveAll();

  ASSERT_EQ(0, root.child_count());
  ASSERT_TRUE(root.empty());

  ASSERT_EQ(1, child1.child_count());
  ASSERT_EQ(3, foo->child_count());
}

// Verify if the model returns correct indexes for the specified nodes.
// The tree looks like this:
// root
// |-- child1
// |   |-- foo1
// +-- child2
TEST_F(TreeNodeModelTest, GetIndexOf) {
  TreeNodeWithValue<int> root;

  TreeNodeWithValue<int>* child1 = new TreeNodeWithValue<int>(1);
  root.Add(child1, 0);

  TreeNodeWithValue<int>* child2 = new TreeNodeWithValue<int>(2);
  root.Add(child2, 1);

  TreeNodeWithValue<int>* foo1 = new TreeNodeWithValue<int>(0);
  child1->Add(foo1, 0);

  ASSERT_EQ(-1, root.GetIndexOf(&root));
  ASSERT_EQ(0, root.GetIndexOf(child1));
  ASSERT_EQ(1, root.GetIndexOf(child2));
  ASSERT_EQ(-1, root.GetIndexOf(foo1));

  ASSERT_EQ(-1, child1->GetIndexOf(&root));
  ASSERT_EQ(-1, child1->GetIndexOf(child1));
  ASSERT_EQ(-1, child1->GetIndexOf(child2));
  ASSERT_EQ(0, child1->GetIndexOf(foo1));

  ASSERT_EQ(-1, child2->GetIndexOf(&root));
  ASSERT_EQ(-1, child2->GetIndexOf(child2));
  ASSERT_EQ(-1, child2->GetIndexOf(child1));
  ASSERT_EQ(-1, child2->GetIndexOf(foo1));
}

// Verify whether a specified node has or not an ancestor.
// The tree looks like this:
// root
// |-- child1
// |   |-- foo1
// +-- child2
TEST_F(TreeNodeModelTest, HasAncestor) {
  TreeNodeWithValue<int> root;
  TreeNodeWithValue<int>* child1 = new TreeNodeWithValue<int>(0);
  TreeNodeWithValue<int>* child2 = new TreeNodeWithValue<int>(0);

  root.Add(child1, 0);
  root.Add(child2, 1);

  TreeNodeWithValue<int>* foo1 = new TreeNodeWithValue<int>(0);
  child1->Add(foo1, 0);

  ASSERT_TRUE(root.HasAncestor(&root));
  ASSERT_FALSE(root.HasAncestor(child1));
  ASSERT_FALSE(root.HasAncestor(child2));
  ASSERT_FALSE(root.HasAncestor(foo1));

  ASSERT_TRUE(child1->HasAncestor(child1));
  ASSERT_TRUE(child1->HasAncestor(&root));
  ASSERT_FALSE(child1->HasAncestor(child2));
  ASSERT_FALSE(child1->HasAncestor(foo1));

  ASSERT_TRUE(child2->HasAncestor(child2));
  ASSERT_TRUE(child2->HasAncestor(&root));
  ASSERT_FALSE(child2->HasAncestor(child1));
  ASSERT_FALSE(child2->HasAncestor(foo1));

  ASSERT_TRUE(foo1->HasAncestor(foo1));
  ASSERT_TRUE(foo1->HasAncestor(child1));
  ASSERT_TRUE(foo1->HasAncestor(&root));
  ASSERT_FALSE(foo1->HasAncestor(child2));
}

// The tree looks like this:
// root
// |-- child1
// |   |-- child2
// |       |-- child3
// |-- foo1
// |   |-- foo2
// |       |-- foo3
// |   |-- foo4
// +-- bar1
//
// The TotalNodeCount of root is:   9
// The TotalNodeCount of child1 is: 3
// The TotalNodeCount of bar1 is:   1
// And so on...
// The purpose here is to verify if the function returns the total of nodes
// under the specifed node correctly. The count should include the node it self.
TEST_F(TreeNodeModelTest, GetTotalNodeCount) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);

  TreeNodeWithValue<int>* child1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child1"), 1);
  TreeNodeWithValue<int>* child2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child2"), 2);
  TreeNodeWithValue<int>* child3 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("child3"), 3);
  TreeNodeWithValue<int>* foo1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo1"), 4);
  TreeNodeWithValue<int>* foo2 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo2"), 5);
  TreeNodeWithValue<int>* foo3 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo3"), 6);
  TreeNodeWithValue<int>* foo4 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("foo4"), 7);
  TreeNodeWithValue<int>* bar1 =
      new TreeNodeWithValue<int>(ASCIIToUTF16("bar1"), 8);

  model.Add(root, child1, 0);
  model.Add(child1, child2, 0);
  model.Add(child2, child3, 0);

  model.Add(root, foo1, 1);
  model.Add(foo1, foo2, 0);
  model.Add(foo1, foo4, 1);
  model.Add(foo2, foo3, 0);

  model.Add(root, bar1, 0);

  ASSERT_EQ(9, root->GetTotalNodeCount());
  ASSERT_EQ(3, child1->GetTotalNodeCount());
  ASSERT_EQ(1, bar1->GetTotalNodeCount());
  ASSERT_EQ(2, foo2->GetTotalNodeCount());
}

// Makes sure that we are notified when the node is renamed,
// also makes sure the node is properly renamed.
TEST_F(TreeNodeModelTest, SetTitle) {
  TreeNodeWithValue<int>* root =
      new TreeNodeWithValue<int>(ASCIIToUTF16("root"), 0);
  TreeNodeModel<TreeNodeWithValue<int> > model(root);
  model.AddObserver(this);
  ClearCounts();

  const string16 title(ASCIIToUTF16("root2"));
  model.SetTitle(root, title);
  AssertObserverCount(0, 0, 1);
  EXPECT_EQ(title, root->GetTitle());
}

TEST_F(TreeNodeModelTest, BasicOperations) {
  TreeNodeWithValue<int>* root = new TreeNodeWithValue<int>(0);
  EXPECT_EQ(0, root->child_count());

  TreeNodeWithValue<int>* child1 = new TreeNodeWithValue<int>(1);
  root->Add(child1, root->child_count());
  EXPECT_EQ(1, root->child_count());
  EXPECT_EQ(root, child1->parent());

  TreeNodeWithValue<int>* child2 = new TreeNodeWithValue<int>(1);
  root->Add(child2, root->child_count());
  EXPECT_EQ(2, root->child_count());
  EXPECT_EQ(child1->parent(), child2->parent());

  root->Remove(child2);
  EXPECT_EQ(1, root->child_count());
  EXPECT_EQ(NULL, child2->parent());
  delete child2;

  delete root->Remove(child1);
  EXPECT_EQ(0, root->child_count());

  delete root;
}

TEST_F(TreeNodeModelTest, IsRoot) {
  TreeNodeWithValue<int> root;
  EXPECT_TRUE(root.is_root());

  TreeNodeWithValue<int>* child1 = new TreeNodeWithValue<int>(1);
  root.Add(child1, root.child_count());
  EXPECT_FALSE(child1->is_root());
}

}  // namespace ui
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

#include <boost/python.hpp>
#include <mapnik/raster_symbolizer.hpp>

void export_raster_symbolizer()
{
    using namespace boost::python;
    using mapnik::raster_symbolizer;

    class_<raster_symbolizer>("RasterSymbolizer",
				    init<>("Default ctor"))
	;
}
<commit_msg>+ reflect raster symbolizer options in python (may need to eventually switch to ENUMS)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

#include <boost/python.hpp>
#include <mapnik/raster_symbolizer.hpp>

void export_raster_symbolizer()
{
    using namespace boost::python;
    using mapnik::raster_symbolizer;

    class_<raster_symbolizer>("RasterSymbolizer",
				    init<>("Default ctor"))

    .add_property("mode",
            make_function(&raster_symbolizer::get_mode,return_value_policy<copy_const_reference>()),
            &raster_symbolizer::set_mode,
            "Get/Set merging mode.\n"
            "Possible values are:\n"
            "normal, grain_merge, grain_merge2, multiply,\n"
            "multiply2, divide, divide2, screen, and hard_light\n"
            "\n"
            "Usage:\n"
            "\n"
            ">>> from mapnik import RasterSymbolizer\n"
            ">>> r = RasterSymbolizer()\n"
            ">>> r.mode = 'grain_merge2'\n"
            )

    .add_property("scaling",
            make_function(&raster_symbolizer::get_scaling,return_value_policy<copy_const_reference>()),
            &raster_symbolizer::set_scaling,
            "Get/Set scaling algorithm.\n"
            "Possible values are:\n"
            "fast, bilinear, and bilinear8\n"
            "\n"
            "Usage:\n"
            "\n"
            ">>> from mapnik import RasterSymbolizer\n"
            ">>> r = RasterSymbolizer()\n"
            ">>> r.scaling = 'bilinear8'\n"
            )

    .add_property("opacity",
            &raster_symbolizer::get_opacity,
            &raster_symbolizer::set_opacity,
            "Get/Set opacity.\n"
            "\n"
            "Usage:\n"
            "\n"
            ">>> from mapnik import RasterSymbolizer\n"
            ">>> r = RasterSymbolizer()\n"
            ">>> r.opacity = .5\n"
            )
	;
}
<|endoftext|>


<commit_before>#include <glib.h>
#include "debug_lldb.h"
#include <thread>
#include <boost/filesystem.hpp>
#include <atomic>

int main() {
  auto build_path=boost::filesystem::canonical(JUCI_BUILD_PATH);
  auto exec_path=build_path/"tests"/"lldb_test_files"/"lldb_test_executable";
  g_assert(boost::filesystem::exists(exec_path));

  auto tests_path=boost::filesystem::canonical(JUCI_TESTS_PATH);
  auto source_path=tests_path/"lldb_test_files"/"main.cpp";
  g_assert(boost::filesystem::exists(source_path));

  std::vector<std::pair<boost::filesystem::path, int> > breakpoints;
  breakpoints.emplace_back(source_path, 2);

  std::atomic<bool> exited(false);
  int exit_status;
  std::atomic<int> line_nr(0);
  std::thread debug_thread([&] {
    Debug::LLDB::get().start(exec_path.string(), "", breakpoints, [&](int exit_status_){
      exit_status=exit_status_;
      exited=true;
    }, [](const std::string &status) {

    }, [&](const boost::filesystem::path &file_path, int line_nr_, int line_index) {
      line_nr=line_nr_;
    });
  });
  debug_thread.detach();

  for(;;) {
    if(exited) {
      g_assert_cmpint(exit_status, ==, 0);
      break;
    }
    else if(line_nr>0) {
      for(;;) {
        if(Debug::LLDB::get().is_stopped())
          break;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
      }
      g_assert_cmpint(line_nr, ==, 2);
      g_assert(Debug::LLDB::get().get_backtrace().size()>0);
      auto variables=Debug::LLDB::get().get_variables();
      g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
      line_nr=0;
      Debug::LLDB::get().step_over();
      for(;;) {
        if(line_nr>0 && Debug::LLDB::get().is_stopped())
          break;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
      }
      g_assert_cmpint(line_nr, ==, 3);
      g_assert(Debug::LLDB::get().get_backtrace().size()>0);
      variables=Debug::LLDB::get().get_variables();
      g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
      auto value=Debug::LLDB::get().get_value("an_int", source_path, 2, 7);
      g_assert_cmpuint(value.size(), >, 16);
      auto value_substr=value.substr(0, 16);
      g_assert_cmpstr(value_substr.c_str(), ==, "(int) an_int = 1");
      line_nr=0;
      Debug::LLDB::get().continue_debug();
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  Debug::LLDB::get().cancel();
}
<commit_msg>Now joins debug_thread in lldb_test<commit_after>#include <glib.h>
#include "debug_lldb.h"
#include <thread>
#include <boost/filesystem.hpp>
#include <atomic>

int main() {
  auto build_path=boost::filesystem::canonical(JUCI_BUILD_PATH);
  auto exec_path=build_path/"tests"/"lldb_test_files"/"lldb_test_executable";
  g_assert(boost::filesystem::exists(exec_path));

  auto tests_path=boost::filesystem::canonical(JUCI_TESTS_PATH);
  auto source_path=tests_path/"lldb_test_files"/"main.cpp";
  g_assert(boost::filesystem::exists(source_path));

  std::vector<std::pair<boost::filesystem::path, int> > breakpoints;
  breakpoints.emplace_back(source_path, 2);

  std::atomic<bool> exited(false);
  int exit_status;
  std::atomic<int> line_nr(0);
  std::thread debug_thread([&] {
    Debug::LLDB::get().start(exec_path.string(), "", breakpoints, [&](int exit_status_){
      exit_status=exit_status_;
      exited=true;
    }, [](const std::string &status) {

    }, [&](const boost::filesystem::path &file_path, int line_nr_, int line_index) {
      line_nr=line_nr_;
    });
  });

  for(;;) {
    if(exited) {
      g_assert_cmpint(exit_status, ==, 0);
      break;
    }
    else if(line_nr>0) {
      for(;;) {
        if(Debug::LLDB::get().is_stopped())
          break;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
      }
      g_assert_cmpint(line_nr, ==, 2);
      g_assert(Debug::LLDB::get().get_backtrace().size()>0);
      auto variables=Debug::LLDB::get().get_variables();
      g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
      line_nr=0;
      Debug::LLDB::get().step_over();
      for(;;) {
        if(line_nr>0 && Debug::LLDB::get().is_stopped())
          break;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
      }
      g_assert_cmpint(line_nr, ==, 3);
      g_assert(Debug::LLDB::get().get_backtrace().size()>0);
      variables=Debug::LLDB::get().get_variables();
      g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
      auto value=Debug::LLDB::get().get_value("an_int", source_path, 2, 7);
      g_assert_cmpuint(value.size(), >, 16);
      auto value_substr=value.substr(0, 16);
      g_assert_cmpstr(value_substr.c_str(), ==, "(int) an_int = 1");
      line_nr=0;
      Debug::LLDB::get().continue_debug();
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  Debug::LLDB::get().cancel();

  debug_thread.join();
}
<|endoftext|>


<commit_before>#include "game_state.hpp"

#include "start_game_state.hpp"
#include "logger.hpp"
#include "exception.hpp"

static boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;

namespace Quoridor {

static std::vector<std::string> colors = {"red", "green", "blue", "yellow"};
std::string GameState::name_("Game State");

GameState::GameState(std::shared_ptr<StateManager> stm,
        const std::vector<std::string> &player_types) : stm_(stm), anim_(),
    game_(new Game(9, 9)), pf_(), players_(), pawn_list_(), cur_pawn_(),
    drag_list_(), pawn_wins_(), wall_wins_(), pawn_path_(),
    added_wall_(Wall::kInvalid, 0, 0, 0), wall_idx_(0),
    status_(kWaitingForMove),
    pos_utils_(9, 52, 50)
{
    lg.add_attribute("Tag", blattrs::constant<std::string>("game state"));

    init_gui_();
    subscribe_for_events_();

    if ((player_types.size() != 2) && (player_types.size() != 4)) {
        throw Exception("Invalid number of players");
    }

    for (size_t i = 0; i < player_types.size(); ++i) {
        std::shared_ptr<Pawn> pawn(new Pawn(colors[i]));
        pawn_list_.push_back(pawn);
    }

    try {
        game_->set_pawns(pawn_list_);
    }
    catch (Exception &e) {
        BOOST_LOG_ERROR(lg) << "failed to create game: " << e.what();
        throw;
    }

    int i = 0;
    for (auto player_type : player_types) {
        BOOST_LOG_INFO(lg) << "adding player " << player_type << " (" << colors[i] << ")";
        players_[pawn_list_[i]] = pf_.make_player(player_type, game_, pawn_list_[i]);
        ++i;
    }

    set_pawns_();
    init_walls_();
    switch_cur_pawn_();

    if (drag_list_.count(cur_pawn_)) {
        drag_list_[cur_pawn_]->enable_drag();
    }
}

GameState::~GameState()
{
}

void GameState::update()
{
    switch (status_) {
    case kPreparingMove:
        pre_process_move_();
        status_ = kWaitingForMove;
        break;
    case kWaitingForMove:
        make_move_();
        break;
    case kPerformedMove:
        post_process_move_();
        if (is_finished_()) {
            BOOST_LOG_INFO(lg) << cur_pawn_->color() << " win";
            status_ = kFinished;
        }
        else {
            switch_cur_pawn_();
            status_ = kPreparingMove;
        }
        break;
    case kNeedPawnRedraw:
        redraw_pawn_();
        status_ = kWaitingForAnimationEnd;
        break;
    case kNeedDrawWall:
        draw_wall_();
        status_ = kPerformedMove;
        break;
    case kWaitingForAnimationEnd:
        break;
    case kFinished:
        break;
    default:
        break;
    }
}

std::shared_ptr<CEGUI::Window> GameState::window() const
{
    return win_;
}

const std::string &GameState::name() const
{
    return name_;
}

void GameState::init_gui_()
{
    CEGUI::ImageManager::getSingleton().loadImageset("pawn.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("board.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("wall.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("wall_repr.imageset");

    win_ = std::shared_ptr<CEGUI::Window>(
            CEGUI::WindowManager::getSingleton().
                    loadLayoutFromFile("game.layout"),
            [=](CEGUI::Window *w) {
                CEGUI::WindowManager::getSingleton().destroyWindow(w);
            }
    );

    anim_ = std::shared_ptr<CEGUI::Animation>(
            CEGUI::AnimationManager::getSingleton().
                    createAnimation("movePawn"),
            [=](CEGUI::Animation *anim) {
                CEGUI::AnimationManager::getSingleton().destroyAnimation(anim);
            }
    );
    anim_->setDuration(0.5);
    anim_->setReplayMode(CEGUI::Animation::RM_Once);
}

void GameState::set_pawns_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));

    board_win->subscribeEvent(
            CEGUI_Ext::DraggableWindow::EventDraggableWindowDropped,
            CEGUI::Event::Subscriber(&GameState::handle_window_dropped_, this));

    CEGUI::Window *drag_win;
    for (auto pawn_data : game_->pawn_data_list()) {
        if (players_[pawn_data.pawn]->is_interactive()) {
            drag_win = new CEGUI_Ext::DraggableWindow("DefaultWindow", pawn_data.pawn->color());
            drag_list_[pawn_data.pawn] = static_cast<CEGUI_Ext::DraggableWindow*>(drag_win);
            drag_list_[pawn_data.pawn]->disable_drag();
            pawn_wins_[drag_win] = pawn_data.pawn;
        }
        else {
            drag_win = CEGUI::WindowManager::getSingleton().
                createWindow("DefaultWindow", pawn_data.pawn->color());
            drag_win->subscribeEvent(
                    CEGUI::AnimationInstance::EventAnimationEnded,
                    CEGUI::Event::Subscriber(&GameState::handle_end_anim_, this));
        }

        drag_win->setSize(CEGUI::USize({0.1, 0}, {0.1, 0}));
        CEGUI::UVector2 pos = pos_utils_.node_to_pos(pawn_data.node);
        drag_win->setPosition(pos);

        auto pawn_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("pawn_anim.layout");
        drag_win->addChild(pawn_win);
        board_win->addChild(drag_win);
    }
}

void GameState::init_walls_()
{
    auto ws1 = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));
    for (int i = 0; i < 10; ++i) {
        auto w1 = new CEGUI_Ext::DraggableWindow("DefaultWindow", "wall_1_" + std::to_string(i));
        w1->setPosition(CEGUI::UVector2({{0.0f, 25.0f * i + 4.0f}, {0.0f, 4.0f}}));
        w1->setSize(CEGUI::USize({{0.0, 21.0}, {0.0, 42.0}}));

        auto wall_img = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("wall_repr.layout");
        w1->addChild(wall_img);
        ws1->addChild(w1);

        wall_wins_[w1] = 1;
    }
}

void GameState::redraw_pawn_()
{
    Node old_node = pawn_path_[0];
    Node new_node = pawn_path_[1];

    pawn_path_.clear();

    CEGUI::UVector2 old_pos = pos_utils_.node_to_pos(old_node);
    CEGUI::UVector2 new_pos = pos_utils_.node_to_pos(new_node);
    std::string old_pos_str = "{{" + std::to_string(old_pos.d_x.d_scale) + ", "
        + std::to_string(old_pos.d_x.d_offset) + "}, {"
        + std::to_string(old_pos.d_y.d_scale) + ", "
        + std::to_string(old_pos.d_y.d_offset)+ "}}";
    std::string new_pos_str = "{{" + std::to_string(new_pos.d_x.d_scale) + ", "
        + std::to_string(new_pos.d_x.d_offset) + "}, {"
        + std::to_string(new_pos.d_y.d_scale) + ", "
        + std::to_string(new_pos.d_y.d_offset)+ "}}";

    CEGUI::Affector *affector = anim_->createAffector("Position", "UVector2");
    affector->setApplicationMethod(CEGUI::Affector::AM_Absolute);
    affector->createKeyFrame(0.0, old_pos_str);
    affector->createKeyFrame(0.5, new_pos_str);

    auto pawn_win = win_->getChild("boardWindow/" + cur_pawn_->color());
    CEGUI::AnimationInstance *instance = CEGUI::AnimationManager::
            getSingleton().instantiateAnimation(anim_.get());
    instance->setTargetWindow(pawn_win);
    instance->start();
}

void GameState::draw_wall_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));
    Node node;
    CEGUI::UVector2 pos;

    if (added_wall_.orientation() == Wall::kHorizontal) {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            node.set_row(added_wall_.row() - 1);
            node.set_col(added_wall_.col() + i);
            pos = pos_utils_.node_to_pos(node);
            pos.d_y.d_offset = -2.0;
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("horizontal_wall.layout");
            wall_win->setPosition(pos);
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
        }
    }
    else if (added_wall_.orientation() == Wall::kVertical) {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            node.set_row(added_wall_.row() + i);
            node.set_col(added_wall_.col());
            pos = pos_utils_.node_to_pos(node);
            pos.d_x.d_offset = -2.0;
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("vertical_wall.layout");
            wall_win->setPosition(pos);
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
        }
    }
}

void GameState::pre_process_move_()
{
    if (drag_list_.count(cur_pawn_)) {
        drag_list_.at(cur_pawn_)->enable_drag();
    }
}

void GameState::post_process_move_()
{
    if (drag_list_.count(cur_pawn_)) {
        drag_list_.at(cur_pawn_)->disable_drag();
    }
}

void GameState::switch_cur_pawn_()
{
    game_->switch_pawn();
    cur_pawn_ = game_->cur_pawn_data().pawn;
}

void GameState::make_move_()
{
    // human's turn, handle it in one of event handlers
    if (players_[cur_pawn_]->is_interactive()) {
        return;
    }

    move_t move = players_[cur_pawn_]->get_move();
    if (Node *node = boost::get<Node>(&move)) {
        Node cur_node = game_->cur_pawn_data().node;
        if (move_pawn_(*node) == 0) {
            pawn_path_.push_back(cur_node);
            pawn_path_.push_back(*node);
            status_ = kNeedPawnRedraw;
        }
    }
    else if (Wall *wall = boost::get<Wall>(&move)) {
        if (add_wall_(*wall) == 0) {
            status_ = kNeedDrawWall;
        }
    }
}

int GameState::move_pawn_(const Node &node)
{
    Node cur_node = game_->cur_pawn_data().node;
    int rc = game_->move_pawn(node);
    if (rc == 0) {
        BOOST_LOG_INFO(lg) << cur_pawn_->color() << ": " << cur_node << " -> "
            << node;
    }
    return rc;
}

int GameState::add_wall_(const Wall &wall)
{
    int rc = game_->add_wall(wall);
    if (rc == 0) {
        BOOST_LOG_INFO(lg) << cur_pawn_->color() << ": " << wall;
        added_wall_ = wall;
    }
    return rc;
}

bool GameState::is_finished_() const
{
    return game_->is_finished();
}

void GameState::subscribe_for_events_()
{
    win_->getChild("back")->subscribeEvent(
            CEGUI::Window::EventMouseClick,
            CEGUI::Event::Subscriber(
                    &GameState::handle_back_, this
            )
    );
}

bool GameState::handle_back_(const CEGUI::EventArgs &/* e */)
{
    BOOST_LOG_DEBUG(lg) << "returning to start game menu";
    stm_->change_state(std::shared_ptr<IState>(new StartGameState(stm_)));
    return true;
}

bool GameState::handle_end_anim_(const CEGUI::EventArgs &/* e */)
{
    status_ = kPerformedMove;
    return true;
}

bool GameState::handle_window_dropped_(const CEGUI::EventArgs &e)
{
    auto de = static_cast<const CEGUI_Ext::DragEvent&>(e);
    if (pawn_wins_.count(de.window())) {
        return handle_pawn_dropped_(de);
    }
    else if (wall_wins_.count(de.window())) {
        return handle_wall_dropped_(de);
    }
    else {
        return false;
    }
}

bool GameState::handle_pawn_dropped_(const CEGUI_Ext::DragEvent &de)
{
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {568, 568}  // @fixme get parent size
    );
    Node node = normalize_pawn_pos_(rel_pos);

    CEGUI::UVector2 pos;
    int rc = move_pawn_(node);
    if (rc == 0) {
        pos = pos_utils_.node_to_pos(node);
        status_ = kPerformedMove;
    }
    else {
        Node cur_node = game_->cur_pawn_data().node;
        pos = pos_utils_.node_to_pos(cur_node);
    }

    de.window()->setPosition(pos);

    return true;
}

bool GameState::handle_wall_dropped_(const CEGUI_Ext::DragEvent &de)
{
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {568, 568}  // @fixme get parent size
    );
    Wall wall = normalize_wall_pos_(rel_pos);
    int rc = add_wall_(wall);
    if (rc == 0) {
        status_ = kNeedDrawWall;
        de.window()->setVisible(false);
    }

    return true;
}

Node GameState::normalize_pawn_pos_(const CEGUI::Vector2f &rel_pos)
{
    CEGUI::UVector2 pos({rel_pos.d_x, 0.0}, {rel_pos.d_y, 0.0});
    return pos_utils_.pos_to_node(pos);
}

Wall GameState::normalize_wall_pos_(const CEGUI::Vector2f &rel_pos)
{
    CEGUI::UVector2 pos({rel_pos.d_x, 0.0}, {rel_pos.d_y, 0.0});
    Wall wall = pos_utils_.pos_to_wall(pos, 2);
    return wall;
}

}  /* namespace Quoridor */
<commit_msg>Check move validness in GameState::make_move_<commit_after>#include "game_state.hpp"

#include "start_game_state.hpp"
#include "logger.hpp"
#include "exception.hpp"

static boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;

namespace Quoridor {

static std::vector<std::string> colors = {"red", "green", "blue", "yellow"};
std::string GameState::name_("Game State");

GameState::GameState(std::shared_ptr<StateManager> stm,
        const std::vector<std::string> &player_types) : stm_(stm), anim_(),
    game_(new Game(9, 9)), pf_(), players_(), pawn_list_(), cur_pawn_(),
    drag_list_(), pawn_wins_(), wall_wins_(), pawn_path_(),
    added_wall_(Wall::kInvalid, 0, 0, 0), wall_idx_(0),
    status_(kWaitingForMove),
    pos_utils_(9, 52, 50)
{
    lg.add_attribute("Tag", blattrs::constant<std::string>("game state"));

    init_gui_();
    subscribe_for_events_();

    if ((player_types.size() != 2) && (player_types.size() != 4)) {
        throw Exception("Invalid number of players");
    }

    for (size_t i = 0; i < player_types.size(); ++i) {
        std::shared_ptr<Pawn> pawn(new Pawn(colors[i]));
        pawn_list_.push_back(pawn);
    }

    try {
        game_->set_pawns(pawn_list_);
    }
    catch (Exception &e) {
        BOOST_LOG_ERROR(lg) << "failed to create game: " << e.what();
        throw;
    }

    int i = 0;
    for (auto player_type : player_types) {
        BOOST_LOG_INFO(lg) << "adding player " << player_type << " (" << colors[i] << ")";
        players_[pawn_list_[i]] = pf_.make_player(player_type, game_, pawn_list_[i]);
        ++i;
    }

    set_pawns_();
    init_walls_();
    switch_cur_pawn_();

    if (drag_list_.count(cur_pawn_)) {
        drag_list_[cur_pawn_]->enable_drag();
    }
}

GameState::~GameState()
{
}

void GameState::update()
{
    switch (status_) {
    case kPreparingMove:
        pre_process_move_();
        status_ = kWaitingForMove;
        break;
    case kWaitingForMove:
        make_move_();
        break;
    case kPerformedMove:
        post_process_move_();
        if (is_finished_()) {
            BOOST_LOG_INFO(lg) << cur_pawn_->color() << " win";
            status_ = kFinished;
        }
        else {
            switch_cur_pawn_();
            status_ = kPreparingMove;
        }
        break;
    case kNeedPawnRedraw:
        redraw_pawn_();
        status_ = kWaitingForAnimationEnd;
        break;
    case kNeedDrawWall:
        draw_wall_();
        status_ = kPerformedMove;
        break;
    case kWaitingForAnimationEnd:
        break;
    case kFinished:
        break;
    default:
        break;
    }
}

std::shared_ptr<CEGUI::Window> GameState::window() const
{
    return win_;
}

const std::string &GameState::name() const
{
    return name_;
}

void GameState::init_gui_()
{
    CEGUI::ImageManager::getSingleton().loadImageset("pawn.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("board.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("wall.imageset");
    CEGUI::ImageManager::getSingleton().loadImageset("wall_repr.imageset");

    win_ = std::shared_ptr<CEGUI::Window>(
            CEGUI::WindowManager::getSingleton().
                    loadLayoutFromFile("game.layout"),
            [=](CEGUI::Window *w) {
                CEGUI::WindowManager::getSingleton().destroyWindow(w);
            }
    );

    anim_ = std::shared_ptr<CEGUI::Animation>(
            CEGUI::AnimationManager::getSingleton().
                    createAnimation("movePawn"),
            [=](CEGUI::Animation *anim) {
                CEGUI::AnimationManager::getSingleton().destroyAnimation(anim);
            }
    );
    anim_->setDuration(0.5);
    anim_->setReplayMode(CEGUI::Animation::RM_Once);
}

void GameState::set_pawns_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));

    board_win->subscribeEvent(
            CEGUI_Ext::DraggableWindow::EventDraggableWindowDropped,
            CEGUI::Event::Subscriber(&GameState::handle_window_dropped_, this));

    CEGUI::Window *drag_win;
    for (auto pawn_data : game_->pawn_data_list()) {
        if (players_[pawn_data.pawn]->is_interactive()) {
            drag_win = new CEGUI_Ext::DraggableWindow("DefaultWindow", pawn_data.pawn->color());
            drag_list_[pawn_data.pawn] = static_cast<CEGUI_Ext::DraggableWindow*>(drag_win);
            drag_list_[pawn_data.pawn]->disable_drag();
            pawn_wins_[drag_win] = pawn_data.pawn;
        }
        else {
            drag_win = CEGUI::WindowManager::getSingleton().
                createWindow("DefaultWindow", pawn_data.pawn->color());
            drag_win->subscribeEvent(
                    CEGUI::AnimationInstance::EventAnimationEnded,
                    CEGUI::Event::Subscriber(&GameState::handle_end_anim_, this));
        }

        drag_win->setSize(CEGUI::USize({0.1, 0}, {0.1, 0}));
        CEGUI::UVector2 pos = pos_utils_.node_to_pos(pawn_data.node);
        drag_win->setPosition(pos);

        auto pawn_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("pawn_anim.layout");
        drag_win->addChild(pawn_win);
        board_win->addChild(drag_win);
    }
}

void GameState::init_walls_()
{
    auto ws1 = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));
    for (int i = 0; i < 10; ++i) {
        auto w1 = new CEGUI_Ext::DraggableWindow("DefaultWindow", "wall_1_" + std::to_string(i));
        w1->setPosition(CEGUI::UVector2({{0.0f, 25.0f * i + 4.0f}, {0.0f, 4.0f}}));
        w1->setSize(CEGUI::USize({{0.0, 21.0}, {0.0, 42.0}}));

        auto wall_img = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("wall_repr.layout");
        w1->addChild(wall_img);
        ws1->addChild(w1);

        wall_wins_[w1] = 1;
    }
}

void GameState::redraw_pawn_()
{
    Node old_node = pawn_path_[0];
    Node new_node = pawn_path_[1];

    pawn_path_.clear();

    CEGUI::UVector2 old_pos = pos_utils_.node_to_pos(old_node);
    CEGUI::UVector2 new_pos = pos_utils_.node_to_pos(new_node);
    std::string old_pos_str = "{{" + std::to_string(old_pos.d_x.d_scale) + ", "
        + std::to_string(old_pos.d_x.d_offset) + "}, {"
        + std::to_string(old_pos.d_y.d_scale) + ", "
        + std::to_string(old_pos.d_y.d_offset)+ "}}";
    std::string new_pos_str = "{{" + std::to_string(new_pos.d_x.d_scale) + ", "
        + std::to_string(new_pos.d_x.d_offset) + "}, {"
        + std::to_string(new_pos.d_y.d_scale) + ", "
        + std::to_string(new_pos.d_y.d_offset)+ "}}";

    CEGUI::Affector *affector = anim_->createAffector("Position", "UVector2");
    affector->setApplicationMethod(CEGUI::Affector::AM_Absolute);
    affector->createKeyFrame(0.0, old_pos_str);
    affector->createKeyFrame(0.5, new_pos_str);

    auto pawn_win = win_->getChild("boardWindow/" + cur_pawn_->color());
    CEGUI::AnimationInstance *instance = CEGUI::AnimationManager::
            getSingleton().instantiateAnimation(anim_.get());
    instance->setTargetWindow(pawn_win);
    instance->start();
}

void GameState::draw_wall_()
{
    auto board_win = static_cast<CEGUI::DefaultWindow*>(win_->getChild("boardWindow"));
    Node node;
    CEGUI::UVector2 pos;

    if (added_wall_.orientation() == Wall::kHorizontal) {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            node.set_row(added_wall_.row() - 1);
            node.set_col(added_wall_.col() + i);
            pos = pos_utils_.node_to_pos(node);
            pos.d_y.d_offset = -2.0;
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("horizontal_wall.layout");
            wall_win->setPosition(pos);
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
        }
    }
    else if (added_wall_.orientation() == Wall::kVertical) {
        for (int i = 0; i < added_wall_.cnt(); ++i) {
            node.set_row(added_wall_.row() + i);
            node.set_col(added_wall_.col());
            pos = pos_utils_.node_to_pos(node);
            pos.d_x.d_offset = -2.0;
            auto wall_win = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("vertical_wall.layout");
            wall_win->setPosition(pos);
            wall_win->setName("wallWindow" + std::to_string(wall_idx_));
            ++wall_idx_;
            board_win->addChild(wall_win);
        }
    }
}

void GameState::pre_process_move_()
{
    if (drag_list_.count(cur_pawn_)) {
        drag_list_.at(cur_pawn_)->enable_drag();
    }
}

void GameState::post_process_move_()
{
    if (drag_list_.count(cur_pawn_)) {
        drag_list_.at(cur_pawn_)->disable_drag();
    }
}

void GameState::switch_cur_pawn_()
{
    game_->switch_pawn();
    cur_pawn_ = game_->cur_pawn_data().pawn;
}

void GameState::make_move_()
{
    // human's turn, handle it in one of event handlers
    if (players_[cur_pawn_]->is_interactive()) {
        return;
    }

    move_t move = players_[cur_pawn_]->get_move();
    if (move.which() == 0) {
        throw Exception("invalid move");
    }

    if (Node *node = boost::get<Node>(&move)) {
        Node cur_node = game_->cur_pawn_data().node;
        if (move_pawn_(*node) == 0) {
            pawn_path_.push_back(cur_node);
            pawn_path_.push_back(*node);
            status_ = kNeedPawnRedraw;
        }
    }
    else if (Wall *wall = boost::get<Wall>(&move)) {
        if (add_wall_(*wall) == 0) {
            status_ = kNeedDrawWall;
        }
    }
}

int GameState::move_pawn_(const Node &node)
{
    Node cur_node = game_->cur_pawn_data().node;
    int rc = game_->move_pawn(node);
    if (rc == 0) {
        BOOST_LOG_INFO(lg) << cur_pawn_->color() << ": " << cur_node << " -> "
            << node;
    }
    return rc;
}

int GameState::add_wall_(const Wall &wall)
{
    int rc = game_->add_wall(wall);
    if (rc == 0) {
        BOOST_LOG_INFO(lg) << cur_pawn_->color() << ": " << wall;
        added_wall_ = wall;
    }
    return rc;
}

bool GameState::is_finished_() const
{
    return game_->is_finished();
}

void GameState::subscribe_for_events_()
{
    win_->getChild("back")->subscribeEvent(
            CEGUI::Window::EventMouseClick,
            CEGUI::Event::Subscriber(
                    &GameState::handle_back_, this
            )
    );
}

bool GameState::handle_back_(const CEGUI::EventArgs &/* e */)
{
    BOOST_LOG_DEBUG(lg) << "returning to start game menu";
    stm_->change_state(std::shared_ptr<IState>(new StartGameState(stm_)));
    return true;
}

bool GameState::handle_end_anim_(const CEGUI::EventArgs &/* e */)
{
    status_ = kPerformedMove;
    return true;
}

bool GameState::handle_window_dropped_(const CEGUI::EventArgs &e)
{
    auto de = static_cast<const CEGUI_Ext::DragEvent&>(e);
    if (pawn_wins_.count(de.window())) {
        return handle_pawn_dropped_(de);
    }
    else if (wall_wins_.count(de.window())) {
        return handle_wall_dropped_(de);
    }
    else {
        return false;
    }
}

bool GameState::handle_pawn_dropped_(const CEGUI_Ext::DragEvent &de)
{
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {568, 568}  // @fixme get parent size
    );
    Node node = normalize_pawn_pos_(rel_pos);

    CEGUI::UVector2 pos;
    int rc = move_pawn_(node);
    if (rc == 0) {
        pos = pos_utils_.node_to_pos(node);
        status_ = kPerformedMove;
    }
    else {
        Node cur_node = game_->cur_pawn_data().node;
        pos = pos_utils_.node_to_pos(cur_node);
    }

    de.window()->setPosition(pos);

    return true;
}

bool GameState::handle_wall_dropped_(const CEGUI_Ext::DragEvent &de)
{
    CEGUI::Vector2f rel_pos = CEGUI::CoordConverter::asRelative(
            de.window()->getPosition() + de.pos(),
            {568, 568}  // @fixme get parent size
    );
    Wall wall = normalize_wall_pos_(rel_pos);
    int rc = add_wall_(wall);
    if (rc == 0) {
        status_ = kNeedDrawWall;
        de.window()->setVisible(false);
    }

    return true;
}

Node GameState::normalize_pawn_pos_(const CEGUI::Vector2f &rel_pos)
{
    CEGUI::UVector2 pos({rel_pos.d_x, 0.0}, {rel_pos.d_y, 0.0});
    return pos_utils_.pos_to_node(pos);
}

Wall GameState::normalize_wall_pos_(const CEGUI::Vector2f &rel_pos)
{
    CEGUI::UVector2 pos({rel_pos.d_x, 0.0}, {rel_pos.d_y, 0.0});
    Wall wall = pos_utils_.pos_to_wall(pos, 2);
    return wall;
}

}  /* namespace Quoridor */
<|endoftext|>


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

#include "src/core/lib/gprpp/notification.h"

#include <thread>

#include "gtest/gtest.h"

namespace grpc_core {
namespace testing {
namespace {

TEST(Notification, Works) {
  Notification n;
  EXPECT_FALSE(n.HasBeenNotified());
  n.Notify();
  EXPECT_TRUE(n.HasBeenNotified());
  n.WaitForNotification();
  EXPECT_TRUE(n.HasBeenNotified());
}

TEST(Notification, Waits) {
  Notification n;
  auto start = absl::Now();
  std::thread t([&n] {
    absl::SleepFor(absl::Seconds(5));
    n.Notify();
  });
  n.WaitForNotification();
  auto end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(5));
  t.join();
}

TEST(Notification, WaitsWithTimeout) {
  Notification n;
  auto start = absl::Now();
  std::thread t([&n] {
    absl::SleepFor(absl::Seconds(5));
    n.Notify();
  });
  EXPECT_TRUE(n.WaitForNotificationWithTimeout(absl::Seconds(10)));
  auto end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(5));
  EXPECT_LE(end - start, absl::Seconds(10));
  t.join();
}

TEST(Notification, WaitWithTimeoutCanFinishEarly) {
  Notification n;
  auto start = absl::Now();
  std::thread t([&n] {
    absl::SleepFor(absl::Seconds(5));
    n.Notify();
  });
  EXPECT_FALSE(n.WaitForNotificationWithTimeout(absl::Seconds(1)));
  auto end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(1));
  EXPECT_LE(end - start, absl::Seconds(5));
  n.WaitForNotification();
  end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(5));
  t.join();
}

}  // namespace
}  // namespace testing
}  // namespace grpc_core

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>[notification] sloppier tests (#31422)<commit_after>// Copyright 2022 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/core/lib/gprpp/notification.h"

#include <thread>

#include "gtest/gtest.h"

namespace grpc_core {
namespace testing {
namespace {

TEST(Notification, Works) {
  Notification n;
  EXPECT_FALSE(n.HasBeenNotified());
  n.Notify();
  EXPECT_TRUE(n.HasBeenNotified());
  n.WaitForNotification();
  EXPECT_TRUE(n.HasBeenNotified());
}

TEST(Notification, Waits) {
  Notification n;
  auto start = absl::Now();
  std::thread t([&n] {
    absl::SleepFor(absl::Seconds(6));
    n.Notify();
  });
  n.WaitForNotification();
  auto end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(5));
  t.join();
}

TEST(Notification, WaitsWithTimeout) {
  Notification n;
  auto start = absl::Now();
  std::thread t([&n] {
    absl::SleepFor(absl::Seconds(6));
    n.Notify();
  });
  EXPECT_TRUE(n.WaitForNotificationWithTimeout(absl::Seconds(10)));
  auto end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(5));
  EXPECT_LE(end - start, absl::Seconds(10));
  t.join();
}

TEST(Notification, WaitWithTimeoutCanFinishEarly) {
  Notification n;
  auto start = absl::Now();
  std::thread t([&n] {
    absl::SleepFor(absl::Seconds(6));
    n.Notify();
  });
  EXPECT_FALSE(n.WaitForNotificationWithTimeout(absl::Seconds(1)));
  auto end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(1));
  EXPECT_LE(end - start, absl::Seconds(5));
  n.WaitForNotification();
  end = absl::Now();
  EXPECT_GE(end - start, absl::Seconds(5));
  t.join();
}

}  // namespace
}  // namespace testing
}  // namespace grpc_core

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


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

#include <grpc/support/port_platform.h>
#include "test/core/util/test_config.h"

#ifdef GRPC_TEST_PICK_PORT
#include "test/core/util/port_server_client.h"

#include <math.h>
#include <string.h>

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>

#include "src/core/lib/http/httpcli.h"

typedef struct freereq {
  gpr_mu* mu;
  grpc_polling_entity pops;
  int done;
} freereq;

static void destroy_pops_and_shutdown(void* p, grpc_error* error) {
  grpc_pollset* pollset =
      grpc_polling_entity_pollset(static_cast<grpc_polling_entity*>(p));
  grpc_pollset_destroy(pollset);
  gpr_free(pollset);
}

static void freed_port_from_server(void* arg, grpc_error* error) {
  freereq* pr = static_cast<freereq*>(arg);
  gpr_mu_lock(pr->mu);
  pr->done = 1;
  GRPC_LOG_IF_ERROR(
      "pollset_kick",
      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
  gpr_mu_unlock(pr->mu);
}

void grpc_free_port_using_server(int port) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  grpc_httpcli_response rsp;
  freereq pr;
  char* path;
  grpc_core::ExecCtx exec_ctx;
  grpc_closure* shutdown_closure;

  grpc_init();

  memset(&pr, 0, sizeof(pr));
  memset(&req, 0, sizeof(req));
  memset(&rsp, 0, sizeof(rsp));

  grpc_pollset* pollset =
      static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
  grpc_pollset_init(pollset, &pr.mu);
  pr.pops = grpc_polling_entity_create_from_pollset(pollset);
  shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops,
                                         grpc_schedule_on_exec_ctx);

  req.host = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS);
  gpr_asprintf(&path, "/drop/%d", port);
  req.http.path = path;

  grpc_httpcli_context_init(&context);
  grpc_resource_quota* resource_quota =
      grpc_resource_quota_create("port_server_client/free");
  grpc_httpcli_get(&context, &pr.pops, resource_quota, &req,
                   grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC,
                   GRPC_CLOSURE_CREATE(freed_port_from_server, &pr,
                                       grpc_schedule_on_exec_ctx),
                   &rsp);
  grpc_resource_quota_unref_internal(resource_quota);
  grpc_core::ExecCtx::Get()->Flush();
  gpr_mu_lock(pr.mu);
  while (!pr.done) {
    grpc_pollset_worker* worker = nullptr;
    if (!GRPC_LOG_IF_ERROR(
            "pollset_work",
            grpc_pollset_work(
                grpc_polling_entity_pollset(&pr.pops), &worker,
                grpc_core::ExecCtx::Get()->Now() + GPR_MS_PER_SEC))) {
      pr.done = 1;
    }
  }
  gpr_mu_unlock(pr.mu);

  grpc_httpcli_context_destroy(&context);
  grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops),
                        shutdown_closure);

  gpr_free(path);
  grpc_http_response_destroy(&rsp);

  grpc_shutdown();
}

typedef struct portreq {
  gpr_mu* mu;
  grpc_polling_entity pops;
  int port;
  int retries;
  char* server;
  grpc_httpcli_context* ctx;
  grpc_httpcli_response response;
} portreq;

static void got_port_from_server(void* arg, grpc_error* error) {
  size_t i;
  int port = 0;
  portreq* pr = static_cast<portreq*>(arg);
  int failed = 0;
  grpc_httpcli_response* response = &pr->response;

  if (error != GRPC_ERROR_NONE) {
    failed = 1;
    const char* msg = grpc_error_string(error);
    gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);

  } else if (response->status != 200) {
    failed = 1;
    gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
            response->status);
  }

  if (failed) {
    grpc_httpcli_request req;
    memset(&req, 0, sizeof(req));
    if (pr->retries >= 5) {
      gpr_mu_lock(pr->mu);
      pr->port = 0;
      GRPC_LOG_IF_ERROR(
          "pollset_kick",
          grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
      gpr_mu_unlock(pr->mu);
      return;
    }
    GPR_ASSERT(pr->retries < 10);
    gpr_sleep_until(gpr_time_add(
        gpr_now(GPR_CLOCK_REALTIME),
        gpr_time_from_millis(
            static_cast<int64_t>(
                1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
            GPR_TIMESPAN)));
    pr->retries++;
    req.host = pr->server;
    req.http.path = const_cast<char*>("/get");
    grpc_http_response_destroy(&pr->response);
    memset(&pr->response, 0, sizeof(pr->response));
    grpc_resource_quota* resource_quota =
        grpc_resource_quota_create("port_server_client/pick_retry");
    grpc_httpcli_get(pr->ctx, &pr->pops, resource_quota, &req,
                     grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC,
                     GRPC_CLOSURE_CREATE(got_port_from_server, pr,
                                         grpc_schedule_on_exec_ctx),
                     &pr->response);
    grpc_resource_quota_unref_internal(resource_quota);
    return;
  }
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  for (i = 0; i < response->body_length; i++) {
    GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
    port = port * 10 + response->body[i] - '0';
  }
  GPR_ASSERT(port > 1024);
  gpr_mu_lock(pr->mu);
  pr->port = port;
  GRPC_LOG_IF_ERROR(
      "pollset_kick",
      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
  gpr_mu_unlock(pr->mu);
}

int grpc_pick_port_using_server(void) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  portreq pr;
  grpc_closure* shutdown_closure;

  grpc_init();
  {
    grpc_core::ExecCtx exec_ctx;
    memset(&pr, 0, sizeof(pr));
    memset(&req, 0, sizeof(req));
    grpc_pollset* pollset =
        static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
    grpc_pollset_init(pollset, &pr.mu);
    pr.pops = grpc_polling_entity_create_from_pollset(pollset);
    shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops,
                                           grpc_schedule_on_exec_ctx);
    pr.port = -1;
    pr.server = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS);
    pr.ctx = &context;

    req.host = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS);
    req.http.path = const_cast<char*>("/get");

    grpc_httpcli_context_init(&context);
    grpc_resource_quota* resource_quota =
        grpc_resource_quota_create("port_server_client/pick");
    grpc_httpcli_get(&context, &pr.pops, resource_quota, &req,
                     grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC,
                     GRPC_CLOSURE_CREATE(got_port_from_server, &pr,
                                         grpc_schedule_on_exec_ctx),
                     &pr.response);
    grpc_resource_quota_unref_internal(resource_quota);
    grpc_core::ExecCtx::Get()->Flush();
    gpr_mu_lock(pr.mu);
    while (pr.port == -1) {
      grpc_pollset_worker* worker = nullptr;
      if (!GRPC_LOG_IF_ERROR(
              "pollset_work",
              grpc_pollset_work(
                  grpc_polling_entity_pollset(&pr.pops), &worker,
                  grpc_core::ExecCtx::Get()->Now() + GPR_MS_PER_SEC))) {
        pr.port = 0;
      }
    }
    gpr_mu_unlock(pr.mu);

    grpc_http_response_destroy(&pr.response);
    grpc_httpcli_context_destroy(&context);
    grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops),
                          shutdown_closure);

    grpc_core::ExecCtx::Get()->Flush();
  }
  grpc_shutdown();

  return pr.port;
}

#endif  // GRPC_TEST_PICK_PORT
<commit_msg>Use struct-defined initialization when available<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>
#include "test/core/util/test_config.h"

#ifdef GRPC_TEST_PICK_PORT
#include "test/core/util/port_server_client.h"

#include <math.h>
#include <string.h>

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>

#include "src/core/lib/http/httpcli.h"

typedef struct freereq {
  gpr_mu* mu = nullptr;
  grpc_polling_entity pops = {};
  int done = 0;
} freereq;

static void destroy_pops_and_shutdown(void* p, grpc_error* error) {
  grpc_pollset* pollset =
      grpc_polling_entity_pollset(static_cast<grpc_polling_entity*>(p));
  grpc_pollset_destroy(pollset);
  gpr_free(pollset);
}

static void freed_port_from_server(void* arg, grpc_error* error) {
  freereq* pr = static_cast<freereq*>(arg);
  gpr_mu_lock(pr->mu);
  pr->done = 1;
  GRPC_LOG_IF_ERROR(
      "pollset_kick",
      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
  gpr_mu_unlock(pr->mu);
}

void grpc_free_port_using_server(int port) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  grpc_httpcli_response rsp;
  freereq pr;
  char* path;
  grpc_core::ExecCtx exec_ctx;
  grpc_closure* shutdown_closure;

  grpc_init();

  pr = {};
  memset(&req, 0, sizeof(req));
  rsp = {};

  grpc_pollset* pollset =
      static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
  grpc_pollset_init(pollset, &pr.mu);
  pr.pops = grpc_polling_entity_create_from_pollset(pollset);
  shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops,
                                         grpc_schedule_on_exec_ctx);

  req.host = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS);
  gpr_asprintf(&path, "/drop/%d", port);
  req.http.path = path;

  grpc_httpcli_context_init(&context);
  grpc_resource_quota* resource_quota =
      grpc_resource_quota_create("port_server_client/free");
  grpc_httpcli_get(&context, &pr.pops, resource_quota, &req,
                   grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC,
                   GRPC_CLOSURE_CREATE(freed_port_from_server, &pr,
                                       grpc_schedule_on_exec_ctx),
                   &rsp);
  grpc_resource_quota_unref_internal(resource_quota);
  grpc_core::ExecCtx::Get()->Flush();
  gpr_mu_lock(pr.mu);
  while (!pr.done) {
    grpc_pollset_worker* worker = nullptr;
    if (!GRPC_LOG_IF_ERROR(
            "pollset_work",
            grpc_pollset_work(
                grpc_polling_entity_pollset(&pr.pops), &worker,
                grpc_core::ExecCtx::Get()->Now() + GPR_MS_PER_SEC))) {
      pr.done = 1;
    }
  }
  gpr_mu_unlock(pr.mu);

  grpc_httpcli_context_destroy(&context);
  grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops),
                        shutdown_closure);

  gpr_free(path);
  grpc_http_response_destroy(&rsp);

  grpc_shutdown();
}

typedef struct portreq {
  gpr_mu* mu = nullptr;
  grpc_polling_entity pops = {};
  int port = 0;
  int retries = 0;
  char* server = nullptr;
  grpc_httpcli_context* ctx = nullptr;
  grpc_httpcli_response response = {};
} portreq;

static void got_port_from_server(void* arg, grpc_error* error) {
  size_t i;
  int port = 0;
  portreq* pr = static_cast<portreq*>(arg);
  int failed = 0;
  grpc_httpcli_response* response = &pr->response;

  if (error != GRPC_ERROR_NONE) {
    failed = 1;
    const char* msg = grpc_error_string(error);
    gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);

  } else if (response->status != 200) {
    failed = 1;
    gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",
            response->status);
  }

  if (failed) {
    grpc_httpcli_request req;
    memset(&req, 0, sizeof(req));
    if (pr->retries >= 5) {
      gpr_mu_lock(pr->mu);
      pr->port = 0;
      GRPC_LOG_IF_ERROR(
          "pollset_kick",
          grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
      gpr_mu_unlock(pr->mu);
      return;
    }
    GPR_ASSERT(pr->retries < 10);
    gpr_sleep_until(gpr_time_add(
        gpr_now(GPR_CLOCK_REALTIME),
        gpr_time_from_millis(
            static_cast<int64_t>(
                1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)),
            GPR_TIMESPAN)));
    pr->retries++;
    req.host = pr->server;
    req.http.path = const_cast<char*>("/get");
    grpc_http_response_destroy(&pr->response);
    pr->response = {};
    grpc_resource_quota* resource_quota =
        grpc_resource_quota_create("port_server_client/pick_retry");
    grpc_httpcli_get(pr->ctx, &pr->pops, resource_quota, &req,
                     grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC,
                     GRPC_CLOSURE_CREATE(got_port_from_server, pr,
                                         grpc_schedule_on_exec_ctx),
                     &pr->response);
    grpc_resource_quota_unref_internal(resource_quota);
    return;
  }
  GPR_ASSERT(response);
  GPR_ASSERT(response->status == 200);
  for (i = 0; i < response->body_length; i++) {
    GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9');
    port = port * 10 + response->body[i] - '0';
  }
  GPR_ASSERT(port > 1024);
  gpr_mu_lock(pr->mu);
  pr->port = port;
  GRPC_LOG_IF_ERROR(
      "pollset_kick",
      grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), nullptr));
  gpr_mu_unlock(pr->mu);
}

int grpc_pick_port_using_server(void) {
  grpc_httpcli_context context;
  grpc_httpcli_request req;
  portreq pr;
  grpc_closure* shutdown_closure;

  grpc_init();
  {
    grpc_core::ExecCtx exec_ctx;
    pr = {};
    memset(&req, 0, sizeof(req));
    grpc_pollset* pollset =
        static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
    grpc_pollset_init(pollset, &pr.mu);
    pr.pops = grpc_polling_entity_create_from_pollset(pollset);
    shutdown_closure = GRPC_CLOSURE_CREATE(destroy_pops_and_shutdown, &pr.pops,
                                           grpc_schedule_on_exec_ctx);
    pr.port = -1;
    pr.server = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS);
    pr.ctx = &context;

    req.host = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS);
    req.http.path = const_cast<char*>("/get");

    grpc_httpcli_context_init(&context);
    grpc_resource_quota* resource_quota =
        grpc_resource_quota_create("port_server_client/pick");
    grpc_httpcli_get(&context, &pr.pops, resource_quota, &req,
                     grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC,
                     GRPC_CLOSURE_CREATE(got_port_from_server, &pr,
                                         grpc_schedule_on_exec_ctx),
                     &pr.response);
    grpc_resource_quota_unref_internal(resource_quota);
    grpc_core::ExecCtx::Get()->Flush();
    gpr_mu_lock(pr.mu);
    while (pr.port == -1) {
      grpc_pollset_worker* worker = nullptr;
      if (!GRPC_LOG_IF_ERROR(
              "pollset_work",
              grpc_pollset_work(
                  grpc_polling_entity_pollset(&pr.pops), &worker,
                  grpc_core::ExecCtx::Get()->Now() + GPR_MS_PER_SEC))) {
        pr.port = 0;
      }
    }
    gpr_mu_unlock(pr.mu);

    grpc_http_response_destroy(&pr.response);
    grpc_httpcli_context_destroy(&context);
    grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops),
                          shutdown_closure);

    grpc_core::ExecCtx::Get()->Flush();
  }
  grpc_shutdown();

  return pr.port;
}

#endif  // GRPC_TEST_PICK_PORT
<|endoftext|>


<commit_before>

#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING 1
#define ELPP_DEFAULT_LOG_FILE "logs/swgchat.log"

#include "easylogging++.h"

#include "StationChatApp.hpp"

#include <boost/program_options.hpp>

#include <chrono>
#include <fstream>
#include <iostream>
#include <thread>

#ifdef __GNUC__
#include <execinfo.h>
#endif

INITIALIZE_EASYLOGGINGPP

StationChatConfig BuildConfiguration(int argc, const char* argv[]);

#ifdef __GNUC__
void SignalHandler(int sig);
#endif

int main(int argc, const char* argv[]) {
#ifdef __GNUC__
    signal(SIGSEGV, SignalHandler);
#endif

    auto config = BuildConfiguration(argc, argv);

    el::Loggers::setDefaultConfigurations(config.loggerConfig, true);
    START_EASYLOGGINGPP(argc, argv);

    StationChatApp app{config};

    while (app.IsRunning()) {
        app.Tick();
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    return 0;
}

StationChatConfig BuildConfiguration(int argc, const char* argv[]) {
    namespace po = boost::program_options;
    StationChatConfig config;
    std::string configFile;

    // Declare a group of options that will be
    // allowed only on command line
    po::options_description generic("Generic options");
    generic.add_options()
        ("help,h", "produces help message")
        ("config,c", po::value<std::string>(&configFile)->default_value("swgchat.cfg"),
            "sets path to the configuration file")
        ("logger_config", po::value<std::string>(&config.loggerConfig)->default_value("logger.cfg"),
            "sets path to the logger configuration file")
        ;

    po::options_description options("Configuration");
    options.add_options()
        ("gateway_address", po::value<std::string>(&config.gatewayAddress)->default_value("127.0.0.1"),
            "address for gateway connections")
        ("gateway_port", po::value<uint16_t>(&config.gatewayPort)->default_value(5001),
            "port for gateway connections")
        ("registrar_address", po::value<std::string>(&config.registrarAddress)->default_value("127.0.0.1"),
            "address for registrar connections")
        ("registrar_port", po::value<uint16_t>(&config.registrarPort)->default_value(5000),
            "port for registrar connections")
        ("bind_to_ip", po::value<bool>(&config.bindToIp)->default_value(false),
            "when set to true, binds to the config address; otherwise, binds on any interface")
        ("database_path", po::value<std::string>(&config.chatDatabasePath)->default_value("var/stationapi/stationchat.db"),
            "path to the sqlite3 database file")
        ;

    po::options_description cmdline_options;
    cmdline_options.add(generic).add(options);

    po::options_description config_file_options;
    config_file_options.add(options);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(cmdline_options).allow_unregistered().run(), vm);
    po::notify(vm);

    std::ifstream ifs(configFile.c_str());
    if (!ifs) {
        throw std::runtime_error("Cannot open configuration file: " + configFile);
    }

    po::store(po::parse_config_file(ifs, config_file_options), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << cmdline_options << "\n";
        exit(EXIT_SUCCESS);
    }

    return config;
}

#ifdef __GNUC__
void SignalHandler(int sig) {
    const int BACKTRACE_LIMIT = 10;
    void *arr[BACKTRACE_LIMIT];
    auto size = backtrace(arr, BACKTRACE_LIMIT);

    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(arr, size, STDERR_FILENO);
    exit(1);
}
#endif
<commit_msg>Change runtime locations of config files<commit_after>

#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING 1
#define ELPP_DEFAULT_LOG_FILE "logs/swgchat.log"

#include "easylogging++.h"

#include "StationChatApp.hpp"

#include <boost/program_options.hpp>

#include <chrono>
#include <fstream>
#include <iostream>
#include <thread>

#ifdef __GNUC__
#include <execinfo.h>
#endif

INITIALIZE_EASYLOGGINGPP

StationChatConfig BuildConfiguration(int argc, const char* argv[]);

#ifdef __GNUC__
void SignalHandler(int sig);
#endif

int main(int argc, const char* argv[]) {
#ifdef __GNUC__
    signal(SIGSEGV, SignalHandler);
#endif

    auto config = BuildConfiguration(argc, argv);

    el::Loggers::setDefaultConfigurations(config.loggerConfig, true);
    START_EASYLOGGINGPP(argc, argv);

    StationChatApp app{config};

    while (app.IsRunning()) {
        app.Tick();
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    return 0;
}

StationChatConfig BuildConfiguration(int argc, const char* argv[]) {
    namespace po = boost::program_options;
    StationChatConfig config;
    std::string configFile;

    // Declare a group of options that will be
    // allowed only on command line
    po::options_description generic("Generic options");
    generic.add_options()
        ("help,h", "produces help message")
        ("config,c", po::value<std::string>(&configFile)->default_value("etc/stationapi/swgchat.cfg"),
            "sets path to the configuration file")
        ("logger_config", po::value<std::string>(&config.loggerConfig)->default_value("etc/stationapi/logger.cfg"),
            "sets path to the logger configuration file")
        ;

    po::options_description options("Configuration");
    options.add_options()
        ("gateway_address", po::value<std::string>(&config.gatewayAddress)->default_value("127.0.0.1"),
            "address for gateway connections")
        ("gateway_port", po::value<uint16_t>(&config.gatewayPort)->default_value(5001),
            "port for gateway connections")
        ("registrar_address", po::value<std::string>(&config.registrarAddress)->default_value("127.0.0.1"),
            "address for registrar connections")
        ("registrar_port", po::value<uint16_t>(&config.registrarPort)->default_value(5000),
            "port for registrar connections")
        ("bind_to_ip", po::value<bool>(&config.bindToIp)->default_value(false),
            "when set to true, binds to the config address; otherwise, binds on any interface")
        ("database_path", po::value<std::string>(&config.chatDatabasePath)->default_value("var/stationapi/stationchat.db"),
            "path to the sqlite3 database file")
        ;

    po::options_description cmdline_options;
    cmdline_options.add(generic).add(options);

    po::options_description config_file_options;
    config_file_options.add(options);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(cmdline_options).allow_unregistered().run(), vm);
    po::notify(vm);

    std::ifstream ifs(configFile.c_str());
    if (!ifs) {
        throw std::runtime_error("Cannot open configuration file: " + configFile);
    }

    po::store(po::parse_config_file(ifs, config_file_options), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << cmdline_options << "\n";
        exit(EXIT_SUCCESS);
    }

    return config;
}

#ifdef __GNUC__
void SignalHandler(int sig) {
    const int BACKTRACE_LIMIT = 10;
    void *arr[BACKTRACE_LIMIT];
    auto size = backtrace(arr, BACKTRACE_LIMIT);

    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(arr, size, STDERR_FILENO);
    exit(1);
}
#endif
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "ray.hpp"

TEST(ray_test, test_construction)
{
  // Default constructor.
  Ray r1;
  EXPECT_FLOAT_EQ(r1.origin().x(), 0.0f);
  EXPECT_FLOAT_EQ(r1.origin().y(), 0.0f);
  EXPECT_FLOAT_EQ(r1.direction().x(), 0.0f);
  EXPECT_FLOAT_EQ(r1.direction().y(), 0.0f);

  // Constructor with parameters.
  Ray r2(Point2D(1.0f, 1.0f),
         Point2D(0.0f, 1.0f));

  EXPECT_FLOAT_EQ(r2.origin().x(), 1.0f);
  EXPECT_FLOAT_EQ(r2.origin().y(), 1.0f);
  EXPECT_FLOAT_EQ(r2.direction().x(), 0.0f);
  EXPECT_FLOAT_EQ(r2.direction().y(), 1.0f);

  // Copy constructor.
  Ray r3 = r2;

  EXPECT_EQ(r3 == r2, true);
}

TEST(ray_test, test_assignment)
{
  Ray r1;

  r1 = Ray(Point2D(1.0f, 1.0f),
           Point2D(0.0f, 1.0f));

  EXPECT_FLOAT_EQ(r1.origin().x(), 1.0f);
  EXPECT_FLOAT_EQ(r1.origin().y(), 1.0f);
  EXPECT_FLOAT_EQ(r1.direction().x(), 0.0f);
  EXPECT_FLOAT_EQ(r1.direction().y(), 1.0f);
}

TEST(ray_test, test_equality)
{
  Ray r1(Point2D(1.0f, 1.0f),
         Point2D(0.0f, 1.0f));

  Ray r2(Point2D(1.0f, 1.0f),
         Point2D(0.0f, 1.0f));

  Ray r3(Point2D(1.0f, 1.0f),
         Point2D(1.0f, 1.0f));

  EXPECT_EQ(r1, r2);
  EXPECT_NE(r1, r3);
}

TEST(ray_test, test_intersection_outside)
{
  // Send a ray to the right.
  Ray r1(Point2D(0.0f, 0.0f),
         Point2D(1.0f, 0.0f));

  Box2D box1 = { Point2D(1.0f, -1.0f), Point2D(4.0f, 1.0f) };

  EXPECT_EQ(Ray::checkIntersection(r1, box1), true);

  // Send a ray to the left.
  Ray r2(Point2D(0.0f, 0.0f),
         Point2D(-1.0f, 0.0f));

  Box2D box2 = { Point2D(-1.0f, -1.0f), Point2D(-4.0f, 1.0f) };

  EXPECT_EQ(Ray::checkIntersection(r2, box2), true);

  // Send a ray to the upwards.
  Ray r3(Point2D(0.0f, 0.0f),
         Point2D(0.0f, 1.0f));

  Box2D box3 = { Point2D(-1.0f, 1.0f), Point2D(1.0f, 4.0f) };

  EXPECT_EQ(Ray::checkIntersection(r3, box3), true);

  // Send a ray to the bottom.
  Ray r4(Point2D(0.0f, 0.0f),
         Point2D(0.0f, -1.0f));

  Box2D box4 = { Point2D(-1.0f, -1.0f), Point2D(1.0f, -4.0f) };

  EXPECT_EQ(Ray::checkIntersection(r4, box4), true);
}

TEST(ray_test, test_radian_to_degree)
{
  EXPECT_FLOAT_EQ(Ray::convertRadianToDegrees(Constants::PI), 180);
  EXPECT_FLOAT_EQ(Ray::convertRadianToDegrees(0.5 * Constants::PI), 90);
}

TEST(ray_test, test_intersection_inside)
{
  // Ray origin is inside a box.
  Ray r1(Point2D(0.0f, 0.0f),
         Point2D(1.0f, 0.0f));

  Box2D box1 = { Point2D(-1.0f, -1.0f), Point2D(1.0f, 1.0f) };

  EXPECT_EQ(Ray::checkIntersection(r1, box1), true);
}
<commit_msg>reformat code<commit_after>#include "gtest/gtest.h"
#include "ray.hpp"

TEST(ray_test, test_construction)
{
  // Default constructor.
  Ray r1;
  EXPECT_FLOAT_EQ(r1.origin().x(), 0.0f);
  EXPECT_FLOAT_EQ(r1.origin().y(), 0.0f);
  EXPECT_FLOAT_EQ(r1.direction().x(), 0.0f);
  EXPECT_FLOAT_EQ(r1.direction().y(), 0.0f);

  // Constructor with parameters.
  Ray r2(Point2D(1.0f, 1.0f),
         Point2D(0.0f, 1.0f));

  EXPECT_FLOAT_EQ(r2.origin().x(), 1.0f);
  EXPECT_FLOAT_EQ(r2.origin().y(), 1.0f);
  EXPECT_FLOAT_EQ(r2.direction().x(), 0.0f);
  EXPECT_FLOAT_EQ(r2.direction().y(), 1.0f);

  // Copy constructor.
  Ray r3 = r2;

  EXPECT_EQ(r3 == r2, true);
}

TEST(ray_test, test_assignment)
{
  Ray r1;

  r1 = Ray(Point2D(1.0f, 1.0f),
           Point2D(0.0f, 1.0f));

  EXPECT_FLOAT_EQ(r1.origin().x(), 1.0f);
  EXPECT_FLOAT_EQ(r1.origin().y(), 1.0f);
  EXPECT_FLOAT_EQ(r1.direction().x(), 0.0f);
  EXPECT_FLOAT_EQ(r1.direction().y(), 1.0f);
}

TEST(ray_test, test_equality)
{
  Ray r1(Point2D(1.0f, 1.0f),
         Point2D(0.0f, 1.0f));

  Ray r2(Point2D(1.0f, 1.0f),
         Point2D(0.0f, 1.0f));

  Ray r3(Point2D(1.0f, 1.0f),
         Point2D(1.0f, 1.0f));

  EXPECT_EQ(r1, r2);
  EXPECT_NE(r1, r3);
}

TEST(ray_test, test_intersection_outside)
{
  // Send a ray to the right.
  Ray r1(Point2D(0.0f, 0.0f),
         Point2D(1.0f, 0.0f));

  Box2D box1 = { Point2D(1.0f, -1.0f),
                 Point2D(4.0f, 1.0f) };

  EXPECT_EQ(Ray::checkIntersection(r1, box1), true);

  // Send a ray to the left.
  Ray r2(Point2D(0.0f, 0.0f),
         Point2D(-1.0f, 0.0f));

  Box2D box2 = { Point2D(-1.0f, -1.0f),
                 Point2D(-4.0f, 1.0f) };

  EXPECT_EQ(Ray::checkIntersection(r2, box2), true);

  // Send a ray to the upwards.
  Ray r3(Point2D(0.0f, 0.0f),
         Point2D(0.0f, 1.0f));

  Box2D box3 = { Point2D(-1.0f, 1.0f),
                 Point2D(1.0f, 4.0f) };

  EXPECT_EQ(Ray::checkIntersection(r3, box3), true);

  // Send a ray to the bottom.
  Ray r4(Point2D(0.0f, 0.0f),
         Point2D(0.0f, -1.0f));

  Box2D box4 = { Point2D(-1.0f, -1.0f),
                 Point2D(1.0f, -4.0f) };

  EXPECT_EQ(Ray::checkIntersection(r4, box4), true);
}

TEST(ray_test, test_radian_to_degree)
{
  EXPECT_FLOAT_EQ(Ray::convertRadianToDegrees(Constants::PI), 180);
  EXPECT_FLOAT_EQ(Ray::convertRadianToDegrees(0.5 * Constants::PI), 90);
}

TEST(ray_test, test_intersection_inside)
{
  // Ray origin is inside a box.
  Ray r1(Point2D(0.0f, 0.0f),
         Point2D(1.0f, 0.0f));

  Box2D box1 = { Point2D(-1.0f, -1.0f),
                 Point2D(1.0f, 1.0f) };

  EXPECT_EQ(Ray::checkIntersection(r1, box1), true);
}
<|endoftext|>