<commit_before>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)

#include "gmock/gmock-generated-nice-strict.h"

#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"

// This must not be defined inside the ::testing namespace, or it will
// clash with ::testing::Mock.
class Mock {
 public:
  Mock() {}

  MOCK_METHOD0(DoThis, void());

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mock);
};

namespace testing {
namespace gmock_nice_strict_test {

using testing::GMOCK_FLAG(verbose);
using testing::HasSubstr;
using testing::NaggyMock;
using testing::NiceMock;
using testing::StrictMock;

#if GTEST_HAS_STREAM_REDIRECTION
using testing::internal::CaptureStdout;
using testing::internal::GetCapturedStdout;
#endif

// Defines some mock classes needed by the tests.

class Foo {
 public:
  virtual ~Foo() {}

  virtual void DoThis() = 0;
  virtual int DoThat(bool flag) = 0;
};

class MockFoo : public Foo {
 public:
  MockFoo() {}
  void Delete() { delete this; }

  MOCK_METHOD0(DoThis, void());
  MOCK_METHOD1(DoThat, int(bool flag));

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
};

class MockBar {
 public:
  explicit MockBar(const std::string& s) : str_(s) {}

  MockBar(char a1, char a2, std::string a3, std::string a4, int a5, int a6,
          const std::string& a7, const std::string& a8, bool a9, bool a10) {
    str_ = std::string() + a1 + a2 + a3 + a4 + static_cast<char>(a5) +
        static_cast<char>(a6) + a7 + a8 + (a9 ? 'T' : 'F') + (a10 ? 'T' : 'F');
  }

  virtual ~MockBar() {}

  const std::string& str() const { return str_; }

  MOCK_METHOD0(This, int());
  MOCK_METHOD2(That, std::string(int, bool));

 private:
  std::string str_;

  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockBar);
};

#if GTEST_HAS_STREAM_REDIRECTION

// Tests that a raw mock generates warnings for uninteresting calls.
TEST(RawMockTest, WarningForUninterestingCall) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  MockFoo raw_foo;

  CaptureStdout();
  raw_foo.DoThis();
  raw_foo.DoThat(true);
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a raw mock generates warnings for uninteresting calls
// that delete the mock object.
TEST(RawMockTest, WarningForUninterestingCallAfterDeath) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  MockFoo* const raw_foo = new MockFoo;

  ON_CALL(*raw_foo, DoThis())
      .WillByDefault(Invoke(raw_foo, &MockFoo::Delete));

  CaptureStdout();
  raw_foo->DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a raw mock generates informational logs for
// uninteresting calls.
TEST(RawMockTest, InfoForUninterestingCall) {
  MockFoo raw_foo;

  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "info";
  CaptureStdout();
  raw_foo.DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a nice mock generates no warning for uninteresting calls.
TEST(NiceMockTest, NoWarningForUninterestingCall) {
  NiceMock<MockFoo> nice_foo;

  CaptureStdout();
  nice_foo.DoThis();
  nice_foo.DoThat(true);
  EXPECT_EQ("", GetCapturedStdout());
}

// Tests that a nice mock generates no warning for uninteresting calls
// that delete the mock object.
TEST(NiceMockTest, NoWarningForUninterestingCallAfterDeath) {
  NiceMock<MockFoo>* const nice_foo = new NiceMock<MockFoo>;

  ON_CALL(*nice_foo, DoThis())
      .WillByDefault(Invoke(nice_foo, &MockFoo::Delete));

  CaptureStdout();
  nice_foo->DoThis();
  EXPECT_EQ("", GetCapturedStdout());
}

// Tests that a nice mock generates informational logs for
// uninteresting calls.
TEST(NiceMockTest, InfoForUninterestingCall) {
  NiceMock<MockFoo> nice_foo;

  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "info";
  CaptureStdout();
  nice_foo.DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

#endif  // GTEST_HAS_STREAM_REDIRECTION

// Tests that a nice mock allows expected calls.
TEST(NiceMockTest, AllowsExpectedCall) {
  NiceMock<MockFoo> nice_foo;

  EXPECT_CALL(nice_foo, DoThis());
  nice_foo.DoThis();
}

// Tests that an unexpected call on a nice mock fails.
TEST(NiceMockTest, UnexpectedCallFails) {
  NiceMock<MockFoo> nice_foo;

  EXPECT_CALL(nice_foo, DoThis()).Times(0);
  EXPECT_NONFATAL_FAILURE(nice_foo.DoThis(), "called more times than expected");
}

// Tests that NiceMock works with a mock class that has a non-default
// constructor.
TEST(NiceMockTest, NonDefaultConstructor) {
  NiceMock<MockBar> nice_bar("hi");
  EXPECT_EQ("hi", nice_bar.str());

  nice_bar.This();
  nice_bar.That(5, true);
}

// Tests that NiceMock works with a mock class that has a 10-ary
// non-default constructor.
TEST(NiceMockTest, NonDefaultConstructor10) {
  NiceMock<MockBar> nice_bar('a', 'b', "c", "d", 'e', 'f',
                             "g", "h", true, false);
  EXPECT_EQ("abcdefghTF", nice_bar.str());

  nice_bar.This();
  nice_bar.That(5, true);
}

#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
// Tests that NiceMock<Mock> compiles where Mock is a user-defined
// class (as opposed to ::testing::Mock).  We had to work around an
// MSVC 8.0 bug that caused the symbol Mock used in the definition of
// NiceMock to be looked up in the wrong context, and this test
// ensures that our fix works.
//
// We have to skip this test on Symbian and Windows Mobile, as it
// causes the program to crash there, for reasons unclear to us yet.
TEST(NiceMockTest, AcceptsClassNamedMock) {
  NiceMock< ::Mock> nice;
  EXPECT_CALL(nice, DoThis());
  nice.DoThis();
}
#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE

#if GTEST_HAS_STREAM_REDIRECTION

// Tests that a naggy mock generates warnings for uninteresting calls.
TEST(NaggyMockTest, WarningForUninterestingCall) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  NaggyMock<MockFoo> naggy_foo;

  CaptureStdout();
  naggy_foo.DoThis();
  naggy_foo.DoThat(true);
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a naggy mock generates a warning for an uninteresting call
// that deletes the mock object.
TEST(NaggyMockTest, WarningForUninterestingCallAfterDeath) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  NaggyMock<MockFoo>* const naggy_foo = new NaggyMock<MockFoo>;

  ON_CALL(*naggy_foo, DoThis())
      .WillByDefault(Invoke(naggy_foo, &MockFoo::Delete));

  CaptureStdout();
  naggy_foo->DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

#endif  // GTEST_HAS_STREAM_REDIRECTION

// Tests that a naggy mock allows expected calls.
TEST(NaggyMockTest, AllowsExpectedCall) {
  NaggyMock<MockFoo> naggy_foo;

  EXPECT_CALL(naggy_foo, DoThis());
  naggy_foo.DoThis();
}

// Tests that an unexpected call on a naggy mock fails.
TEST(NaggyMockTest, UnexpectedCallFails) {
  NaggyMock<MockFoo> naggy_foo;

  EXPECT_CALL(naggy_foo, DoThis()).Times(0);
  EXPECT_NONFATAL_FAILURE(naggy_foo.DoThis(),
                          "called more times than expected");
}

// Tests that NaggyMock works with a mock class that has a non-default
// constructor.
TEST(NaggyMockTest, NonDefaultConstructor) {
  NaggyMock<MockBar> naggy_bar("hi");
  EXPECT_EQ("hi", naggy_bar.str());

  naggy_bar.This();
  naggy_bar.That(5, true);
}

// Tests that NaggyMock works with a mock class that has a 10-ary
// non-default constructor.
TEST(NaggyMockTest, NonDefaultConstructor10) {
  NaggyMock<MockBar> naggy_bar('0', '1', "2", "3", '4', '5',
                               "6", "7", true, false);
  EXPECT_EQ("01234567TF", naggy_bar.str());

  naggy_bar.This();
  naggy_bar.That(5, true);
}

#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
// Tests that NaggyMock<Mock> compiles where Mock is a user-defined
// class (as opposed to ::testing::Mock).  We had to work around an
// MSVC 8.0 bug that caused the symbol Mock used in the definition of
// NaggyMock to be looked up in the wrong context, and this test
// ensures that our fix works.
//
// We have to skip this test on Symbian and Windows Mobile, as it
// causes the program to crash there, for reasons unclear to us yet.
TEST(NaggyMockTest, AcceptsClassNamedMock) {
  NaggyMock< ::Mock> naggy;
  EXPECT_CALL(naggy, DoThis());
  naggy.DoThis();
}
#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE

// Tests that a strict mock allows expected calls.
TEST(StrictMockTest, AllowsExpectedCall) {
  StrictMock<MockFoo> strict_foo;

  EXPECT_CALL(strict_foo, DoThis());
  strict_foo.DoThis();
}

// Tests that an unexpected call on a strict mock fails.
TEST(StrictMockTest, UnexpectedCallFails) {
  StrictMock<MockFoo> strict_foo;

  EXPECT_CALL(strict_foo, DoThis()).Times(0);
  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
                          "called more times than expected");
}

// Tests that an uninteresting call on a strict mock fails.
TEST(StrictMockTest, UninterestingCallFails) {
  StrictMock<MockFoo> strict_foo;

  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
                          "Uninteresting mock function call");
}

// Tests that an uninteresting call on a strict mock fails, even if
// the call deletes the mock object.
TEST(StrictMockTest, UninterestingCallFailsAfterDeath) {
  StrictMock<MockFoo>* const strict_foo = new StrictMock<MockFoo>;

  ON_CALL(*strict_foo, DoThis())
      .WillByDefault(Invoke(strict_foo, &MockFoo::Delete));

  EXPECT_NONFATAL_FAILURE(strict_foo->DoThis(),
                          "Uninteresting mock function call");
}

// Tests that StrictMock works with a mock class that has a
// non-default constructor.
TEST(StrictMockTest, NonDefaultConstructor) {
  StrictMock<MockBar> strict_bar("hi");
  EXPECT_EQ("hi", strict_bar.str());

  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
                          "Uninteresting mock function call");
}

// Tests that StrictMock works with a mock class that has a 10-ary
// non-default constructor.
TEST(StrictMockTest, NonDefaultConstructor10) {
  StrictMock<MockBar> strict_bar('a', 'b', "c", "d", 'e', 'f',
                                 "g", "h", true, false);
  EXPECT_EQ("abcdefghTF", strict_bar.str());

  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
                          "Uninteresting mock function call");
}

#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
// Tests that StrictMock<Mock> compiles where Mock is a user-defined
// class (as opposed to ::testing::Mock).  We had to work around an
// MSVC 8.0 bug that caused the symbol Mock used in the definition of
// StrictMock to be looked up in the wrong context, and this test
// ensures that our fix works.
//
// We have to skip this test on Symbian and Windows Mobile, as it
// causes the program to crash there, for reasons unclear to us yet.
TEST(StrictMockTest, AcceptsClassNamedMock) {
  StrictMock< ::Mock> strict;
  EXPECT_CALL(strict, DoThis());
  strict.DoThis();
}
#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE

}  // namespace gmock_nice_strict_test
}  // namespace testing
<commit_msg>adds test for NiceMock with unknown return value<commit_after>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)

#include "gmock/gmock-generated-nice-strict.h"

#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "gtest/gtest-spi.h"

// This must not be defined inside the ::testing namespace, or it will
// clash with ::testing::Mock.
class Mock {
 public:
  Mock() {}

  MOCK_METHOD0(DoThis, void());

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mock);
};

namespace testing {
namespace gmock_nice_strict_test {

using testing::GMOCK_FLAG(verbose);
using testing::HasSubstr;
using testing::NaggyMock;
using testing::NiceMock;
using testing::StrictMock;

#if GTEST_HAS_STREAM_REDIRECTION
using testing::internal::CaptureStdout;
using testing::internal::GetCapturedStdout;
#endif

// Defines some mock classes needed by the tests.

class Foo {
 public:
  virtual ~Foo() {}

  virtual void DoThis() = 0;
  virtual int DoThat(bool flag) = 0;
};

class MockFoo : public Foo {
 public:
  MockFoo() {}
  void Delete() { delete this; }

  MOCK_METHOD0(DoThis, void());
  MOCK_METHOD1(DoThat, int(bool flag));
  MOCK_METHOD0(ReturnSomething, Mock());

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
};

class MockBar {
 public:
  explicit MockBar(const std::string& s) : str_(s) {}

  MockBar(char a1, char a2, std::string a3, std::string a4, int a5, int a6,
          const std::string& a7, const std::string& a8, bool a9, bool a10) {
    str_ = std::string() + a1 + a2 + a3 + a4 + static_cast<char>(a5) +
        static_cast<char>(a6) + a7 + a8 + (a9 ? 'T' : 'F') + (a10 ? 'T' : 'F');
  }

  virtual ~MockBar() {}

  const std::string& str() const { return str_; }

  MOCK_METHOD0(This, int());
  MOCK_METHOD2(That, std::string(int, bool));

 private:
  std::string str_;

  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockBar);
};

#if GTEST_HAS_STREAM_REDIRECTION

// Tests that a raw mock generates warnings for uninteresting calls.
TEST(RawMockTest, WarningForUninterestingCall) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  MockFoo raw_foo;

  CaptureStdout();
  raw_foo.DoThis();
  raw_foo.DoThat(true);
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a raw mock generates warnings for uninteresting calls
// that delete the mock object.
TEST(RawMockTest, WarningForUninterestingCallAfterDeath) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  MockFoo* const raw_foo = new MockFoo;

  ON_CALL(*raw_foo, DoThis())
      .WillByDefault(Invoke(raw_foo, &MockFoo::Delete));

  CaptureStdout();
  raw_foo->DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a raw mock generates informational logs for
// uninteresting calls.
TEST(RawMockTest, InfoForUninterestingCall) {
  MockFoo raw_foo;

  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "info";
  CaptureStdout();
  raw_foo.DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a nice mock generates no warning for uninteresting calls.
TEST(NiceMockTest, NoWarningForUninterestingCall) {
  NiceMock<MockFoo> nice_foo;

  CaptureStdout();
  nice_foo.DoThis();
  nice_foo.DoThat(true);
  EXPECT_EQ("", GetCapturedStdout());
}

// Tests that a nice mock generates no warning for uninteresting calls
// that delete the mock object.
TEST(NiceMockTest, NoWarningForUninterestingCallAfterDeath) {
  NiceMock<MockFoo>* const nice_foo = new NiceMock<MockFoo>;

  ON_CALL(*nice_foo, DoThis())
      .WillByDefault(Invoke(nice_foo, &MockFoo::Delete));

  CaptureStdout();
  nice_foo->DoThis();
  EXPECT_EQ("", GetCapturedStdout());
}

// Tests that a nice mock generates informational logs for
// uninteresting calls.
TEST(NiceMockTest, InfoForUninterestingCall) {
  NiceMock<MockFoo> nice_foo;

  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "info";
  CaptureStdout();
  nice_foo.DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

#endif  // GTEST_HAS_STREAM_REDIRECTION

// Tests that a nice mock allows expected calls.
TEST(NiceMockTest, AllowsExpectedCall) {
  NiceMock<MockFoo> nice_foo;

  EXPECT_CALL(nice_foo, DoThis());
  nice_foo.DoThis();
}

// Tests that an unexpected call on a nice mock which returns a non-built in
// default value throws an exception and the exception contains the name of
// the method.
TEST(NiceMockTest, ThrowsExceptionForUnknownReturnTypes) {
	NiceMock<MockFoo> nice_foo;
	try	{
		nice_foo.ReturnSomething();
		FAIL();
	} catch (const std::runtime_error& ex) {
		const std::string exception_msg(ex.what());
		EXPECT_NE(exception_msg.find("ReturnSomething"), std::string::npos);
	}
}

// Tests that an unexpected call on a nice mock fails.
TEST(NiceMockTest, UnexpectedCallFails) {
  NiceMock<MockFoo> nice_foo;

  EXPECT_CALL(nice_foo, DoThis()).Times(0);
  EXPECT_NONFATAL_FAILURE(nice_foo.DoThis(), "called more times than expected");
}

// Tests that NiceMock works with a mock class that has a non-default
// constructor.
TEST(NiceMockTest, NonDefaultConstructor) {
  NiceMock<MockBar> nice_bar("hi");
  EXPECT_EQ("hi", nice_bar.str());

  nice_bar.This();
  nice_bar.That(5, true);
}

// Tests that NiceMock works with a mock class that has a 10-ary
// non-default constructor.
TEST(NiceMockTest, NonDefaultConstructor10) {
  NiceMock<MockBar> nice_bar('a', 'b', "c", "d", 'e', 'f',
                             "g", "h", true, false);
  EXPECT_EQ("abcdefghTF", nice_bar.str());

  nice_bar.This();
  nice_bar.That(5, true);
}

#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
// Tests that NiceMock<Mock> compiles where Mock is a user-defined
// class (as opposed to ::testing::Mock).  We had to work around an
// MSVC 8.0 bug that caused the symbol Mock used in the definition of
// NiceMock to be looked up in the wrong context, and this test
// ensures that our fix works.
//
// We have to skip this test on Symbian and Windows Mobile, as it
// causes the program to crash there, for reasons unclear to us yet.
TEST(NiceMockTest, AcceptsClassNamedMock) {
  NiceMock< ::Mock> nice;
  EXPECT_CALL(nice, DoThis());
  nice.DoThis();
}
#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE

#if GTEST_HAS_STREAM_REDIRECTION

// Tests that a naggy mock generates warnings for uninteresting calls.
TEST(NaggyMockTest, WarningForUninterestingCall) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  NaggyMock<MockFoo> naggy_foo;

  CaptureStdout();
  naggy_foo.DoThis();
  naggy_foo.DoThat(true);
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

// Tests that a naggy mock generates a warning for an uninteresting call
// that deletes the mock object.
TEST(NaggyMockTest, WarningForUninterestingCallAfterDeath) {
  const std::string saved_flag = GMOCK_FLAG(verbose);
  GMOCK_FLAG(verbose) = "warning";

  NaggyMock<MockFoo>* const naggy_foo = new NaggyMock<MockFoo>;

  ON_CALL(*naggy_foo, DoThis())
      .WillByDefault(Invoke(naggy_foo, &MockFoo::Delete));

  CaptureStdout();
  naggy_foo->DoThis();
  EXPECT_THAT(GetCapturedStdout(),
              HasSubstr("Uninteresting mock function call"));

  GMOCK_FLAG(verbose) = saved_flag;
}

#endif  // GTEST_HAS_STREAM_REDIRECTION

// Tests that a naggy mock allows expected calls.
TEST(NaggyMockTest, AllowsExpectedCall) {
  NaggyMock<MockFoo> naggy_foo;

  EXPECT_CALL(naggy_foo, DoThis());
  naggy_foo.DoThis();
}

// Tests that an unexpected call on a naggy mock fails.
TEST(NaggyMockTest, UnexpectedCallFails) {
  NaggyMock<MockFoo> naggy_foo;

  EXPECT_CALL(naggy_foo, DoThis()).Times(0);
  EXPECT_NONFATAL_FAILURE(naggy_foo.DoThis(),
                          "called more times than expected");
}

// Tests that NaggyMock works with a mock class that has a non-default
// constructor.
TEST(NaggyMockTest, NonDefaultConstructor) {
  NaggyMock<MockBar> naggy_bar("hi");
  EXPECT_EQ("hi", naggy_bar.str());

  naggy_bar.This();
  naggy_bar.That(5, true);
}

// Tests that NaggyMock works with a mock class that has a 10-ary
// non-default constructor.
TEST(NaggyMockTest, NonDefaultConstructor10) {
  NaggyMock<MockBar> naggy_bar('0', '1', "2", "3", '4', '5',
                               "6", "7", true, false);
  EXPECT_EQ("01234567TF", naggy_bar.str());

  naggy_bar.This();
  naggy_bar.That(5, true);
}

#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
// Tests that NaggyMock<Mock> compiles where Mock is a user-defined
// class (as opposed to ::testing::Mock).  We had to work around an
// MSVC 8.0 bug that caused the symbol Mock used in the definition of
// NaggyMock to be looked up in the wrong context, and this test
// ensures that our fix works.
//
// We have to skip this test on Symbian and Windows Mobile, as it
// causes the program to crash there, for reasons unclear to us yet.
TEST(NaggyMockTest, AcceptsClassNamedMock) {
  NaggyMock< ::Mock> naggy;
  EXPECT_CALL(naggy, DoThis());
  naggy.DoThis();
}
#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE

// Tests that a strict mock allows expected calls.
TEST(StrictMockTest, AllowsExpectedCall) {
  StrictMock<MockFoo> strict_foo;

  EXPECT_CALL(strict_foo, DoThis());
  strict_foo.DoThis();
}

// Tests that an unexpected call on a strict mock fails.
TEST(StrictMockTest, UnexpectedCallFails) {
  StrictMock<MockFoo> strict_foo;

  EXPECT_CALL(strict_foo, DoThis()).Times(0);
  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
                          "called more times than expected");
}

// Tests that an uninteresting call on a strict mock fails.
TEST(StrictMockTest, UninterestingCallFails) {
  StrictMock<MockFoo> strict_foo;

  EXPECT_NONFATAL_FAILURE(strict_foo.DoThis(),
                          "Uninteresting mock function call");
}

// Tests that an uninteresting call on a strict mock fails, even if
// the call deletes the mock object.
TEST(StrictMockTest, UninterestingCallFailsAfterDeath) {
  StrictMock<MockFoo>* const strict_foo = new StrictMock<MockFoo>;

  ON_CALL(*strict_foo, DoThis())
      .WillByDefault(Invoke(strict_foo, &MockFoo::Delete));

  EXPECT_NONFATAL_FAILURE(strict_foo->DoThis(),
                          "Uninteresting mock function call");
}

// Tests that StrictMock works with a mock class that has a
// non-default constructor.
TEST(StrictMockTest, NonDefaultConstructor) {
  StrictMock<MockBar> strict_bar("hi");
  EXPECT_EQ("hi", strict_bar.str());

  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
                          "Uninteresting mock function call");
}

// Tests that StrictMock works with a mock class that has a 10-ary
// non-default constructor.
TEST(StrictMockTest, NonDefaultConstructor10) {
  StrictMock<MockBar> strict_bar('a', 'b', "c", "d", 'e', 'f',
                                 "g", "h", true, false);
  EXPECT_EQ("abcdefghTF", strict_bar.str());

  EXPECT_NONFATAL_FAILURE(strict_bar.That(5, true),
                          "Uninteresting mock function call");
}

#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE
// Tests that StrictMock<Mock> compiles where Mock is a user-defined
// class (as opposed to ::testing::Mock).  We had to work around an
// MSVC 8.0 bug that caused the symbol Mock used in the definition of
// StrictMock to be looked up in the wrong context, and this test
// ensures that our fix works.
//
// We have to skip this test on Symbian and Windows Mobile, as it
// causes the program to crash there, for reasons unclear to us yet.
TEST(StrictMockTest, AcceptsClassNamedMock) {
  StrictMock< ::Mock> strict;
  EXPECT_CALL(strict, DoThis());
  strict.DoThis();
}
#endif  // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE

}  // namespace gmock_nice_strict_test
}  // namespace testing
<|endoftext|>


<commit_before>// csabase_ppobserver.cpp                                             -*-C++-*-
// -----------------------------------------------------------------------------
// Copyright 2012 Dietmar Kuehl http://www.dietmar-kuehl.de
// Distributed under the Boost Software License, Version 1.0. (See file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
// -----------------------------------------------------------------------------

#include <csabase_ppobserver.h>
#include <csabase_debug.h>
#include <csabase_location.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/SourceManager.h>
#include <llvm/Support/Regex.h>
#include <llvm/Support/raw_ostream.h>
#ident "$Id$"

// -----------------------------------------------------------------------------

cool::csabase::PPObserver::PPObserver(
    clang::SourceManager const* source_manager,
    cool::csabase::Config* config)
: source_manager_(source_manager)
, connected_(true)
, config_(config)
{
}

// -----------------------------------------------------------------------------

cool::csabase::PPObserver::~PPObserver()
{
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::detach()
{
    connected_ = false;
}

// -----------------------------------------------------------------------------

namespace
{
    struct CommentHandler
        : clang::CommentHandler
    {
        CommentHandler(cool::csabase::PPObserver* observer): observer_(observer) {}
        bool HandleComment(clang::Preprocessor&, clang::SourceRange range)
        {
            observer_->HandleComment(range);
            return false;
        }
        cool::csabase::PPObserver* observer_;
    };
}

clang::CommentHandler*
cool::csabase::PPObserver::get_comment_handler()
{
    return new CommentHandler(this);
}

// -----------------------------------------------------------------------------

std::string
cool::csabase::PPObserver::get_file(clang::SourceLocation location) const
{
    return source_manager_->getPresumedLoc(location).getFilename();
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::do_include_file(clang::SourceLocation location, bool is_angled, std::string const& file)
{
    std::string msg("do_include_file '" + file + "' angled=" + (is_angled? "true": "false"));
    cool::csabase::Debug d(msg.c_str());
    onInclude(location, is_angled, file);
}

void
cool::csabase::PPObserver::do_open_file(clang::SourceLocation location, std::string const& from, std::string const& file)
{
    std::string msg("do_open_file '" + file + "'");
    cool::csabase::Debug d(msg.c_str());
    onOpenFile(location, from, file);
}

void
cool::csabase::PPObserver::do_close_file(clang::SourceLocation location, std::string const& from, std::string const& file)
{
    std::string msg("do_close_file '" + file + "'");
    cool::csabase::Debug d(msg.c_str());
    onCloseFile(location, from, file);
}

void
cool::csabase::PPObserver::do_skip_file(std::string const& from, std::string const& file)
{
    std::string msg("do_skip_file(" + from + ", " + file + ")");
    cool::csabase::Debug d(msg.c_str());
    onSkipFile(from, file);
}

void
cool::csabase::PPObserver::do_file_not_found(std::string const& file)
{
    std::string msg("do_file_not_found(" + file + ")");
    cool::csabase::Debug d(msg.c_str());
    onFileNotFound(file);
}

void
cool::csabase::PPObserver::do_other_file(std::string const& file, clang::PPCallbacks::FileChangeReason reason)
{
    std::string msg("do_other_file '" + file + "'");
    cool::csabase::Debug d(msg.c_str());
    onOtherFile(file, reason);
}

void
cool::csabase::PPObserver::do_ident(clang::SourceLocation location, std::string const& ident)
{
    cool::csabase::Debug d("do_ident");
    onIdent(location, ident);
}

void
cool::csabase::PPObserver::do_pragma(clang::SourceLocation location, std::string const& value)
{
    cool::csabase::Debug d("do_pragma");
    onPragma(location, value);
}

void
cool::csabase::PPObserver::do_macro_expands(clang::Token const&          token,
                                            const clang::MacroDirective *macro)
{
    cool::csabase::Debug d("do_macro_expands");
    onMacroExpands(token, macro);
}

void
cool::csabase::PPObserver::do_macro_defined(clang::Token const&          token,
                                            const clang::MacroDirective *macro)
{
    cool::csabase::Debug d("do_macro_defined");
    onMacroDefined(token, macro);
}

void
cool::csabase::PPObserver::do_macro_undefined(
                                            clang::Token const&          token,
                                            const clang::MacroDirective *macro)
{
    cool::csabase::Debug d("do_macro_undefined");
    onMacroUndefined(token, macro);
}

void
cool::csabase::PPObserver::do_if(clang::SourceLocation where,
                                 clang::SourceRange range)
{
    cool::csabase::Debug d("do_if");
    onIf(where, range);
}

void
cool::csabase::PPObserver::do_elif(clang::SourceLocation where,
                                   clang::SourceRange range)
{
    cool::csabase::Debug d("do_elif");
    onElif(where, range);
}

void
cool::csabase::PPObserver::do_ifdef(clang::SourceLocation where,
                                    clang::Token const& token)
{
    cool::csabase::Debug d("do_ifdef");
    onIfdef(where, token);
}

void
cool::csabase::PPObserver::do_ifndef(clang::SourceLocation where,
                                     clang::Token const& token)
{
    cool::csabase::Debug d("do_ifndef");
    onIfndef(where, token);
}

void
cool::csabase::PPObserver::do_else(clang::SourceLocation where,
                                   clang::SourceLocation what)
{
    cool::csabase::Debug d("do_else");
    onElse(where, what);
}

void
cool::csabase::PPObserver::do_endif(clang::SourceLocation where,
                                    clang::SourceLocation what)
{
    cool::csabase::Debug d("do_endif");
    onEndif(where, what);
}

void
cool::csabase::PPObserver::do_comment(clang::SourceRange range)
{
    cool::csabase::Debug d("do_comment");
    onComment(range);
}

void
cool::csabase::PPObserver::do_context()
{
    cool::csabase::Debug d("do_context");
    onContext();
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::FileChanged(
                                 clang::SourceLocation                location,
                                 clang::PPCallbacks::FileChangeReason reason,
                                 clang::SrcMgr::CharacteristicKind    kind,
                                 clang::FileID                        prev)
{
    if (connected_)
    {
        switch (reason)
        {
        case clang::PPCallbacks::EnterFile:
            {
                std::string file(get_file(location));
                do_open_file(location, files_.empty()? std::string(): files_.top(), file);
                files_.push(file);
            }
            break;
        case clang::PPCallbacks::ExitFile:
            {
                std::string file(files_.top());
                files_.pop();
                do_close_file(location, files_.empty()? std::string(): files_.top(), file);
            }
            break;
        default:
            do_other_file(get_file(location), reason);
            break;
        }
    }
}

void
cool::csabase::PPObserver::EndOfMainFile()
{
    if (connected_)
    {
        std::string file(files_.top());
        files_.pop();
        do_close_file(clang::SourceLocation(), files_.empty()? std::string(): files_.top(), file);
    }
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::FileSkipped(clang::FileEntry const& file, clang::Token const&,
                             clang::SrcMgr::CharacteristicKind kind)
{
    do_skip_file(files_.empty()? std::string(): files_.top(), file.getName());
}

// -----------------------------------------------------------------------------

bool
cool::csabase::PPObserver::FileNotFound(llvm::StringRef name,
                                        llvm::SmallVectorImpl<char>& path)
{
    do_file_not_found(name);
    return false;
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::Ident(clang::SourceLocation location, std::string const& ident)
{
    do_ident(location, ident);
}

// -----------------------------------------------------------------------------

static llvm::Regex pragma_bdeverify(
    "^[[:blank:]]*" "#" "[[:blank:]]*" "pragma" "[[:blank:]]+"
    "bde_?verify" "[[:blank:]]+" "("                        // 1
        "(" "push"                                    ")|"  // 2
        "(" "pop"                                     ")|"  // 3
        "(" "[-]" "[[:blank:]]*" "([[:alnum:]]+|[*])" ")|"  // 4 5
        "(" "[+]" "[[:blank:]]*" "([[:alnum:]]+|[*])" ")|"  // 6 7
        "(" "set" "[[:blank:]]*" "([_[:alnum:]]+)"          // 8 9
                  "[[:blank:]]*" "([^[:blank:]]+)"    ")|"  // 10
        "$"
    ")",
    llvm::Regex::NoFlags);

void
cool::csabase::PPObserver::PragmaDirective(clang::SourceLocation location, clang::PragmaIntroducerKind introducer)
{
    const clang::SourceManager& m = *source_manager_;
    clang::FileID fid = m.getFileID(location);
    unsigned line = m.getPresumedLineNumber(location);
    llvm::StringRef directive =
        m.getBufferData(fid).slice(
            m.getFileOffset(m.translateLineCol(fid, line, 1)),
            m.getFileOffset(m.translateLineCol(fid, line, 0)));
    llvm::SmallVector<llvm::StringRef, 8> matches;
    if (pragma_bdeverify.match(directive, &matches)) {
        if (!matches[2].empty()) {
            config_->push_suppress(location);
        } else if (!matches[3].empty()) {
            config_->pop_suppress(location);
        } else if (!matches[5].empty()) {
            config_->suppress(matches[5], location, true);
        } else if (!matches[7].empty()) {
            config_->suppress(matches[7], location, false);
        } else if (!matches[8].empty()) {
            config_->set_bv_value(location, matches[9], matches[10]);
        }
    }
}

void
cool::csabase::PPObserver::PragmaComment(clang::SourceLocation location, clang::IdentifierInfo const*, std::string const& value)
{
    do_pragma(location, value);
}

void
cool::csabase::PPObserver::PragmaDetectMismatch(clang::SourceLocation  loc,
                                                const std::string     &name,
                                                const std::string     &value)
{
}

void
cool::csabase::PPObserver::PragmaDebug(clang::SourceLocation loc,
                                       llvm::StringRef       debugtype)
{
}

void
cool::csabase::PPObserver::PragmaDiagnosticPush(
                                               clang::SourceLocation loc,
                                               llvm::StringRef       nmspc)
{
}

void
cool::csabase::PPObserver::PragmaDiagnosticPop(clang::SourceLocation loc,
                                               llvm::StringRef       nmspc)
{
}

void
cool::csabase::PPObserver::PragmaDiagnostic(clang::SourceLocation loc,
                                            llvm::StringRef       nmspc,
                                            clang::diag::Mapping  mapping,
                                            llvm::StringRef       str)
{
}

void
cool::csabase::PPObserver::PragmaOpenCLExtension(
                                         clang::SourceLocation        nameloc,
                                         const clang::IdentifierInfo *name,
                                         clang::SourceLocation        stateloc,
                                         unsigned                     state)
{
}

void
cool::csabase::PPObserver::PragmaWarning(clang::SourceLocation loc,
                                         llvm::StringRef       warningspec,
                                         llvm::ArrayRef<int>   ids)
{
}

void
cool::csabase::PPObserver::PragmaWarningPush(clang::SourceLocation loc,
                                             int                   level)
{
}

void
cool::csabase::PPObserver::PragmaWarningPop(clang::SourceLocation loc)
{
}

void
cool::csabase::PPObserver::PragmaMessage(clang::SourceLocation location,
                                         llvm::StringRef       nmspc,
                                         PragmaMessageKind     kind,
                                         llvm::StringRef       value)
{
    do_pragma(location, value);
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::MacroExpands(clang::Token const&          token,
                                        const clang::MacroDirective *macro,
                                        clang::SourceRange           range,
                                        const clang::MacroArgs      *args)
{
    do_macro_expands(token, macro);
}

void
cool::csabase::PPObserver::MacroDefined(clang::Token const&          token,
                                        const clang::MacroDirective *macro)
{
    do_macro_defined(token, macro);
}

void
cool::csabase::PPObserver::MacroUndefined(clang::Token const&          token,
                                          const clang::MacroDirective *macro)
{
    do_macro_undefined(token, macro);
}

void
cool::csabase::PPObserver::Defined(const clang::Token&          token,
                                   const clang::MacroDirective *macro,
                                   clang::SourceRange           range)
{
}

void
cool::csabase::PPObserver::SourceRangeSkipped(clang::SourceRange range)
{
}

// ----------------------------------------------------------------------------

void
cool::csabase::PPObserver::If(clang::SourceLocation loc,
                              clang::SourceRange    range,
                              bool                  conditionvalue)
{
    do_if(loc, range);
}

void
cool::csabase::PPObserver::Elif(clang::SourceLocation loc,
                                clang::SourceRange    range,
                                bool                  conditionvalue,
                                clang::SourceLocation ifloc)
{
    do_elif(loc, range);
}

void
cool::csabase::PPObserver::Ifdef(clang::SourceLocation        loc,
                                 clang::Token const&          token,
                                 const clang::MacroDirective *md)
{
    do_ifdef(loc, token);
}

void
cool::csabase::PPObserver::Ifndef(clang::SourceLocation        loc,
                                  clang::Token const&          token,
                                  const clang::MacroDirective *md)
{
    do_ifndef(loc, token);
}

void
cool::csabase::PPObserver::Else(clang::SourceLocation loc,
                                clang::SourceLocation ifloc)
{
    do_else(loc, ifloc);
}

void
cool::csabase::PPObserver::Endif(clang::SourceLocation loc,
                                 clang::SourceLocation ifloc)
{
    do_endif(loc, ifloc);
}

// ----------------------------------------------------------------------------

void
cool::csabase::PPObserver::HandleComment(clang::SourceRange range)
{
    do_comment(range);
}

void
cool::csabase::PPObserver::Context()
{
    do_context();
}

void
cool::csabase::PPObserver::InclusionDirective(
                                         clang::SourceLocation   HashLoc,
                                         const clang::Token&     IncludeTok,
                                         llvm::StringRef         FileName,
                                         bool                    IsAngled,
                                         clang::CharSourceRange  FilenameRange,
                                         const clang::FileEntry *File,
                                         llvm::StringRef         SearchPath,
                                         llvm::StringRef         RelativePath,
                                         const clang::Module    *Imported)
{
    do_include_file(HashLoc, IsAngled, FileName);
    //-dk:TODO make constructive use of this...
}

void
cool::csabase::PPObserver::moduleImport(clang::SourceLocation  ImportLoc,
                                        clang::ModuleIdPath    Path,
                                        const clang::Module   *Imported)
{
}
<commit_msg>Munch whole line for '#pragma bdeverify set var values'.<commit_after>// csabase_ppobserver.cpp                                             -*-C++-*-
// -----------------------------------------------------------------------------
// Copyright 2012 Dietmar Kuehl http://www.dietmar-kuehl.de
// Distributed under the Boost Software License, Version 1.0. (See file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
// -----------------------------------------------------------------------------

#include <csabase_ppobserver.h>
#include <csabase_debug.h>
#include <csabase_location.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/SourceManager.h>
#include <llvm/Support/Regex.h>
#include <llvm/Support/raw_ostream.h>
#ident "$Id$"

// -----------------------------------------------------------------------------

cool::csabase::PPObserver::PPObserver(
    clang::SourceManager const* source_manager,
    cool::csabase::Config* config)
: source_manager_(source_manager)
, connected_(true)
, config_(config)
{
}

// -----------------------------------------------------------------------------

cool::csabase::PPObserver::~PPObserver()
{
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::detach()
{
    connected_ = false;
}

// -----------------------------------------------------------------------------

namespace
{
    struct CommentHandler
        : clang::CommentHandler
    {
        CommentHandler(cool::csabase::PPObserver* observer): observer_(observer) {}
        bool HandleComment(clang::Preprocessor&, clang::SourceRange range)
        {
            observer_->HandleComment(range);
            return false;
        }
        cool::csabase::PPObserver* observer_;
    };
}

clang::CommentHandler*
cool::csabase::PPObserver::get_comment_handler()
{
    return new CommentHandler(this);
}

// -----------------------------------------------------------------------------

std::string
cool::csabase::PPObserver::get_file(clang::SourceLocation location) const
{
    return source_manager_->getPresumedLoc(location).getFilename();
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::do_include_file(clang::SourceLocation location, bool is_angled, std::string const& file)
{
    std::string msg("do_include_file '" + file + "' angled=" + (is_angled? "true": "false"));
    cool::csabase::Debug d(msg.c_str());
    onInclude(location, is_angled, file);
}

void
cool::csabase::PPObserver::do_open_file(clang::SourceLocation location, std::string const& from, std::string const& file)
{
    std::string msg("do_open_file '" + file + "'");
    cool::csabase::Debug d(msg.c_str());
    onOpenFile(location, from, file);
}

void
cool::csabase::PPObserver::do_close_file(clang::SourceLocation location, std::string const& from, std::string const& file)
{
    std::string msg("do_close_file '" + file + "'");
    cool::csabase::Debug d(msg.c_str());
    onCloseFile(location, from, file);
}

void
cool::csabase::PPObserver::do_skip_file(std::string const& from, std::string const& file)
{
    std::string msg("do_skip_file(" + from + ", " + file + ")");
    cool::csabase::Debug d(msg.c_str());
    onSkipFile(from, file);
}

void
cool::csabase::PPObserver::do_file_not_found(std::string const& file)
{
    std::string msg("do_file_not_found(" + file + ")");
    cool::csabase::Debug d(msg.c_str());
    onFileNotFound(file);
}

void
cool::csabase::PPObserver::do_other_file(std::string const& file, clang::PPCallbacks::FileChangeReason reason)
{
    std::string msg("do_other_file '" + file + "'");
    cool::csabase::Debug d(msg.c_str());
    onOtherFile(file, reason);
}

void
cool::csabase::PPObserver::do_ident(clang::SourceLocation location, std::string const& ident)
{
    cool::csabase::Debug d("do_ident");
    onIdent(location, ident);
}

void
cool::csabase::PPObserver::do_pragma(clang::SourceLocation location, std::string const& value)
{
    cool::csabase::Debug d("do_pragma");
    onPragma(location, value);
}

void
cool::csabase::PPObserver::do_macro_expands(clang::Token const&          token,
                                            const clang::MacroDirective *macro)
{
    cool::csabase::Debug d("do_macro_expands");
    onMacroExpands(token, macro);
}

void
cool::csabase::PPObserver::do_macro_defined(clang::Token const&          token,
                                            const clang::MacroDirective *macro)
{
    cool::csabase::Debug d("do_macro_defined");
    onMacroDefined(token, macro);
}

void
cool::csabase::PPObserver::do_macro_undefined(
                                            clang::Token const&          token,
                                            const clang::MacroDirective *macro)
{
    cool::csabase::Debug d("do_macro_undefined");
    onMacroUndefined(token, macro);
}

void
cool::csabase::PPObserver::do_if(clang::SourceLocation where,
                                 clang::SourceRange range)
{
    cool::csabase::Debug d("do_if");
    onIf(where, range);
}

void
cool::csabase::PPObserver::do_elif(clang::SourceLocation where,
                                   clang::SourceRange range)
{
    cool::csabase::Debug d("do_elif");
    onElif(where, range);
}

void
cool::csabase::PPObserver::do_ifdef(clang::SourceLocation where,
                                    clang::Token const& token)
{
    cool::csabase::Debug d("do_ifdef");
    onIfdef(where, token);
}

void
cool::csabase::PPObserver::do_ifndef(clang::SourceLocation where,
                                     clang::Token const& token)
{
    cool::csabase::Debug d("do_ifndef");
    onIfndef(where, token);
}

void
cool::csabase::PPObserver::do_else(clang::SourceLocation where,
                                   clang::SourceLocation what)
{
    cool::csabase::Debug d("do_else");
    onElse(where, what);
}

void
cool::csabase::PPObserver::do_endif(clang::SourceLocation where,
                                    clang::SourceLocation what)
{
    cool::csabase::Debug d("do_endif");
    onEndif(where, what);
}

void
cool::csabase::PPObserver::do_comment(clang::SourceRange range)
{
    cool::csabase::Debug d("do_comment");
    onComment(range);
}

void
cool::csabase::PPObserver::do_context()
{
    cool::csabase::Debug d("do_context");
    onContext();
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::FileChanged(
                                 clang::SourceLocation                location,
                                 clang::PPCallbacks::FileChangeReason reason,
                                 clang::SrcMgr::CharacteristicKind    kind,
                                 clang::FileID                        prev)
{
    if (connected_)
    {
        switch (reason)
        {
        case clang::PPCallbacks::EnterFile:
            {
                std::string file(get_file(location));
                do_open_file(location, files_.empty()? std::string(): files_.top(), file);
                files_.push(file);
            }
            break;
        case clang::PPCallbacks::ExitFile:
            {
                std::string file(files_.top());
                files_.pop();
                do_close_file(location, files_.empty()? std::string(): files_.top(), file);
            }
            break;
        default:
            do_other_file(get_file(location), reason);
            break;
        }
    }
}

void
cool::csabase::PPObserver::EndOfMainFile()
{
    if (connected_)
    {
        std::string file(files_.top());
        files_.pop();
        do_close_file(clang::SourceLocation(), files_.empty()? std::string(): files_.top(), file);
    }
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::FileSkipped(clang::FileEntry const& file, clang::Token const&,
                             clang::SrcMgr::CharacteristicKind kind)
{
    do_skip_file(files_.empty()? std::string(): files_.top(), file.getName());
}

// -----------------------------------------------------------------------------

bool
cool::csabase::PPObserver::FileNotFound(llvm::StringRef name,
                                        llvm::SmallVectorImpl<char>& path)
{
    do_file_not_found(name);
    return false;
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::Ident(clang::SourceLocation location, std::string const& ident)
{
    do_ident(location, ident);
}

// -----------------------------------------------------------------------------

static llvm::Regex pragma_bdeverify(
    "^[[:blank:]]*" "#" "[[:blank:]]*" "pragma" "[[:blank:]]+"
    "bde_?verify" "[[:blank:]]+" "("                        // 1
        "(" "push"                                    ")|"  // 2
        "(" "pop"                                     ")|"  // 3
        "(" "[-]" "[[:blank:]]*" "([[:alnum:]]+|[*])" ")|"  // 4 5
        "(" "[+]" "[[:blank:]]*" "([[:alnum:]]+|[*])" ")|"  // 6 7
        "(" "set" "[[:blank:]]*" "([_[:alnum:]]+)"          // 8 9
                  "[[:blank:]]*" "(.*[^[:blank:]])"   ")|"  // 10
        "$"
    ")",
    llvm::Regex::NoFlags);

void
cool::csabase::PPObserver::PragmaDirective(clang::SourceLocation location, clang::PragmaIntroducerKind introducer)
{
    const clang::SourceManager& m = *source_manager_;
    clang::FileID fid = m.getFileID(location);
    unsigned line = m.getPresumedLineNumber(location);
    llvm::StringRef directive =
        m.getBufferData(fid).slice(
            m.getFileOffset(m.translateLineCol(fid, line, 1)),
            m.getFileOffset(m.translateLineCol(fid, line, 0)));
    llvm::SmallVector<llvm::StringRef, 8> matches;
    if (pragma_bdeverify.match(directive, &matches)) {
        if (!matches[2].empty()) {
            config_->push_suppress(location);
        } else if (!matches[3].empty()) {
            config_->pop_suppress(location);
        } else if (!matches[5].empty()) {
            config_->suppress(matches[5], location, true);
        } else if (!matches[7].empty()) {
            config_->suppress(matches[7], location, false);
        } else if (!matches[8].empty()) {
            config_->set_bv_value(location, matches[9], matches[10]);
        }
    }
}

void
cool::csabase::PPObserver::PragmaComment(clang::SourceLocation location, clang::IdentifierInfo const*, std::string const& value)
{
    do_pragma(location, value);
}

void
cool::csabase::PPObserver::PragmaDetectMismatch(clang::SourceLocation  loc,
                                                const std::string     &name,
                                                const std::string     &value)
{
}

void
cool::csabase::PPObserver::PragmaDebug(clang::SourceLocation loc,
                                       llvm::StringRef       debugtype)
{
}

void
cool::csabase::PPObserver::PragmaDiagnosticPush(
                                               clang::SourceLocation loc,
                                               llvm::StringRef       nmspc)
{
}

void
cool::csabase::PPObserver::PragmaDiagnosticPop(clang::SourceLocation loc,
                                               llvm::StringRef       nmspc)
{
}

void
cool::csabase::PPObserver::PragmaDiagnostic(clang::SourceLocation loc,
                                            llvm::StringRef       nmspc,
                                            clang::diag::Mapping  mapping,
                                            llvm::StringRef       str)
{
}

void
cool::csabase::PPObserver::PragmaOpenCLExtension(
                                         clang::SourceLocation        nameloc,
                                         const clang::IdentifierInfo *name,
                                         clang::SourceLocation        stateloc,
                                         unsigned                     state)
{
}

void
cool::csabase::PPObserver::PragmaWarning(clang::SourceLocation loc,
                                         llvm::StringRef       warningspec,
                                         llvm::ArrayRef<int>   ids)
{
}

void
cool::csabase::PPObserver::PragmaWarningPush(clang::SourceLocation loc,
                                             int                   level)
{
}

void
cool::csabase::PPObserver::PragmaWarningPop(clang::SourceLocation loc)
{
}

void
cool::csabase::PPObserver::PragmaMessage(clang::SourceLocation location,
                                         llvm::StringRef       nmspc,
                                         PragmaMessageKind     kind,
                                         llvm::StringRef       value)
{
    do_pragma(location, value);
}

// -----------------------------------------------------------------------------

void
cool::csabase::PPObserver::MacroExpands(clang::Token const&          token,
                                        const clang::MacroDirective *macro,
                                        clang::SourceRange           range,
                                        const clang::MacroArgs      *args)
{
    do_macro_expands(token, macro);
}

void
cool::csabase::PPObserver::MacroDefined(clang::Token const&          token,
                                        const clang::MacroDirective *macro)
{
    do_macro_defined(token, macro);
}

void
cool::csabase::PPObserver::MacroUndefined(clang::Token const&          token,
                                          const clang::MacroDirective *macro)
{
    do_macro_undefined(token, macro);
}

void
cool::csabase::PPObserver::Defined(const clang::Token&          token,
                                   const clang::MacroDirective *macro,
                                   clang::SourceRange           range)
{
}

void
cool::csabase::PPObserver::SourceRangeSkipped(clang::SourceRange range)
{
}

// ----------------------------------------------------------------------------

void
cool::csabase::PPObserver::If(clang::SourceLocation loc,
                              clang::SourceRange    range,
                              bool                  conditionvalue)
{
    do_if(loc, range);
}

void
cool::csabase::PPObserver::Elif(clang::SourceLocation loc,
                                clang::SourceRange    range,
                                bool                  conditionvalue,
                                clang::SourceLocation ifloc)
{
    do_elif(loc, range);
}

void
cool::csabase::PPObserver::Ifdef(clang::SourceLocation        loc,
                                 clang::Token const&          token,
                                 const clang::MacroDirective *md)
{
    do_ifdef(loc, token);
}

void
cool::csabase::PPObserver::Ifndef(clang::SourceLocation        loc,
                                  clang::Token const&          token,
                                  const clang::MacroDirective *md)
{
    do_ifndef(loc, token);
}

void
cool::csabase::PPObserver::Else(clang::SourceLocation loc,
                                clang::SourceLocation ifloc)
{
    do_else(loc, ifloc);
}

void
cool::csabase::PPObserver::Endif(clang::SourceLocation loc,
                                 clang::SourceLocation ifloc)
{
    do_endif(loc, ifloc);
}

// ----------------------------------------------------------------------------

void
cool::csabase::PPObserver::HandleComment(clang::SourceRange range)
{
    do_comment(range);
}

void
cool::csabase::PPObserver::Context()
{
    do_context();
}

void
cool::csabase::PPObserver::InclusionDirective(
                                         clang::SourceLocation   HashLoc,
                                         const clang::Token&     IncludeTok,
                                         llvm::StringRef         FileName,
                                         bool                    IsAngled,
                                         clang::CharSourceRange  FilenameRange,
                                         const clang::FileEntry *File,
                                         llvm::StringRef         SearchPath,
                                         llvm::StringRef         RelativePath,
                                         const clang::Module    *Imported)
{
    do_include_file(HashLoc, IsAngled, FileName);
    //-dk:TODO make constructive use of this...
}

void
cool::csabase::PPObserver::moduleImport(clang::SourceLocation  ImportLoc,
                                        clang::ModuleIdPath    Path,
                                        const clang::Module   *Imported)
{
}
<|endoftext|>


<commit_before>#include "huffman.hpp"

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <utility>
#include <string>
#include <cstring>
#include <limits>

#include "heap.hpp"
#include "binarystream.hpp"

using namespace algorithm;

void
Huffman
::CompressFile(StreamInType & fin, StreamOutType & fout)
{
    CollectRuns(fin);

    PrintAllRuns();

    fin.clear();            /** Remove eofbit */
    WriteHeader(fin, fout);

    CreateHuffmanTree();
    AssignCodeword(root_, 0, 0);

    PrintHuffmanTree();

    CreateRunList(root_);
    WriteEncode(fin, fout);
}

void
Huffman
::DecompressFile(StreamInType & fin, StreamOutType & fout)
{
    SizeType fout_size = ReadHeader(fin);

    PrintAllRuns();

    CreateHuffmanTree();
    AssignCodeword(root_, 0, 0);

    PrintHuffmanTree();

    WriteDecode(fin, fout, fout_size);
}

void
Huffman
::PrintAllRuns(FILE * f)
{
    fprintf(f, "SYM LENG FREQ\n");  /** Header of data */

    for(auto run : runs_)
        fprintf(f, " %02x %4lu %lu\n", run.symbol, run.run_len, run.freq);
}

void
Huffman
::CollectRuns(StreamInType & fin)
{
    typedef     std::map<MetaSymbolType, unsigned int>  CacheType;
    typedef     CacheType::iterator                     CacheIterType;

    CacheType   cache;              /**< Caching a position of the run in the vector(runs_) */

    fin.clear();                    /** Reset the input position indicator */
    fin.seekg(0, fin.beg);

    while(! fin.eof())
    {
        ByteType    symbol;
        SizeType    run_len = 1;

        BinaryStream::Read<ByteType>(fin, symbol);
        if(fin.eof())
            break;

        //BinaryStream::Read<SizeType>(fin, run_len);

        /** Insert the pair into runs_;
            key:    pair(symbol, run_len)
            value:  appearance frequency of key
        */
        MetaSymbolType  meta_symbol = std::make_pair(symbol, run_len);
        CacheIterType   cache_iter  = cache.find(meta_symbol);  /** Get the position from cache */

        if(cache_iter == cache.end())
        {
            runs_.push_back(RunType(meta_symbol, 1));           /** First appreance; freq is 1 */
            cache.emplace(meta_symbol, runs_.size() - 1);       /** Cache the position */
        }
        else
            ++runs_.at(cache_iter->second);                     /** Add freq */
    }
}

void
Huffman
::CreateHuffmanTree(void)
{
    Heap<RunType>   heap;
    for(auto run : runs_)
        heap.Push(run);

    while(heap.size() > 1)
    {
        RunType * left  = new RunType(heap.Peek());
        heap.Pop();

        RunType * right = new RunType(heap.Peek());
        heap.Pop();

        RunType temp(left, right);
        heap.Push(temp);
    }

    root_ = new RunType(heap.Peek());
    heap.Pop();
}

void
Huffman
::AssignCodeword(RunType * node, const CodewordType & codeword, const SizeType & codeword_len)
{
    if(node->left == nullptr && node->right == nullptr)
    {
        node->codeword      = codeword;
        node->codeword_len  = codeword_len;
    }
    else
    {
        AssignCodeword(node->left,  (codeword << 1) + 0, codeword_len + 1);
        AssignCodeword(node->right, (codeword << 1) + 1, codeword_len + 1);
    }
}

void
Huffman
::CreateRunList(RunType * node)
{
    if(node->left == nullptr && node->right == nullptr)
    {
        //printf("[%4d] %02x:%d:%d:%d %x\n", ++count, node->symbol, node->run_len, node->freq, node->codeword_len, node->codeword);
        if(list_.at(node->symbol) == nullptr)
            list_.at(node->symbol) = node;
        else
        {
            node->next = list_.at(node->symbol);
            list_.at(node->symbol) = node;
        }
    }
    else
    {
        if(node->left != nullptr)
            CreateRunList(node->left);

        if(node->right != nullptr)
            CreateRunList(node->right);
    }
}

Huffman
::SizeType
Huffman
::GetCodeword(CodewordType & codeword, const ByteType & symbol, const SizeType & run_len)
{
    RunType * n = list_.at(symbol);
    for(; n != nullptr && n->run_len != run_len; n = n->next);

    if(n == nullptr)
        return 0;
    else
    {
        codeword = n->codeword;
        return n->codeword_len;
    }
}

void
Huffman
::WriteHeader(StreamInType & fin, StreamOutType & fout)
{
    uint16_t run_size = uint16_t(runs_.size());
    BinaryStream::Write<uint16_t>(fout, run_size);

    fin.clear();
    fin.seekg(0, fin.end);

    uint32_t fin_size = uint32_t(fin.tellg());
    BinaryStream::Write<uint32_t>(fout, SizeType(fin.tellg()));

    for(auto run : runs_)
    {
        BinaryStream::Write<ByteType>(fout, run.symbol);
        BinaryStream::Write<SizeType>(fout, run.run_len);
        BinaryStream::Write<SizeType>(fout, run.freq);
    }
}

void
Huffman
::WriteEncode(StreamInType & fin, StreamOutType & fout)
{
    const   SizeType            bufstat_max     = buffer_size;
            SizeType            bufstat_free    = bufstat_max;
            CodewordType        buffer          = 0;

    /** Reset the input position indicator */
    fin.clear();
    fin.seekg(0, fin.beg);

    while(! fin.eof())
    {
        ByteType    symbol;
        SizeType    run_len = 1;

        BinaryStream::Read<ByteType>(fin, symbol);
        if(fin.eof())
            break;

        /** Write the codeword to fout */

        CodewordType    codeword;
        SizeType        codeword_len = GetCodeword(codeword, symbol, run_len);

        if(codeword_len == 0)
            return; /* TODO: Exception(Codeword not found)  */

        while(codeword_len >= bufstat_free)
        {
            buffer <<= bufstat_free;
            buffer += (codeword >> (codeword_len - bufstat_free));
            codeword = codeword % (0x1 << codeword_len - bufstat_free);
            codeword_len -= bufstat_free;

            BinaryStream::Write<CodewordType>(fout, buffer, false);

            buffer = 0;
            bufstat_free = bufstat_max;
        }

        buffer <<= codeword_len;
        buffer += codeword;
        bufstat_free -= codeword_len;
    }

    if(bufstat_free != bufstat_max)
    {
        buffer <<= bufstat_free;
        BinaryStream::Write<CodewordType>(fout, buffer, true);

        buffer = 0;
        bufstat_free -= bufstat_max;
    }
}

void
Huffman
::PrintHuffmanTree(FILE * f, const RunType * node, const SizeType & depth)
{
    for(int i = 0; i < depth; ++i)
        fprintf(f, "  ");
    if(node == nullptr)
        fprintf(f, "null\n");
    else
    {
        fprintf(f, "%02x:%lu:%lu:%lu %x\n"
                    , node->symbol
                    , node->run_len
                    , node->freq
                    , node->codeword_len
                    , node->codeword);

        PrintHuffmanTree(f, node->left,  depth + 1);
        PrintHuffmanTree(f, node->right, depth + 1);
    }
}

Huffman::
SizeType
Huffman::
ReadHeader(StreamInType & fin)
{
    typedef     std::map<MetaSymbolType, unsigned int>  CacheType;
    typedef     CacheType::iterator                     CacheIterType;

    fin.clear();
    fin.seekg(0, fin.beg);

    uint16_t run_size;
    BinaryStream::Read<uint16_t>(fin, run_size);

    uint32_t fout_size;
    BinaryStream::Read<uint32_t>(fin, fout_size);

    runs_.clear();

    for(int i = 0; i < run_size; ++i)
    {
        ByteType symbol;
        BinaryStream::Read<ByteType>(fin, symbol);

        SizeType run_len;
        BinaryStream::Read<SizeType>(fin, run_len);

        SizeType freq;
        BinaryStream::Read<SizeType>(fin, freq);

        Run temp = Run(symbol, run_len, freq);
        runs_.push_back(temp);
    }

    return SizeType(fout_size);
}

void
Huffman::
WriteDecode(StreamInType & fin, StreamOutType & fout, const SizeType & fout_size)
{
    const   SizeType            bufstat_max     = buffer_size;
            SizeType            bufstat_free    = bufstat_max;
            CodewordType        buffer          = 0;
            Run *               run             = root_;

    fout.clear();
    fout.seekp(0, fin.beg);

    while(! fin.eof())
    {
        BinaryStream::Read<CodewordType>(fin, buffer);
        bufstat_free = 0;

        while(bufstat_free < bufstat_max)
        {
            if(buffer / (0x1 << (buffer_size - 1)) == zerobit)
                run = run->left;
            else
                run = run->right;

            buffer <<= 0x1;
            ++bufstat_free;

            if(run->codeword_len > 0)
            {
                for(int i = 0; i < run->run_len; ++i)
                {
                    BinaryStream::Write<ByteType>(fout, run->symbol);

                    if(fout.tellp() >= fout_size)
                        goto RETURN;
                }

                run = root_;
            }
        }
    }

RETURN:
    return;
}
<commit_msg>Add tracing codes<commit_after>#include "huffman.hpp"

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <utility>
#include <string>
#include <cstring>
#include <limits>

#include "heap.hpp"
#include "binarystream.hpp"

using namespace algorithm;

void
Huffman
::CompressFile(StreamInType & fin, StreamOutType & fout)
{
    CollectRuns(fin);

    PrintAllRuns();

    fin.clear();            /** Remove eofbit */
    WriteHeader(fin, fout);

    CreateHuffmanTree();
    AssignCodeword(root_, 0, 0);

    PrintHuffmanTree();

    CreateRunList(root_);
    WriteEncode(fin, fout);
}

void
Huffman
::DecompressFile(StreamInType & fin, StreamOutType & fout)
{
    SizeType fout_size = ReadHeader(fin);

    PrintAllRuns();

    CreateHuffmanTree();
    AssignCodeword(root_, 0, 0);

    PrintHuffmanTree();

    WriteDecode(fin, fout, fout_size);
}

void
Huffman
::PrintAllRuns(FILE * f)
{
    fprintf(f, "SYM LENG FREQ\n");  /** Header of data */

    for(auto run : runs_)
        fprintf(f, " %02x %4lu %lu\n", run.symbol, run.run_len, run.freq);
}

void
Huffman
::CollectRuns(StreamInType & fin)
{
    typedef     std::map<MetaSymbolType, unsigned int>  CacheType;
    typedef     CacheType::iterator                     CacheIterType;

    CacheType   cache;              /**< Caching a position of the run in the vector(runs_) */

    fin.clear();                    /** Reset the input position indicator */
    fin.seekg(0, fin.beg);

    while(! fin.eof())
    {
        ByteType    symbol;
        SizeType    run_len = 1;

        BinaryStream::Read<ByteType>(fin, symbol);
        if(fin.eof())
            break;

        //BinaryStream::Read<SizeType>(fin, run_len);

        /** Insert the pair into runs_;
            key:    pair(symbol, run_len)
            value:  appearance frequency of key
        */
        MetaSymbolType  meta_symbol = std::make_pair(symbol, run_len);
        CacheIterType   cache_iter  = cache.find(meta_symbol);  /** Get the position from cache */

        if(cache_iter == cache.end())
        {
            runs_.push_back(RunType(meta_symbol, 1));           /** First appreance; freq is 1 */
            cache.emplace(meta_symbol, runs_.size() - 1);       /** Cache the position */
        }
        else
            ++runs_.at(cache_iter->second);                     /** Add freq */
    }
}

void
Huffman
::CreateHuffmanTree(void)
{
    Heap<RunType>   heap;
    for(auto run : runs_)
        heap.Push(run);

    while(heap.size() > 1)
    {
        RunType * left  = new RunType(heap.Peek());
        heap.Pop();

        RunType * right = new RunType(heap.Peek());
        heap.Pop();

        RunType temp(left, right);
        heap.Push(temp);
    }

    root_ = new RunType(heap.Peek());
    heap.Pop();
}

void
Huffman
::AssignCodeword(RunType * node, const CodewordType & codeword, const SizeType & codeword_len)
{
    if(node->left == nullptr && node->right == nullptr)
    {
        node->codeword      = codeword;
        node->codeword_len  = codeword_len;
    }
    else
    {
        AssignCodeword(node->left,  (codeword << 1) + 0, codeword_len + 1);
        AssignCodeword(node->right, (codeword << 1) + 1, codeword_len + 1);
    }
}

void
Huffman
::CreateRunList(RunType * node)
{
    if(node->left == nullptr && node->right == nullptr)
    {
        //printf("[%4d] %02x:%d:%d:%d %x\n", ++count, node->symbol, node->run_len, node->freq, node->codeword_len, node->codeword);
        if(list_.at(node->symbol) == nullptr)
            list_.at(node->symbol) = node;
        else
        {
            node->next = list_.at(node->symbol);
            list_.at(node->symbol) = node;
        }
    }
    else
    {
        if(node->left != nullptr)
            CreateRunList(node->left);

        if(node->right != nullptr)
            CreateRunList(node->right);
    }
}

Huffman
::SizeType
Huffman
::GetCodeword(CodewordType & codeword, const ByteType & symbol, const SizeType & run_len)
{
    RunType * n = list_.at(symbol);
    for(; n != nullptr && n->run_len != run_len; n = n->next);

    if(n == nullptr)
        return 0;
    else
    {
        codeword = n->codeword;
        return n->codeword_len;
    }
}

void
Huffman
::WriteHeader(StreamInType & fin, StreamOutType & fout)
{
    uint16_t run_size = uint16_t(runs_.size());
    BinaryStream::Write<uint16_t>(fout, run_size);

    fin.clear();
    fin.seekg(0, fin.end);

    uint32_t fin_size = uint32_t(fin.tellg());
    BinaryStream::Write<uint32_t>(fout, SizeType(fin.tellg()));

    for(auto run : runs_)
    {
        BinaryStream::Write<ByteType>(fout, run.symbol);
        BinaryStream::Write<SizeType>(fout, run.run_len);
        BinaryStream::Write<SizeType>(fout, run.freq);
    }
}

void
Huffman
::WriteEncode(StreamInType & fin, StreamOutType & fout)
{
    const   SizeType            bufstat_max     = buffer_size;
            SizeType            bufstat_free    = bufstat_max;
            CodewordType        buffer          = 0;

    /** Reset the input position indicator */
    fin.clear();
    fin.seekg(0, fin.beg);

    while(! fin.eof())
    {
        ByteType    symbol;
        SizeType    run_len = 1;

        BinaryStream::Read<ByteType>(fin, symbol);
        if(fin.eof())
            break;

        /** Write the codeword to fout */

        CodewordType    codeword;
        SizeType        codeword_len = GetCodeword(codeword, symbol, run_len);

        if(codeword_len == 0)
            return; /* TODO: Exception(Codeword not found)  */

        while(codeword_len >= bufstat_free)
        {
            buffer <<= bufstat_free;
            buffer += (codeword >> (codeword_len - bufstat_free));
            codeword = codeword % (0x1 << codeword_len - bufstat_free);
            codeword_len -= bufstat_free;

            BinaryStream::Write<CodewordType>(fout, buffer, false);

            buffer = 0;
            bufstat_free = bufstat_max;
        }

        buffer <<= codeword_len;
        buffer += codeword;
        bufstat_free -= codeword_len;
    }

    if(bufstat_free != bufstat_max)
    {
        buffer <<= bufstat_free;
        BinaryStream::Write<CodewordType>(fout, buffer, true);

        buffer = 0;
        bufstat_free -= bufstat_max;
    }
}

void
Huffman
::PrintHuffmanTree(FILE * f, const RunType * node, const SizeType & depth)
{
    for(int i = 0; i < depth; ++i)
        fprintf(f, "  ");
    if(node == nullptr)
        fprintf(f, "null\n");
    else
    {
        fprintf(f, "%02x:%lu:%lu:%lu %x\n"
                    , node->symbol
                    , node->run_len
                    , node->freq
                    , node->codeword_len
                    , node->codeword);

        PrintHuffmanTree(f, node->left,  depth + 1);
        PrintHuffmanTree(f, node->right, depth + 1);
    }
}

Huffman::
SizeType
Huffman::
ReadHeader(StreamInType & fin)
{
    typedef     std::map<MetaSymbolType, unsigned int>  CacheType;
    typedef     CacheType::iterator                     CacheIterType;

    fin.clear();
    fin.seekg(0, fin.beg);

    uint16_t run_size;
    BinaryStream::Read<uint16_t>(fin, run_size);

    uint32_t fout_size;
    BinaryStream::Read<uint32_t>(fin, fout_size);

    runs_.clear();

    for(int i = 0; i < run_size; ++i)
    {
        ByteType symbol;
        BinaryStream::Read<ByteType>(fin, symbol);

        SizeType run_len;
        BinaryStream::Read<SizeType>(fin, run_len);

        SizeType freq;
        BinaryStream::Read<SizeType>(fin, freq);

        Run temp = Run(symbol, run_len, freq);
        runs_.push_back(temp);
    }

    return SizeType(fout_size);
}

void
Huffman::
WriteDecode(StreamInType & fin, StreamOutType & fout, const SizeType & fout_size)
{
    const   SizeType            bufstat_max     = buffer_size;
            SizeType            bufstat_free    = bufstat_max;
            CodewordType        buffer          = 0;
            Run *               run             = root_;

    fout.clear();
    fout.seekp(0, fin.beg);

    while(! fin.eof())
    {
        BinaryStream::Read<CodewordType>(fin, buffer);
        bufstat_free = 0;

        while(bufstat_free < bufstat_max)
        {
            BinaryStream::Print<CodewordType>(std::cout, buffer, size_t(buffer_size));
            std::cout << "\n";

            if(buffer / (0x1 << (buffer_size - 1)) == zerobit)
            {
                std::cout << "[0] ";
                run = run->left;
            }
            else
            {
                std::cout << "[1] ";
                run = run->right;
            }

            fprintf(stdout, "%02x:%lu:%lu:%lu %x\n\n"
                    , run->symbol
                    , run->run_len
                    , run->freq
                    , run->codeword_len
                    , run->codeword);

            buffer <<= 0x1;
            ++bufstat_free;

            if(run->codeword_len > 0)
            {
                for(int i = 0; i < run->run_len; ++i)
                {
                    BinaryStream::Write<ByteType>(fout, run->symbol);

                    if(fout.tellp() >= fout_size)
                        goto RETURN;
                }

                run = root_;
            }
        }
    }

RETURN:
    return;
}
<|endoftext|>


<commit_before>
#include <cmath>
#include "lcmtypes/bot_core/planar_lidar_t.hpp"
#include "drake/systems/LCMSystem.h"
#include "drake/systems/plants/RigidBodySystem.h"
#include "drake/systems/plants/BotVisualizer.h"
#include "drake/util/testUtil.h"

using namespace std;
using namespace Eigen;
using namespace Drake;

int main(int argc, char* argv[]) {
  // unit test that sets up a lidar in a box room and verifies the returns

  auto rigid_body_sys = make_shared<RigidBodySystem>();
  rigid_body_sys->addRobotFromFile(getDrakePath() + "/systems/plants/test/lidarTest.sdf", DrakeJoint::FIXED);

  double t = 0;
  VectorXd x = VectorXd::Zero(rigid_body_sys->getNumStates());
  VectorXd u = VectorXd::Zero(rigid_body_sys->getNumInputs());

  //  rigid_body_sys->getRigidBodyTree()->drawKinematicTree("/tmp/lidar.dot");

  auto distances = rigid_body_sys->output(t, x, u);

  // these parameters must match the sdf (i've also implicitly hard-coded the
  // box geometry from the sdf)
  const double min_yaw = -1.7;
  const double max_yaw = 1.7;
  const double max_range = 25.0;
  const double tol = 0.01;

  for (int i = 0; i < distances.size(); i++) {
    double theta = min_yaw + (max_yaw - min_yaw) * i / (distances.size() - 1);

    if (abs(theta) >= M_PI / 2 + 0.01) {  // should not be hitting any wall.  //
                                         // todo: get rid of the .05 artifact
                                         // (see #1712)
      valuecheck(max_range, distances(i));
    } else if (theta <= -M_PI / 4) {  // hitting the right wall
      valuecheck(-1.0 / sin(theta), distances(i), tol);
    } else if (theta >= M_PI / 4) {  // hitting the left wall
      valuecheck(1.0 / sin(theta), distances(i), tol);
    } else {  // hitting the front wall
      valuecheck(1 / cos(theta), distances(i), tol);
    }
  }

  auto lcm = make_shared<lcm::LCM>();

  bot_core::planar_lidar_t msg;
  msg.utime = -1;
  msg.nintensities = 0;
  msg.rad0 = min_yaw;
  msg.radstep = (max_yaw - min_yaw) / (distances.size() - 1);

  msg.nranges = distances.size();
  for (int i = 0; i < distances.size(); i++)
    msg.ranges.push_back(distances(i));

  lcm->publish("DRAKE_POINTCLOUD_LIDAR_TEST", &msg);

  // render for debugging:
  auto visualizer = make_shared<BotVisualizer<RigidBodySystem::StateVector>>(
      lcm, rigid_body_sys->getRigidBodyTree());
  visualizer->output(t, x, u);

  return 0;
}
<commit_msg>Fix lidar test for drake-visualizer's benefit<commit_after>
#include <cmath>
#include "lcmtypes/bot_core/planar_lidar_t.hpp"
#include "drake/systems/LCMSystem.h"
#include "drake/systems/plants/RigidBodySystem.h"
#include "drake/systems/plants/BotVisualizer.h"
#include "drake/util/testUtil.h"

using namespace std;
using namespace Eigen;
using namespace Drake;

int main(int argc, char* argv[]) {
  // unit test that sets up a lidar in a box room and verifies the returns

  auto rigid_body_sys = make_shared<RigidBodySystem>();
  rigid_body_sys->addRobotFromFile(getDrakePath() + "/systems/plants/test/lidarTest.sdf", DrakeJoint::FIXED);

  double t = 0;
  VectorXd x = VectorXd::Zero(rigid_body_sys->getNumStates());
  VectorXd u = VectorXd::Zero(rigid_body_sys->getNumInputs());

  //  rigid_body_sys->getRigidBodyTree()->drawKinematicTree("/tmp/lidar.dot");

  auto distances = rigid_body_sys->output(t, x, u);

  // these parameters must match the sdf (i've also implicitly hard-coded the
  // box geometry from the sdf)
  const double min_yaw = -1.7;
  const double max_yaw = 1.7;
  const double max_range = 25.0;
  const double tol = 0.01;

  for (int i = 0; i < distances.size(); i++) {
    double theta = min_yaw + (max_yaw - min_yaw) * i / (distances.size() - 1);

    if (abs(theta) >= M_PI / 2 + 0.01) {  // should not be hitting any wall.  //
                                         // todo: get rid of the .05 artifact
                                         // (see #1712)
      valuecheck(max_range, distances(i));
    } else if (theta <= -M_PI / 4) {  // hitting the right wall
      valuecheck(-1.0 / sin(theta), distances(i), tol);
    } else if (theta >= M_PI / 4) {  // hitting the left wall
      valuecheck(1.0 / sin(theta), distances(i), tol);
    } else {  // hitting the front wall
      valuecheck(1 / cos(theta), distances(i), tol);
    }
  }

  // render for debugging; do this before publishing lidar so visualizer knows
  // the sensor position
  auto lcm = make_shared<lcm::LCM>();
  auto visualizer = make_shared<BotVisualizer<RigidBodySystem::StateVector>>(
      lcm, rigid_body_sys->getRigidBodyTree());
  visualizer->output(t, x, u);

  // publish lidar message
  bot_core::planar_lidar_t msg;
  msg.utime = -1;
  msg.nintensities = 0;
  msg.rad0 = min_yaw;
  msg.radstep = (max_yaw - min_yaw) / (distances.size() - 1);

  msg.nranges = distances.size();
  for (int i = 0; i < distances.size(); i++)
    msg.ranges.push_back(distances(i));

  lcm->publish("DRAKE_PLANAR_LIDAR_0_rear_wall", &msg);

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>mean pt fluctuation PbPb 5.02 TeV<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTDxInteractorStyle.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkTDxInteractorStyle.h"

#include "vtkCommand.h"
#include "vtkTDxInteractorStyleSettings.h"

vtkCxxRevisionMacro(vtkTDxInteractorStyle, "1.1");

vtkCxxSetObjectMacro(vtkTDxInteractorStyle,Settings,
                     vtkTDxInteractorStyleSettings);

// ----------------------------------------------------------------------------
vtkTDxInteractorStyle::vtkTDxInteractorStyle()
{
  this->Renderer=0;
  this->Settings=vtkTDxInteractorStyleSettings::New();
}

// ----------------------------------------------------------------------------
vtkTDxInteractorStyle::~vtkTDxInteractorStyle()
{
  if(this->Settings!=0)
    {
    this->Settings->Delete();
    }
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::ProcessEvent(vtkRenderer *renderer,
                                         unsigned long event,
                                         void *calldata)
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::ProcessEvent()");
  this->Renderer=renderer;

  vtkTDxMotionEventInfo *motionInfo;
  int *buttonInfo;

  switch(event)
    {
    case vtkCommand::TDxMotionEvent:
      motionInfo=static_cast<vtkTDxMotionEventInfo *>(calldata);
      this->OnMotionEvent(motionInfo);
      break;
    case vtkCommand::TDxButtonPressEvent:
      buttonInfo=static_cast<int *>(calldata);
      this->OnButtonPressedEvent(*buttonInfo);
      break;
    case vtkCommand::TDxButtonReleaseEvent:
      buttonInfo=static_cast<int *>(calldata);
      this->OnButtonReleasedEvent(*buttonInfo);
      break;
    }
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::OnMotionEvent(
  vtkTDxMotionEventInfo *vtkNotUsed(motionInfo))
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::OnMotionEvent()");
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::OnButtonPressedEvent(int vtkNotUsed(button))
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::OnButtonPressedEvent()");
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::OnButtonReleasedEvent(int vtkNotUsed(button))
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::OnButtonReleasedEvent()");
}

//----------------------------------------------------------------------------
void vtkTDxInteractorStyle::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Settings: ";
  if(this->Settings==0)
    {
    os << "(none)" << endl;
    }
  else
    {
    os << endl;
    this->Settings->PrintSelf(os,indent.GetNextIndent());
    }
}
<commit_msg>COMP:BCC needs a class definition for a static_cast on class pointers...<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTDxInteractorStyle.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkTDxInteractorStyle.h"

#include "vtkCommand.h"
#include "vtkTDxInteractorStyleSettings.h"
#include "vtkTDxMotionEventInfo.h" // Borland needs it.

vtkCxxRevisionMacro(vtkTDxInteractorStyle, "1.2");

vtkCxxSetObjectMacro(vtkTDxInteractorStyle,Settings,
                     vtkTDxInteractorStyleSettings);

// ----------------------------------------------------------------------------
vtkTDxInteractorStyle::vtkTDxInteractorStyle()
{
  this->Renderer=0;
  this->Settings=vtkTDxInteractorStyleSettings::New();
}

// ----------------------------------------------------------------------------
vtkTDxInteractorStyle::~vtkTDxInteractorStyle()
{
  if(this->Settings!=0)
    {
    this->Settings->Delete();
    }
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::ProcessEvent(vtkRenderer *renderer,
                                         unsigned long event,
                                         void *calldata)
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::ProcessEvent()");
  this->Renderer=renderer;

  vtkTDxMotionEventInfo *motionInfo;
  int *buttonInfo;

  switch(event)
    {
    case vtkCommand::TDxMotionEvent:
      motionInfo=static_cast<vtkTDxMotionEventInfo *>(calldata);
      this->OnMotionEvent(motionInfo);
      break;
    case vtkCommand::TDxButtonPressEvent:
      buttonInfo=static_cast<int *>(calldata);
      this->OnButtonPressedEvent(*buttonInfo);
      break;
    case vtkCommand::TDxButtonReleaseEvent:
      buttonInfo=static_cast<int *>(calldata);
      this->OnButtonReleasedEvent(*buttonInfo);
      break;
    }
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::OnMotionEvent(
  vtkTDxMotionEventInfo *vtkNotUsed(motionInfo))
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::OnMotionEvent()");
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::OnButtonPressedEvent(int vtkNotUsed(button))
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::OnButtonPressedEvent()");
}

// ----------------------------------------------------------------------------
void vtkTDxInteractorStyle::OnButtonReleasedEvent(int vtkNotUsed(button))
{
  vtkDebugMacro(<<"vtkTDxInteractorStyle::OnButtonReleasedEvent()");
}

//----------------------------------------------------------------------------
void vtkTDxInteractorStyle::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Settings: ";
  if(this->Settings==0)
    {
    os << "(none)" << endl;
    }
  else
    {
    os << endl;
    this->Settings->PrintSelf(os,indent.GetNextIndent());
    }
}
<|endoftext|>