<commit_before>// Copyright © 2014 German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.
//
// Author: Jan Grewe <jan.grewe@g-node.org>

#include "TestDataTag.hpp"
#include <sstream>
#include <ctime>

using namespace nix;
using namespace nix::hdf5;

void TestDataTag::setUp() {
	startup_time = time(NULL);
	file = File::open("test_dataTag.h5", FileMode::Overwrite);
	block = file.createBlock("block", "dataset");
	tag = block.createDataTag("tag_one", "test_tag");
	tag_other = block.createDataTag("tag_two", "test_tag");
	tag_null = nullptr;

	positions = block.createDataArray("positions_DataArray", "dataArray");
	extents = block.createDataArray("extents_DataArray", "dataArray");
	typedef boost::multi_array<double, 1> array_type;
	typedef array_type::index index;
	array_type A(boost::extents[5]);
	for(index i = 0; i != 5; ++i){
		A[i] = 100.0*i;
	}
	positions.setData(A);

	array_type B(boost::extents[10]);
	for(index i = 0; i != 10; ++i){
		B[i] = 100.0*i;
	}
	extents.setData(B);

	section = file.createSection("foo_section", "metadata");
}

void TestDataTag::tearDown(){
	file.deleteBlock(block.id());
	file.deleteSection(section.id());
	file.close();
}

void TestDataTag::testId() {
	CPPUNIT_ASSERT(tag.id().size() == 25);
}

void TestDataTag::testName() {
	CPPUNIT_ASSERT(*tag.name() == "tag_one");
	std::string name = util::createId("", 32);
	tag.name(name);
	CPPUNIT_ASSERT(*tag.name() == name);
}

void TestDataTag::testType() {
	CPPUNIT_ASSERT(tag.type() == "test_tag");
	std::string type = util::createId("", 32);
	tag.type(type);
	CPPUNIT_ASSERT(tag.type() == type);
}

void TestDataTag::testDefinition() {
	std::string def = util::createId("", 128);
	tag.definition(def);
	CPPUNIT_ASSERT(*tag.definition() == def);
}

void TestDataTag::testCreateRemove() {
	std::vector<std::string> ids;
	size_t count = block.dataTagCount();
	const char *names[5] = { "tag_a", "tag_b", "tag_c", "tag_d",
			"tag_e" };
	for (int i = 0; i < 5; i++) {
		std::string type = "Event";
		DataTag dt1 = block.createDataTag(names[i], type);
		DataTag dt2 = block.getDataTag(dt1.id());
		ids.push_back(dt1.id());

		std::stringstream errmsg;
		errmsg << "Error while accessing dataTag: dt1.id() = " << dt1.id()
            				   << " / dt2.id() = " << dt2.id();
		CPPUNIT_ASSERT_MESSAGE(errmsg.str(), dt1.id().compare(dt2.id()) == 0);
	}
	std::stringstream errmsg2;
	errmsg2 << "Error creating DataTags. Counts do not match!";
	CPPUNIT_ASSERT_MESSAGE(errmsg2.str(), block.dataTagCount() == (count+5));

	for (size_t i = 0; i < ids.size(); i++) {
		block.deleteDataTag(ids[i]);
	}

	std::stringstream errmsg1;
	errmsg1 << "Error while removing dataTags!";
	CPPUNIT_ASSERT_MESSAGE(errmsg1.str(), block.dataTagCount() == count);
}

//TODO Constraints on References are not tested yet.

void TestDataTag::testReferences(){
	DataArray da_1 = block.createDataArray("TestReference 1","Reference");
	DataArray da_2 = block.createDataArray("TestReference 2","Reference");
	DataTag dt = block.createDataTag("TestDataTag1","Tag");

	std::stringstream counterrmsg;
	counterrmsg << "TestDataTag::testReference: Counts do not match!";
	CPPUNIT_ASSERT_MESSAGE(counterrmsg.str(), dt.referenceCount() == 0);

	dt.addReference(da_1);
	dt.addReference(da_2);
	CPPUNIT_ASSERT_MESSAGE(counterrmsg.str(), dt.referenceCount() == 2);

	DataArray ref1 = dt.getReference(da_1.id());
	std::stringstream retrieveerrmsg;
	retrieveerrmsg << "TestDataTag::testReference: Retrieval did not work!";
	CPPUNIT_ASSERT_MESSAGE(retrieveerrmsg.str(), ref1.id() == da_1.id());

	std::vector<DataArray> arrays = dt.references();
	CPPUNIT_ASSERT_MESSAGE(retrieveerrmsg.str(), arrays.size() == 2);

	std::stringstream hasReferrmsg;
	hasReferrmsg << "TestDataTag::testReference: hadReference did not work!";
	CPPUNIT_ASSERT_MESSAGE(hasReferrmsg.str(), dt.hasReference(da_1.id()));
	CPPUNIT_ASSERT_MESSAGE(hasReferrmsg.str(), dt.hasReference(da_2.id()));

	std::stringstream delReferrmsg;
	delReferrmsg << "TestDataTag::testReference: removeReference did not work!";
	dt.removeReference(da_1.id());
	CPPUNIT_ASSERT_MESSAGE(delReferrmsg.str(), dt.referenceCount() == 1);
	dt.removeReference(da_2.id());
	CPPUNIT_ASSERT_MESSAGE(delReferrmsg.str(), dt.referenceCount() == 0);

	block.deleteDataArray(da_1.id());
	block.deleteDataArray(da_1.id());
	block.deleteDataTag(dt.id());
}

void TestDataTag::testExtents(){
	CPPUNIT_ASSERT_THROW(tag.extents("wrong_data_array_id"),std::runtime_error);

	tag.extents(extents);
	CPPUNIT_ASSERT(tag.hasExtents());
	tag.extents(boost::none);
	CPPUNIT_ASSERT(tag.hasExtents() == false);
	CPPUNIT_ASSERT(tag.hasPositions() == false);
}

void TestDataTag::testPositions(){
	CPPUNIT_ASSERT_THROW(tag.positions("wrong_data_array_id"),std::runtime_error);

	tag.positions(positions);
	CPPUNIT_ASSERT(tag.hasPositions());
}

void TestDataTag::testPositionExtents(){
	tag.positions(positions);
	CPPUNIT_ASSERT_THROW(tag.extents(extents),std::runtime_error);
	tag.extents(boost::none);
	CPPUNIT_ASSERT(tag.hasExtents() == false);
}

void TestDataTag::testMetadataAccess() {
	CPPUNIT_ASSERT(!tag.hasMetadata());

	tag.metadata(section);
	CPPUNIT_ASSERT(tag.hasMetadata());
	// TODO This test fails due to operator== of Section
	// CPPUNIT_ASSERT(source.metadata() == section);

	tag.metadata(boost::none);
	CPPUNIT_ASSERT(!tag.hasMetadata());
}

void TestDataTag::testSourceAccess(){
	std::vector<std::string> names = { "source_a", "source_b", "source_c", "source_d", "source_e" };
	CPPUNIT_ASSERT(tag.sourceCount() == 0);
	CPPUNIT_ASSERT(tag.sources().size() == 0);

	std::vector<std::string> ids;
	for (auto it = names.begin(); it != names.end(); it++) {
		Source child_source = block.createSource(*it,"channel");
		tag.addSource(child_source);
		CPPUNIT_ASSERT(child_source.name() == *it);
		ids.push_back(child_source.id());
	}

	CPPUNIT_ASSERT(tag.sourceCount() == names.size());
	//TODO the following test crashes!!!
	//std::vector<Source> sources = tag.sources();
	//std::cerr << "\n" <<sources.size() << "\n";
	//CPPUNIT_ASSERT(tag.sources().size() == names.size());

	for (auto it = ids.begin(); it != ids.end(); it++) {
		Source child_source = tag.getSource(*it);
		CPPUNIT_ASSERT(tag.hasSource(*it) == true);
		CPPUNIT_ASSERT(child_source.id() == *it);

		tag.removeSource(*it);
		block.deleteSource(*it);
	}

	CPPUNIT_ASSERT(tag.sourceCount() == 0);
	//CPPUNIT_ASSERT(tag.sources().size() == 0);
}

void TestDataTag::testOperators() {
    CPPUNIT_ASSERT(tag_null == NULL);
    CPPUNIT_ASSERT(tag_null == nullptr);

    CPPUNIT_ASSERT(tag != NULL);
    CPPUNIT_ASSERT(tag != nullptr);

    CPPUNIT_ASSERT(tag == tag);
    CPPUNIT_ASSERT(tag != tag_other);

    tag_other = tag;
    CPPUNIT_ASSERT(tag == tag_other);

    tag_other = nullptr;
    CPPUNIT_ASSERT(tag_null == NULL);
    CPPUNIT_ASSERT(tag_null == nullptr);
}

void TestDataTag::testCreatedAt() {
    CPPUNIT_ASSERT(tag.createdAt() >= startup_time);
    time_t past_time = time(NULL) - 10000000;
    tag.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(tag.createdAt() == past_time);
}

void TestDataTag::testUpdatedAt() {
    CPPUNIT_ASSERT(tag.updatedAt() >= startup_time);
}
<commit_msg>[test] DataTag: Test for OutOfBounds ex. in getReference call<commit_after>// Copyright © 2014 German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.
//
// Author: Jan Grewe <jan.grewe@g-node.org>

#include "TestDataTag.hpp"
#include <nix/Exception.hpp>
#include <sstream>
#include <ctime>

using namespace nix;
using namespace nix::hdf5;

void TestDataTag::setUp() {
	startup_time = time(NULL);
	file = File::open("test_dataTag.h5", FileMode::Overwrite);
	block = file.createBlock("block", "dataset");
	tag = block.createDataTag("tag_one", "test_tag");
	tag_other = block.createDataTag("tag_two", "test_tag");
	tag_null = nullptr;

	positions = block.createDataArray("positions_DataArray", "dataArray");
	extents = block.createDataArray("extents_DataArray", "dataArray");
	typedef boost::multi_array<double, 1> array_type;
	typedef array_type::index index;
	array_type A(boost::extents[5]);
	for(index i = 0; i != 5; ++i){
		A[i] = 100.0*i;
	}
	positions.setData(A);

	array_type B(boost::extents[10]);
	for(index i = 0; i != 10; ++i){
		B[i] = 100.0*i;
	}
	extents.setData(B);

	section = file.createSection("foo_section", "metadata");
}

void TestDataTag::tearDown(){
	file.deleteBlock(block.id());
	file.deleteSection(section.id());
	file.close();
}

void TestDataTag::testId() {
	CPPUNIT_ASSERT(tag.id().size() == 25);
}

void TestDataTag::testName() {
	CPPUNIT_ASSERT(*tag.name() == "tag_one");
	std::string name = util::createId("", 32);
	tag.name(name);
	CPPUNIT_ASSERT(*tag.name() == name);
}

void TestDataTag::testType() {
	CPPUNIT_ASSERT(tag.type() == "test_tag");
	std::string type = util::createId("", 32);
	tag.type(type);
	CPPUNIT_ASSERT(tag.type() == type);
}

void TestDataTag::testDefinition() {
	std::string def = util::createId("", 128);
	tag.definition(def);
	CPPUNIT_ASSERT(*tag.definition() == def);
}

void TestDataTag::testCreateRemove() {
	std::vector<std::string> ids;
	size_t count = block.dataTagCount();
	const char *names[5] = { "tag_a", "tag_b", "tag_c", "tag_d",
			"tag_e" };
	for (int i = 0; i < 5; i++) {
		std::string type = "Event";
		DataTag dt1 = block.createDataTag(names[i], type);
		DataTag dt2 = block.getDataTag(dt1.id());
		ids.push_back(dt1.id());

		std::stringstream errmsg;
		errmsg << "Error while accessing dataTag: dt1.id() = " << dt1.id()
            				   << " / dt2.id() = " << dt2.id();
		CPPUNIT_ASSERT_MESSAGE(errmsg.str(), dt1.id().compare(dt2.id()) == 0);
	}
	std::stringstream errmsg2;
	errmsg2 << "Error creating DataTags. Counts do not match!";
	CPPUNIT_ASSERT_MESSAGE(errmsg2.str(), block.dataTagCount() == (count+5));

	for (size_t i = 0; i < ids.size(); i++) {
		block.deleteDataTag(ids[i]);
	}

	std::stringstream errmsg1;
	errmsg1 << "Error while removing dataTags!";
	CPPUNIT_ASSERT_MESSAGE(errmsg1.str(), block.dataTagCount() == count);
}

//TODO Constraints on References are not tested yet.

void TestDataTag::testReferences(){
	DataArray da_1 = block.createDataArray("TestReference 1","Reference");
	DataArray da_2 = block.createDataArray("TestReference 2","Reference");
	DataTag dt = block.createDataTag("TestDataTag1","Tag");

    CPPUNIT_ASSERT_THROW(dt.getReference(42), nix::OutOfBounds);

	std::stringstream counterrmsg;
	counterrmsg << "TestDataTag::testReference: Counts do not match!";
	CPPUNIT_ASSERT_MESSAGE(counterrmsg.str(), dt.referenceCount() == 0);

	dt.addReference(da_1);
	dt.addReference(da_2);
	CPPUNIT_ASSERT_MESSAGE(counterrmsg.str(), dt.referenceCount() == 2);

	DataArray ref1 = dt.getReference(da_1.id());
	std::stringstream retrieveerrmsg;
	retrieveerrmsg << "TestDataTag::testReference: Retrieval did not work!";
	CPPUNIT_ASSERT_MESSAGE(retrieveerrmsg.str(), ref1.id() == da_1.id());

	std::vector<DataArray> arrays = dt.references();
	CPPUNIT_ASSERT_MESSAGE(retrieveerrmsg.str(), arrays.size() == 2);

	std::stringstream hasReferrmsg;
	hasReferrmsg << "TestDataTag::testReference: hadReference did not work!";
	CPPUNIT_ASSERT_MESSAGE(hasReferrmsg.str(), dt.hasReference(da_1.id()));
	CPPUNIT_ASSERT_MESSAGE(hasReferrmsg.str(), dt.hasReference(da_2.id()));

	std::stringstream delReferrmsg;
	delReferrmsg << "TestDataTag::testReference: removeReference did not work!";
	dt.removeReference(da_1.id());
	CPPUNIT_ASSERT_MESSAGE(delReferrmsg.str(), dt.referenceCount() == 1);
	dt.removeReference(da_2.id());
	CPPUNIT_ASSERT_MESSAGE(delReferrmsg.str(), dt.referenceCount() == 0);

	block.deleteDataArray(da_1.id());
	block.deleteDataArray(da_1.id());
	block.deleteDataTag(dt.id());
}

void TestDataTag::testExtents(){
	CPPUNIT_ASSERT_THROW(tag.extents("wrong_data_array_id"),std::runtime_error);

	tag.extents(extents);
	CPPUNIT_ASSERT(tag.hasExtents());
	tag.extents(boost::none);
	CPPUNIT_ASSERT(tag.hasExtents() == false);
	CPPUNIT_ASSERT(tag.hasPositions() == false);
}

void TestDataTag::testPositions(){
	CPPUNIT_ASSERT_THROW(tag.positions("wrong_data_array_id"),std::runtime_error);

	tag.positions(positions);
	CPPUNIT_ASSERT(tag.hasPositions());
}

void TestDataTag::testPositionExtents(){
	tag.positions(positions);
	CPPUNIT_ASSERT_THROW(tag.extents(extents),std::runtime_error);
	tag.extents(boost::none);
	CPPUNIT_ASSERT(tag.hasExtents() == false);
}

void TestDataTag::testMetadataAccess() {
	CPPUNIT_ASSERT(!tag.hasMetadata());

	tag.metadata(section);
	CPPUNIT_ASSERT(tag.hasMetadata());
	// TODO This test fails due to operator== of Section
	// CPPUNIT_ASSERT(source.metadata() == section);

	tag.metadata(boost::none);
	CPPUNIT_ASSERT(!tag.hasMetadata());
}

void TestDataTag::testSourceAccess(){
	std::vector<std::string> names = { "source_a", "source_b", "source_c", "source_d", "source_e" };
	CPPUNIT_ASSERT(tag.sourceCount() == 0);
	CPPUNIT_ASSERT(tag.sources().size() == 0);

	std::vector<std::string> ids;
	for (auto it = names.begin(); it != names.end(); it++) {
		Source child_source = block.createSource(*it,"channel");
		tag.addSource(child_source);
		CPPUNIT_ASSERT(child_source.name() == *it);
		ids.push_back(child_source.id());
	}

	CPPUNIT_ASSERT(tag.sourceCount() == names.size());
	//TODO the following test crashes!!!
	//std::vector<Source> sources = tag.sources();
	//std::cerr << "\n" <<sources.size() << "\n";
	//CPPUNIT_ASSERT(tag.sources().size() == names.size());

	for (auto it = ids.begin(); it != ids.end(); it++) {
		Source child_source = tag.getSource(*it);
		CPPUNIT_ASSERT(tag.hasSource(*it) == true);
		CPPUNIT_ASSERT(child_source.id() == *it);

		tag.removeSource(*it);
		block.deleteSource(*it);
	}

	CPPUNIT_ASSERT(tag.sourceCount() == 0);
	//CPPUNIT_ASSERT(tag.sources().size() == 0);
}

void TestDataTag::testOperators() {
    CPPUNIT_ASSERT(tag_null == NULL);
    CPPUNIT_ASSERT(tag_null == nullptr);

    CPPUNIT_ASSERT(tag != NULL);
    CPPUNIT_ASSERT(tag != nullptr);

    CPPUNIT_ASSERT(tag == tag);
    CPPUNIT_ASSERT(tag != tag_other);

    tag_other = tag;
    CPPUNIT_ASSERT(tag == tag_other);

    tag_other = nullptr;
    CPPUNIT_ASSERT(tag_null == NULL);
    CPPUNIT_ASSERT(tag_null == nullptr);
}

void TestDataTag::testCreatedAt() {
    CPPUNIT_ASSERT(tag.createdAt() >= startup_time);
    time_t past_time = time(NULL) - 10000000;
    tag.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(tag.createdAt() == past_time);
}

void TestDataTag::testUpdatedAt() {
    CPPUNIT_ASSERT(tag.updatedAt() >= startup_time);
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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/multiprocess_test.h"
#include "base/platform_thread.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/shared_memory.h"
#include "base/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"

static const int kNumThreads = 5;
static const int kNumTasks = 5;

namespace base {

namespace {

// Each thread will open the shared memory.  Each thread will take a different 4
// byte int pointer, and keep changing it, with some small pauses in between.
// Verify that each thread's value in the shared memory is always correct.
class MultipleThreadMain : public PlatformThread::Delegate {
 public:
  explicit MultipleThreadMain(int16 id) : id_(id) {}
  ~MultipleThreadMain() {}

  static void CleanUp() {
    SharedMemory memory;
    memory.Delete(s_test_name_);
  }

  // PlatformThread::Delegate interface.
  void ThreadMain() {
    ScopedNSAutoreleasePool pool;  // noop if not OSX
    const int kDataSize = 1024;
    SharedMemory memory;
    bool rv = memory.Create(s_test_name_, false, true, kDataSize);
    EXPECT_TRUE(rv);
    rv = memory.Map(kDataSize);
    EXPECT_TRUE(rv);
    int *ptr = static_cast<int*>(memory.memory()) + id_;
    EXPECT_EQ(*ptr, 0);

    for (int idx = 0; idx < 100; idx++) {
      *ptr = idx;
      PlatformThread::Sleep(1);  // Short wait.
      EXPECT_EQ(*ptr, idx);
    }

    memory.Close();
  }

 private:
  int16 id_;

  static const wchar_t* const s_test_name_;

  DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
};

const wchar_t* const MultipleThreadMain::s_test_name_ =
    L"SharedMemoryOpenThreadTest";

// TODO(port):
// This test requires the ability to pass file descriptors between processes.
// We haven't done that yet in Chrome for POSIX.
#if defined(OS_WIN)
// Each thread will open the shared memory.  Each thread will take the memory,
// and keep changing it while trying to lock it, with some small pauses in
// between. Verify that each thread's value in the shared memory is always
// correct.
class MultipleLockThread : public PlatformThread::Delegate {
 public:
  explicit MultipleLockThread(int id) : id_(id) {}
  ~MultipleLockThread() {}

  // PlatformThread::Delegate interface.
  void ThreadMain() {
    const int kDataSize = sizeof(int);
    SharedMemoryHandle handle = NULL;
    {
      SharedMemory memory1;
      EXPECT_TRUE(memory1.Create(L"SharedMemoryMultipleLockThreadTest",
                                 false, true, kDataSize));
      EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
      // TODO(paulg): Implement this once we have a posix version of
      // SharedMemory::ShareToProcess.
      EXPECT_TRUE(true);
    }

    SharedMemory memory2(handle, false);
    EXPECT_TRUE(memory2.Map(kDataSize));
    volatile int* const ptr = static_cast<int*>(memory2.memory());

    for (int idx = 0; idx < 20; idx++) {
      memory2.Lock();
      int i = (id_ << 16) + idx;
      *ptr = i;
      PlatformThread::Sleep(1);  // Short wait.
      EXPECT_EQ(*ptr, i);
      memory2.Unlock();
    }

    memory2.Close();
  }

 private:
  int id_;

  DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
};
#endif

}  // namespace

TEST(SharedMemoryTest, OpenClose) {
  const int kDataSize = 1024;
  std::wstring test_name = L"SharedMemoryOpenCloseTest";

  // Open two handles to a memory segment, confirm that they are mapped
  // separately yet point to the same space.
  SharedMemory memory1;
  bool rv = memory1.Delete(test_name);
  EXPECT_TRUE(rv);
  rv = memory1.Delete(test_name);
  EXPECT_TRUE(rv);
  rv = memory1.Open(test_name, false);
  EXPECT_FALSE(rv);
  rv = memory1.Create(test_name, false, false, kDataSize);
  EXPECT_TRUE(rv);
  rv = memory1.Map(kDataSize);
  EXPECT_TRUE(rv);
  SharedMemory memory2;
  rv = memory2.Open(test_name, false);
  EXPECT_TRUE(rv);
  rv = memory2.Map(kDataSize);
  EXPECT_TRUE(rv);
  EXPECT_NE(memory1.memory(), memory2.memory());  // Compare the pointers.

  // Make sure we don't segfault. (it actually happened!)
  ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
  ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));

  // Write data to the first memory segment, verify contents of second.
  memset(memory1.memory(), '1', kDataSize);
  EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);

  // Close the first memory segment, and verify the second has the right data.
  memory1.Close();
  char *start_ptr = static_cast<char *>(memory2.memory());
  char *end_ptr = start_ptr + kDataSize;
  for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
    EXPECT_EQ(*ptr, '1');

  // Close the second memory segment.
  memory2.Close();

  rv = memory1.Delete(test_name);
  EXPECT_TRUE(rv);
  rv = memory2.Delete(test_name);
  EXPECT_TRUE(rv);
}

// Create a set of N threads to each open a shared memory segment and write to
// it. Verify that they are always reading/writing consistent data.
TEST(SharedMemoryTest, MultipleThreads) {
  MultipleThreadMain::CleanUp();
  // On POSIX we have a problem when 2 threads try to create the shmem
  // (a file) at exactly the same time, since create both creates the
  // file and zerofills it.  We solve the problem for this unit test
  // (make it not flaky) by starting with 1 thread, then
  // intentionally don't clean up its shmem before running with
  // kNumThreads.

  int threadcounts[] = { 1, kNumThreads };
  for (size_t i = 0; i < sizeof(threadcounts) / sizeof(threadcounts); i++) {
    int numthreads = threadcounts[i];
    scoped_array<PlatformThreadHandle> thread_handles;
    scoped_array<MultipleThreadMain*> thread_delegates;

    thread_handles.reset(new PlatformThreadHandle[numthreads]);
    thread_delegates.reset(new MultipleThreadMain*[numthreads]);

    // Spawn the threads.
    for (int16 index = 0; index < numthreads; index++) {
      PlatformThreadHandle pth;
      thread_delegates[index] = new MultipleThreadMain(index);
      EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
      thread_handles[index] = pth;
    }

    // Wait for the threads to finish.
    for (int index = 0; index < numthreads; index++) {
      PlatformThread::Join(thread_handles[index]);
      delete thread_delegates[index];
    }
  }
  MultipleThreadMain::CleanUp();
}

// TODO(port): this test requires the MultipleLockThread class
// (defined above), which requires the ability to pass file
// descriptors between processes.  We haven't done that yet in Chrome
// for POSIX.
#if defined(OS_WIN)
// Create a set of threads to each open a shared memory segment and write to it
// with the lock held. Verify that they are always reading/writing consistent
// data.
TEST(SharedMemoryTest, Lock) {
  PlatformThreadHandle thread_handles[kNumThreads];
  MultipleLockThread* thread_delegates[kNumThreads];

  // Spawn the threads.
  for (int index = 0; index < kNumThreads; ++index) {
    PlatformThreadHandle pth;
    thread_delegates[index] = new MultipleLockThread(index);
    EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
    thread_handles[index] = pth;
  }

  // Wait for the threads to finish.
  for (int index = 0; index < kNumThreads; ++index) {
    PlatformThread::Join(thread_handles[index]);
    delete thread_delegates[index];
  }
}
#endif

// Allocate private (unique) shared memory with an empty string for a
// name.  Make sure several of them don't point to the same thing as
// we might expect if the names are equal.
TEST(SharedMemoryTest, AnonymousPrivate) {
  int i, j;
  int count = 4;
  bool rv;
  const int kDataSize = 8192;

  scoped_array<SharedMemory> memories(new SharedMemory[count]);
  scoped_array<int*> pointers(new int*[count]);
  ASSERT_TRUE(memories.get());
  ASSERT_TRUE(pointers.get());

  for (i = 0; i < count; i++) {
    rv = memories[i].Create(L"", false, true, kDataSize);
    EXPECT_TRUE(rv);
    rv = memories[i].Map(kDataSize);
    EXPECT_TRUE(rv);
    int *ptr = static_cast<int*>(memories[i].memory());
    EXPECT_TRUE(ptr);
    pointers[i] = ptr;
  }

  for (i = 0; i < count; i++) {
    // zero out the first int in each except for i; for that one, make it 100.
    for (j = 0; j < count; j++) {
      if (i == j)
        pointers[j][0] = 100;
      else
        pointers[j][0] = 0;
    }
    // make sure there is no bleeding of the 100 into the other pointers
    for (j = 0; j < count; j++) {
      if (i == j)
        EXPECT_EQ(100, pointers[j][0]);
      else
        EXPECT_EQ(0, pointers[j][0]);
    }
  }

  for (int i = 0; i < count; i++) {
    memories[i].Close();
  }

}

// On POSIX it is especially important we test shmem across processes,
// not just across threads.  But the test is enabled on all platforms.
class SharedMemoryProcessTest : public MultiProcessTest {
 public:

  static void CleanUp() {
    SharedMemory memory;
    memory.Delete(s_test_name_);
  }

  static int TaskTestMain() {
    int errors = 0;
    ScopedNSAutoreleasePool pool;  // noop if not OSX
    const int kDataSize = 1024;
    SharedMemory memory;
    bool rv = memory.Create(s_test_name_, false, true, kDataSize);
    EXPECT_TRUE(rv);
    if (rv != true)
      errors++;
    rv = memory.Map(kDataSize);
    EXPECT_TRUE(rv);
    if (rv != true)
      errors++;
    int *ptr = static_cast<int*>(memory.memory());

    for (int idx = 0; idx < 20; idx++) {
      memory.Lock();
      int i = (1 << 16) + idx;
      *ptr = i;
      PlatformThread::Sleep(10);  // Short wait.
      if (*ptr != i)
        errors++;
      memory.Unlock();
    }

    memory.Close();
    return errors;
  }

 private:
  static const wchar_t* const s_test_name_;
};

const const wchar_t* const SharedMemoryProcessTest::s_test_name_ = L"MPMem";

TEST_F(SharedMemoryProcessTest, Tasks) {
  SharedMemoryProcessTest::CleanUp();

  base::ProcessHandle handles[kNumTasks];
  for (int index = 0; index < kNumTasks; ++index) {
    handles[index] = SpawnChild(L"SharedMemoryTestMain");
  }

  int exit_code = 0;
  for (int index = 0; index < kNumTasks; ++index) {
    EXPECT_TRUE(base::WaitForExitCode(handles[index], &exit_code));
    EXPECT_TRUE(exit_code == 0);
  }

  SharedMemoryProcessTest::CleanUp();
}

MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
  return SharedMemoryProcessTest::TaskTestMain();
}

}  // namespace base
<commit_msg>Remove an extra const keyword which caused a build break.<commit_after>// Copyright (c) 2006-2008 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/multiprocess_test.h"
#include "base/platform_thread.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/shared_memory.h"
#include "base/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"

static const int kNumThreads = 5;
static const int kNumTasks = 5;

namespace base {

namespace {

// Each thread will open the shared memory.  Each thread will take a different 4
// byte int pointer, and keep changing it, with some small pauses in between.
// Verify that each thread's value in the shared memory is always correct.
class MultipleThreadMain : public PlatformThread::Delegate {
 public:
  explicit MultipleThreadMain(int16 id) : id_(id) {}
  ~MultipleThreadMain() {}

  static void CleanUp() {
    SharedMemory memory;
    memory.Delete(s_test_name_);
  }

  // PlatformThread::Delegate interface.
  void ThreadMain() {
    ScopedNSAutoreleasePool pool;  // noop if not OSX
    const int kDataSize = 1024;
    SharedMemory memory;
    bool rv = memory.Create(s_test_name_, false, true, kDataSize);
    EXPECT_TRUE(rv);
    rv = memory.Map(kDataSize);
    EXPECT_TRUE(rv);
    int *ptr = static_cast<int*>(memory.memory()) + id_;
    EXPECT_EQ(*ptr, 0);

    for (int idx = 0; idx < 100; idx++) {
      *ptr = idx;
      PlatformThread::Sleep(1);  // Short wait.
      EXPECT_EQ(*ptr, idx);
    }

    memory.Close();
  }

 private:
  int16 id_;

  static const wchar_t* const s_test_name_;

  DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
};

const wchar_t* const MultipleThreadMain::s_test_name_ =
    L"SharedMemoryOpenThreadTest";

// TODO(port):
// This test requires the ability to pass file descriptors between processes.
// We haven't done that yet in Chrome for POSIX.
#if defined(OS_WIN)
// Each thread will open the shared memory.  Each thread will take the memory,
// and keep changing it while trying to lock it, with some small pauses in
// between. Verify that each thread's value in the shared memory is always
// correct.
class MultipleLockThread : public PlatformThread::Delegate {
 public:
  explicit MultipleLockThread(int id) : id_(id) {}
  ~MultipleLockThread() {}

  // PlatformThread::Delegate interface.
  void ThreadMain() {
    const int kDataSize = sizeof(int);
    SharedMemoryHandle handle = NULL;
    {
      SharedMemory memory1;
      EXPECT_TRUE(memory1.Create(L"SharedMemoryMultipleLockThreadTest",
                                 false, true, kDataSize));
      EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
      // TODO(paulg): Implement this once we have a posix version of
      // SharedMemory::ShareToProcess.
      EXPECT_TRUE(true);
    }

    SharedMemory memory2(handle, false);
    EXPECT_TRUE(memory2.Map(kDataSize));
    volatile int* const ptr = static_cast<int*>(memory2.memory());

    for (int idx = 0; idx < 20; idx++) {
      memory2.Lock();
      int i = (id_ << 16) + idx;
      *ptr = i;
      PlatformThread::Sleep(1);  // Short wait.
      EXPECT_EQ(*ptr, i);
      memory2.Unlock();
    }

    memory2.Close();
  }

 private:
  int id_;

  DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
};
#endif

}  // namespace

TEST(SharedMemoryTest, OpenClose) {
  const int kDataSize = 1024;
  std::wstring test_name = L"SharedMemoryOpenCloseTest";

  // Open two handles to a memory segment, confirm that they are mapped
  // separately yet point to the same space.
  SharedMemory memory1;
  bool rv = memory1.Delete(test_name);
  EXPECT_TRUE(rv);
  rv = memory1.Delete(test_name);
  EXPECT_TRUE(rv);
  rv = memory1.Open(test_name, false);
  EXPECT_FALSE(rv);
  rv = memory1.Create(test_name, false, false, kDataSize);
  EXPECT_TRUE(rv);
  rv = memory1.Map(kDataSize);
  EXPECT_TRUE(rv);
  SharedMemory memory2;
  rv = memory2.Open(test_name, false);
  EXPECT_TRUE(rv);
  rv = memory2.Map(kDataSize);
  EXPECT_TRUE(rv);
  EXPECT_NE(memory1.memory(), memory2.memory());  // Compare the pointers.

  // Make sure we don't segfault. (it actually happened!)
  ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
  ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));

  // Write data to the first memory segment, verify contents of second.
  memset(memory1.memory(), '1', kDataSize);
  EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);

  // Close the first memory segment, and verify the second has the right data.
  memory1.Close();
  char *start_ptr = static_cast<char *>(memory2.memory());
  char *end_ptr = start_ptr + kDataSize;
  for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
    EXPECT_EQ(*ptr, '1');

  // Close the second memory segment.
  memory2.Close();

  rv = memory1.Delete(test_name);
  EXPECT_TRUE(rv);
  rv = memory2.Delete(test_name);
  EXPECT_TRUE(rv);
}

// Create a set of N threads to each open a shared memory segment and write to
// it. Verify that they are always reading/writing consistent data.
TEST(SharedMemoryTest, MultipleThreads) {
  MultipleThreadMain::CleanUp();
  // On POSIX we have a problem when 2 threads try to create the shmem
  // (a file) at exactly the same time, since create both creates the
  // file and zerofills it.  We solve the problem for this unit test
  // (make it not flaky) by starting with 1 thread, then
  // intentionally don't clean up its shmem before running with
  // kNumThreads.

  int threadcounts[] = { 1, kNumThreads };
  for (size_t i = 0; i < sizeof(threadcounts) / sizeof(threadcounts); i++) {
    int numthreads = threadcounts[i];
    scoped_array<PlatformThreadHandle> thread_handles;
    scoped_array<MultipleThreadMain*> thread_delegates;

    thread_handles.reset(new PlatformThreadHandle[numthreads]);
    thread_delegates.reset(new MultipleThreadMain*[numthreads]);

    // Spawn the threads.
    for (int16 index = 0; index < numthreads; index++) {
      PlatformThreadHandle pth;
      thread_delegates[index] = new MultipleThreadMain(index);
      EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
      thread_handles[index] = pth;
    }

    // Wait for the threads to finish.
    for (int index = 0; index < numthreads; index++) {
      PlatformThread::Join(thread_handles[index]);
      delete thread_delegates[index];
    }
  }
  MultipleThreadMain::CleanUp();
}

// TODO(port): this test requires the MultipleLockThread class
// (defined above), which requires the ability to pass file
// descriptors between processes.  We haven't done that yet in Chrome
// for POSIX.
#if defined(OS_WIN)
// Create a set of threads to each open a shared memory segment and write to it
// with the lock held. Verify that they are always reading/writing consistent
// data.
TEST(SharedMemoryTest, Lock) {
  PlatformThreadHandle thread_handles[kNumThreads];
  MultipleLockThread* thread_delegates[kNumThreads];

  // Spawn the threads.
  for (int index = 0; index < kNumThreads; ++index) {
    PlatformThreadHandle pth;
    thread_delegates[index] = new MultipleLockThread(index);
    EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
    thread_handles[index] = pth;
  }

  // Wait for the threads to finish.
  for (int index = 0; index < kNumThreads; ++index) {
    PlatformThread::Join(thread_handles[index]);
    delete thread_delegates[index];
  }
}
#endif

// Allocate private (unique) shared memory with an empty string for a
// name.  Make sure several of them don't point to the same thing as
// we might expect if the names are equal.
TEST(SharedMemoryTest, AnonymousPrivate) {
  int i, j;
  int count = 4;
  bool rv;
  const int kDataSize = 8192;

  scoped_array<SharedMemory> memories(new SharedMemory[count]);
  scoped_array<int*> pointers(new int*[count]);
  ASSERT_TRUE(memories.get());
  ASSERT_TRUE(pointers.get());

  for (i = 0; i < count; i++) {
    rv = memories[i].Create(L"", false, true, kDataSize);
    EXPECT_TRUE(rv);
    rv = memories[i].Map(kDataSize);
    EXPECT_TRUE(rv);
    int *ptr = static_cast<int*>(memories[i].memory());
    EXPECT_TRUE(ptr);
    pointers[i] = ptr;
  }

  for (i = 0; i < count; i++) {
    // zero out the first int in each except for i; for that one, make it 100.
    for (j = 0; j < count; j++) {
      if (i == j)
        pointers[j][0] = 100;
      else
        pointers[j][0] = 0;
    }
    // make sure there is no bleeding of the 100 into the other pointers
    for (j = 0; j < count; j++) {
      if (i == j)
        EXPECT_EQ(100, pointers[j][0]);
      else
        EXPECT_EQ(0, pointers[j][0]);
    }
  }

  for (int i = 0; i < count; i++) {
    memories[i].Close();
  }

}

// On POSIX it is especially important we test shmem across processes,
// not just across threads.  But the test is enabled on all platforms.
class SharedMemoryProcessTest : public MultiProcessTest {
 public:

  static void CleanUp() {
    SharedMemory memory;
    memory.Delete(s_test_name_);
  }

  static int TaskTestMain() {
    int errors = 0;
    ScopedNSAutoreleasePool pool;  // noop if not OSX
    const int kDataSize = 1024;
    SharedMemory memory;
    bool rv = memory.Create(s_test_name_, false, true, kDataSize);
    EXPECT_TRUE(rv);
    if (rv != true)
      errors++;
    rv = memory.Map(kDataSize);
    EXPECT_TRUE(rv);
    if (rv != true)
      errors++;
    int *ptr = static_cast<int*>(memory.memory());

    for (int idx = 0; idx < 20; idx++) {
      memory.Lock();
      int i = (1 << 16) + idx;
      *ptr = i;
      PlatformThread::Sleep(10);  // Short wait.
      if (*ptr != i)
        errors++;
      memory.Unlock();
    }

    memory.Close();
    return errors;
  }

 private:
  static const wchar_t* const s_test_name_;
};

const wchar_t* const SharedMemoryProcessTest::s_test_name_ = L"MPMem";

TEST_F(SharedMemoryProcessTest, Tasks) {
  SharedMemoryProcessTest::CleanUp();

  base::ProcessHandle handles[kNumTasks];
  for (int index = 0; index < kNumTasks; ++index) {
    handles[index] = SpawnChild(L"SharedMemoryTestMain");
  }

  int exit_code = 0;
  for (int index = 0; index < kNumTasks; ++index) {
    EXPECT_TRUE(base::WaitForExitCode(handles[index], &exit_code));
    EXPECT_TRUE(exit_code == 0);
  }

  SharedMemoryProcessTest::CleanUp();
}

MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
  return SharedMemoryProcessTest::TaskTestMain();
}

}  // namespace base
<|endoftext|>


<commit_before>#pragma once
//=========================================================================//
/*!	@file
	@brief	SSIE マネージャー @n
			SSIE デバイスを使ったサウンドの再生
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=========================================================================//

namespace sound {

}
<commit_msg>Remove: remove a file<commit_after><|endoftext|>


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

#include "defragmenter_visitor.h"
#include "tests/module_tests/defragmenter_test.h"
#include "tests/module_tests/test_helpers.h"
#include "vbucket.h"

#include <gtest/gtest.h>
#include <valgrind/valgrind.h>

/* Measure the rate at which the defragmenter can defragment documents, using
 * the given age threshold.
 *
 * Setup a Defragmenter, then time how long it takes to visit them all
 * documents in the given vbucket, npasses times.
 */
static size_t benchmarkDefragment(VBucket& vbucket, size_t passes,
                                  uint8_t age_threshold,
                                  std::chrono::milliseconds chunk_duration) {
    // Create and run visitor for the specified number of iterations, with
    // the given age.
    DefragmentVisitor visitor(age_threshold);
    auto start = ProcessClock::now();
    for (size_t i = 0; i < passes; i++) {
        // Loop until we get to the end; this may take multiple chunks depending
        // on the chunk_duration.
        HashTable::Position pos;
        while (pos != vbucket.ht.endPosition()) {
            visitor.setDeadline(ProcessClock::now() + chunk_duration);
            pos = vbucket.ht.pauseResumeVisit(visitor, pos);
        }
    }
    auto end = ProcessClock::now();
    size_t visited = visitor.getVisitedCount();

    std::chrono::duration<double> duration = (end - start);
    return size_t(visited / duration.count());
}

class DefragmenterBenchmarkTest : public DefragmenterTest {
protected:
    /* Fill the bucket with the given number of docs. Returns the rate at which
     * items were added.
     */
    size_t populateVbucket() {
        // How many items to create in the VBucket. Use a large number for
        // normal runs when measuring performance, but a very small number
        // (enough for functional testing) when running under Valgrind
        // where there's no sense in measuring performance.
        const size_t ndocs = RUNNING_ON_VALGRIND ? 10 : 500000;

        /* Set the hashTable to a sensible size */
        vbucket->ht.resize(ndocs);

        /* Store items */
        char value[256];
        auto start = ProcessClock::now();
        for (size_t i = 0; i < ndocs; i++) {
            std::string key = "key" + std::to_string(i);
            Item item(makeStoredDocKey(key), 0, 0, value, sizeof(value));
            public_processSet(item, 0);
        }
        auto end = ProcessClock::now();

        // Let hashTable set itself to correct size, post-fill
        vbucket->ht.resize();

        std::chrono::duration<double> duration = (end - start);
        return size_t(ndocs / duration.count());
    }

};

TEST_P(DefragmenterBenchmarkTest, Populate) {
    size_t populateRate = populateVbucket();
    RecordProperty("items_per_sec", populateRate);
}

TEST_P(DefragmenterBenchmarkTest, Visit) {
    populateVbucket();
    size_t visit_rate = benchmarkDefragment(*vbucket, 1,
                                            std::numeric_limits<uint8_t>::max(),
                                            std::chrono::minutes(1));
    RecordProperty("items_per_sec", visit_rate);
}

TEST_P(DefragmenterBenchmarkTest, DefragAlways) {
    populateVbucket();
    size_t defrag_always_rate = benchmarkDefragment(*vbucket, 1, 0,
                                                    std::chrono::minutes(1));
    RecordProperty("items_per_sec", defrag_always_rate);
}

TEST_P(DefragmenterBenchmarkTest, DefragAge10) {
    populateVbucket();
    size_t defrag_age10_rate = benchmarkDefragment(*vbucket, 1, 10,
                                                   std::chrono::minutes(1));
    RecordProperty("items_per_sec", defrag_age10_rate);
}

TEST_P(DefragmenterBenchmarkTest, DefragAge10_20ms) {
    populateVbucket();
    size_t defrag_age10_20ms_rate =
            benchmarkDefragment(*vbucket, 1, 10, std::chrono::milliseconds(20));
    RecordProperty("items_per_sec", defrag_age10_20ms_rate);
}

INSTANTIATE_TEST_CASE_P(
        FullAndValueEviction,
        DefragmenterBenchmarkTest,
        ::testing::Values(VALUE_ONLY, FULL_EVICTION),
        [](const ::testing::TestParamInfo<item_eviction_policy_t>& info) {
            if (info.param == VALUE_ONLY) {
                return "VALUE_ONLY";
            } else {
                return "FULL_EVICTION";
            }
        });
<commit_msg>MB-24765: Migrate Defragmenter benchmarks to Google Benchmark<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2017 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include "defragmenter_visitor.h"
#include "ep_vb.h"
#include "failover-table.h"
#include "tests/module_tests/defragmenter_test.h"
#include "tests/module_tests/test_helpers.h"

#include <benchmark/benchmark.h>
#include <gtest/gtest.h>
#include <valgrind/valgrind.h>

class DefragmentBench : public benchmark::Fixture {
public:
    void SetUp(::benchmark::State& state) {
        // The first parameter specifies the eviction mode:
        item_eviction_policy_t evictionPolicy;
        switch (state.range(0)) {
        case 0:
            state.SetLabel("ValueOnly");
            evictionPolicy = VALUE_ONLY;
            break;
        case 1:
            state.SetLabel("FullEviction");
            evictionPolicy = FULL_EVICTION;
            break;
        default:
            FAIL() << "Invalid input param(0) value:" << state.range(0);
        }
        vbucket.reset(new EPVBucket(0,
                                    vbucket_state_active,
                                    globalStats,
                                    checkpointConfig,
                                    /*kvshard*/ nullptr,
                                    /*lastSeqno*/ 1000,
                                    /*lastSnapStart*/ 0,
                                    /*lastSnapEnd*/ 0,
                                    /*table*/ nullptr,
                                    std::make_shared<DummyCB>(),
                                    /*newSeqnoCb*/ nullptr,
                                    config,
                                    evictionPolicy));

        populateVbucket();
    }

    void TearDown(const ::benchmark::State& state) {
        vbucket.reset();
    }

protected:
    /* Fill the bucket with the given number of docs.
     */
    void populateVbucket() {
        // How many items to create in the VBucket. Use a large number for
        // normal runs when measuring performance (ideally we want to exceed
        // the D$ as that's how we'd expect to run in production), but a very
        // small number (enough for functional testing) when running under
        // Valgrind where there's no sense in measuring performance.
        const size_t ndocs = RUNNING_ON_VALGRIND ? 10 : 500000;

        /* Set the hashTable to a sensible size */
        vbucket->ht.resize(ndocs);

        /* Store items */
        char value[256];
        for (size_t i = 0; i < ndocs; i++) {
            std::string key = "key" + std::to_string(i);
            Item item(makeStoredDocKey(key), 0, 0, value, sizeof(value));
            ASSERT_EQ(MutationStatus::WasClean, vbucket->ht.set(item));
        }

        ASSERT_EQ(ndocs, vbucket->ht.getNumItems());
    }

    /* Measure the rate at which the defragmenter can defragment documents, using
     * the given age threshold.
     *
     * Setup a Defragmenter, then time how long it takes to visit them all
     * documents in the given vbucket, 10 passes times.
     * @return a pair of {items visited, duration}.
     */
    std::pair<size_t, std::chrono::nanoseconds> benchmarkDefragment(
            uint8_t age_threshold,
            std::chrono::milliseconds chunk_duration) {
        // Create and run visitor for the specified number of iterations, with
        // the given age.
        DefragmentVisitor visitor(age_threshold);
        // Need to run 10 passes; so we allow the deframenter to defrag at
        // least once (given the age_threshold may be up to 10).
        const size_t passes = 10;

        auto start = ProcessClock::now();
        for (size_t i = 0; i < passes; i++) {
            // Loop until we get to the end; this may take multiple chunks
            // depending
            // on the chunk_duration.
            HashTable::Position pos;
            while (pos != vbucket->ht.endPosition()) {
                visitor.setDeadline(ProcessClock::now() + chunk_duration);
                pos = vbucket->ht.pauseResumeVisit(visitor, pos);
            }
        }
        auto end = ProcessClock::now();
        auto duration = (end - start);

        return {visitor.getVisitedCount(), duration};
    }

    std::unique_ptr<VBucket> vbucket;
    EPStats globalStats;
    CheckpointConfig checkpointConfig;
    Configuration config;
};

BENCHMARK_DEFINE_F(DefragmentBench, Visit)(benchmark::State& state) {
    std::pair<size_t, std::chrono::nanoseconds> total;
    while (state.KeepRunning()) {
        auto result = benchmarkDefragment(std::numeric_limits<uint8_t>::max(),
                                          std::chrono::minutes(1));
        total.first += result.first;
        total.second += result.second;
    }
    state.counters["ItemsPerSec"] =
            total.first / std::chrono::duration<double>(total.second).count();
}

BENCHMARK_DEFINE_F(DefragmentBench, DefragAlways)(benchmark::State& state) {
    std::pair<size_t, std::chrono::nanoseconds> total;
    while (state.KeepRunning()) {
        auto result = benchmarkDefragment(0, std::chrono::minutes(1));
        total.first += result.first;
        total.second += result.second;
    }
    state.counters["ItemsPerSec"] =
            total.first / std::chrono::duration<double>(total.second).count();
}

BENCHMARK_DEFINE_F(DefragmentBench, DefragAge10)(benchmark::State& state) {
    std::pair<size_t, std::chrono::nanoseconds> total;
    while (state.KeepRunning()) {
        auto result = benchmarkDefragment(10, std::chrono::minutes(1));
        total.first += result.first;
        total.second += result.second;
    }
    state.counters["ItemsPerSec"] =
            total.first / std::chrono::duration<double>(total.second).count();
}

BENCHMARK_DEFINE_F(DefragmentBench, DefragAge10_20ms)(benchmark::State& state) {
    std::pair<size_t, std::chrono::nanoseconds> total;
    while (state.KeepRunning()) {
        auto result = benchmarkDefragment(10, std::chrono::milliseconds(20));
        total.first += result.first;
        total.second += result.second;
    }
    state.counters["ItemsPerSec"] =
            total.first / std::chrono::duration<double>(total.second).count();
}

BENCHMARK_REGISTER_F(DefragmentBench, Visit)->Range(0,1);
BENCHMARK_REGISTER_F(DefragmentBench, DefragAlways)->Range(0,1);
BENCHMARK_REGISTER_F(DefragmentBench, DefragAge10)->Range(0,1);
BENCHMARK_REGISTER_F(DefragmentBench, DefragAge10_20ms)->Range(0,1);

<|endoftext|>


<commit_before>#include <stdio.h>
#include <string>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>

#include "overlapgraph.h"

using namespace std;

std::string path;
std::vector<std::string> reads;
std::vector<overlap> overlaps;

std::vector<std::string> split(std::string input, char splitChar)
{
	std::vector<std::string> substrings;
	std::string::iterator it;
	std::string s = "";
	for (it = input.begin(); it<input.end(); it++)
	{
		if (*it == splitChar)
		{
			substrings.push_back(s);
			s = "";
		}
		else
			s += *it;
	}
	substrings.push_back(s);
	return substrings;
}

void loadReads()
{
	ifstream readsMap(path + "\\reads.bnk\\RED.0.map");
	ifstream readsMap2(path + "\\reads.2k.10x.fasta");

	map<string, int> readMap;
	for (string line; getline(readsMap, line);)
	{
		if (line.substr(0, 3) == "RED")
			continue;

		vector<string> tokens = split(line, '\t');
		pair <string, int> p(tokens[2], stoi(tokens[0]));
		readMap.insert(p);
	}

	int no = 0;
	string read;
	for (string line; getline(readsMap2, line);)
	{

		if (line.substr(0, 1) == ">"){
			no = readMap[line.substr(1)];
			continue;
		}
		else
		{
			reads.push_back(line);
		}
	}
}

void loadoverlaps()
{
	std::string overlapsfile = path + "\\overlaps.afg";

	std::ifstream overlapinput(overlapsfile.c_str());
	overlap *o = NULL;
	string line;
	for (string line; getline(overlapinput, line);)
	{
		if (line[0] == '{')
			o = (overlap *)malloc(sizeof(overlap));
		else if (line.substr(0, 3) == "adj")
			o->orientation = line[4];
		else if (line.substr(0, 3) == "rds")
		{
			string s = line.substr(4);
			vector<string> reads = split(s, ',');
			o->read1 = stoi(reads[0]) - 1;
			o->read2 = stoi(reads[1]) - 1;
		}
		else if (line.substr(0, 3) == "ahg")
		{
			o->ahg = stoi(line.substr(4));
		}
		else if (line.substr(0, 3) == "bhg")
		{
			o->bhg = stoi(line.substr(4));
		}
		else if (line[0] == '}')
		{
			overlaps.push_back(*o);
		}
	}
}

int main(int argc, char *argv[])
{
	path = argv[1];

	loadReads();
	loadoverlaps();

	OverlapGraph overlapGraph(reads, overlaps);
	overlapGraph.runUnitigging();

	overlapGraph.printLayouts();
}
<commit_msg>changed backslash with slash for linux<commit_after>#include <stdio.h>
#include <string>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>

#include "overlapgraph.h"

using namespace std;

std::string path;
std::vector<std::string> reads;
std::vector<overlap> overlaps;

std::vector<std::string> split(std::string input, char splitChar)
{
	std::vector<std::string> substrings;
	std::string::iterator it;
	std::string s = "";
	for (it = input.begin(); it<input.end(); it++)
	{
		if (*it == splitChar)
		{
			substrings.push_back(s);
			s = "";
		}
		else
			s += *it;
	}
	substrings.push_back(s);
	return substrings;
}

void loadReads()
{
	ifstream readsMap(path + "/reads.bnk/RED.0.map");
	ifstream readsMap2(path + "/reads.2k.10x.fasta");

	map<string, int> readMap;
	for (string line; getline(readsMap, line);)
	{
		if (line.substr(0, 3) == "RED")
			continue;

		vector<string> tokens = split(line, '\t');
		pair <string, int> p(tokens[2], stoi(tokens[0]));
		readMap.insert(p);
	}

	int no = 0;
	string read;
	for (string line; getline(readsMap2, line);)
	{

		if (line.substr(0, 1) == ">"){
			no = readMap[line.substr(1)];
			continue;
		}
		else
		{
			reads.push_back(line);
		}
	}
}

void loadoverlaps()
{
	std::string overlapsfile = path + "/overlaps.afg";

	std::ifstream overlapinput(overlapsfile.c_str());
	overlap *o = NULL;
	string line;
	for (string line; getline(overlapinput, line);)
	{
		if (line[0] == '{')
			o = (overlap *)malloc(sizeof(overlap));
		else if (line.substr(0, 3) == "adj")
			o->orientation = line[4];
		else if (line.substr(0, 3) == "rds")
		{
			string s = line.substr(4);
			vector<string> reads = split(s, ',');
			o->read1 = stoi(reads[0]) - 1;
			o->read2 = stoi(reads[1]) - 1;
		}
		else if (line.substr(0, 3) == "ahg")
		{
			o->ahg = stoi(line.substr(4));
		}
		else if (line.substr(0, 3) == "bhg")
		{
			o->bhg = stoi(line.substr(4));
		}
		else if (line[0] == '}')
		{
			overlaps.push_back(*o);
		}
	}
}

int main(int argc, char *argv[])
{
	path = argv[1];

	loadReads();
	loadoverlaps();

	OverlapGraph overlapGraph(reads, overlaps);
	overlapGraph.runUnitigging();

	overlapGraph.printLayouts();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2015 John Connor (BM-NC49AxAjcqVcF5jNPu85Rb8MJ2d9JqZt)
 *
 * This file is part of vanillacoin.
 *
 * vanillacoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <coin/chainblender.hpp>

using namespace coin;

std::mutex chainblender::mutex_;

chainblender::chainblender()
{
    // ...
}

chainblender & chainblender::instance()
{
    static chainblender g_chainblender;

    std::lock_guard<std::mutex> l1(mutex_);

    return g_chainblender;
}
<commit_msg>chainblender partial merge<commit_after>/*
 * Copyright (c) 2013-2015 John Connor (BM-NC49AxAjcqVcF5jNPu85Rb8MJ2d9JqZt)
 *
 * This file is part of vanillacoin.
 *
 * vanillacoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <coin/chainblender.hpp>
#include <coin/constants.hpp>
#include <coin/globals.hpp>
#include <coin/utility.hpp>

using namespace coin;

std::mutex chainblender::mutex_;

chainblender::chainblender()
{
    // ...
}

chainblender & chainblender::instance()
{
    static chainblender g_chainblender;

    std::lock_guard<std::mutex> l1(mutex_);

    return g_chainblender;
}

std::set<std::int64_t> chainblender::denominations()
{
    return
    {
        static_cast<std::int64_t> (500.0 * constants::coin) + 500000,
        static_cast<std::int64_t> (50.0 * constants::coin) + 50000,
        static_cast<std::int64_t> (5.0 * constants::coin) + 5000,
        static_cast<std::int64_t> (0.5 * constants::coin) + 500,
        static_cast<std::int64_t> (globals::instance().transaction_fee()) + 0,
    };
}

std::int16_t chainblender::calculate_score(
    const boost::asio::ip::tcp::endpoint & ep
    )
{
	std::int16_t ret = -1;

    auto index = utility::find_block_index_by_height(
        globals::instance().best_block_height()
    );

    if (index)
    {
        const auto & hash_block = index->get_block_hash();

        /**
         * Get the node endpoint.
         */
        auto node_ep =
            ep.address().to_string() + ":" + std::to_string(ep.port())
        ;

        /**
         * Hash the endpoint.
         */
        auto digest1 = hash::sha256d(
            reinterpret_cast<const std::uint8_t *>(node_ep.data()),
            node_ep.size()
        );

        /**
         * Hash the hash of the block.
         */
        auto digest2 = hash::sha256d(
            hash_block.digest(), sha256::digest_length
        );

        auto hash2 = sha256::from_digest(&digest2[0]);

        auto digest3 = hash::sha256d(
            &digest2[0], &digest2[0] + digest2.size(),
            &digest1[0], &digest1[0] + digest1.size()
        );

        auto hash3 = sha256::from_digest(&digest3[0]);

        if (hash3 > hash2)
        {
            ret =
                static_cast<std::int16_t> (
                (hash3 - hash2).to_uint64())
            ;
        }
        else
        {
            ret =
                static_cast<std::int16_t> (
                (hash2 - hash3).to_uint64())
            ;
        }
    }

    return ret;
}

std::map<sha256, chainblender::session_t> & chainblender::sessions()
{
    return m_sessions;
}
<|endoftext|>


<commit_before>#ifndef K3_RUNTIME_BUILTINS_H
#define K3_RUNTIME_BUILTINS_H

#include <ctime>
#include <chrono>
#include <climits>
#include <fstream>
#include <sstream>
#include <string>
#include <functional>

#include "BaseTypes.hpp"

namespace K3 {
  //class Builtins: public __k3_context {
  //  public:

  //    Builtins() {
  //      // seed the random number generator
  //      std::srand(std::time(0));
  //    }

  //    int random(int x) { return std::rand(x); }

  //    double randomFraction(unit_t) { return (double)rand() / RAND_MAX; }

  //    <template t>
  //      int hash(t x) { return static_cast<int>std::hash<t>(x); }

  //    int truncate(double x) { return (int)x; }

  //    double real_of_int(int x) { return (double)x; }

  //    int get_max_int(unit_t x) { return INT_MAX; }
  //};

  F<F<F<unit_t(string)>(string)>(string)> openBuiltin =
    [] (string chan_id) {
      return [=] (string builtin_chan_id) {
        return [=] (string format) {
          engine.openBuiltin(chan_id, builtin_chan_id);
          return unit_t();
        };
      };
    };

  F<F<F<F<unit_t(string)>(string)>(string)>(string)> openFile =
    [] (string chan_id) {
      return [=] (string path) {
          return [=] (string fmt) {
              return [=] (string mode) {
                  IOMode iomode = engine.ioMode(mode);
                  engine.openFile(chan_id, path, iomode);
                  return unit_t();
              };
          };
      };
  };

  unit_t close(string chan_id) {
      engine.close(chan_id);
      return unit_t();
  }

  unit_t printLine(string message) {
    std::cout << message << endl;
    return unit_t();
  }

  string itos(int i) {
    return to_string(i);
  }

  string rtos(double d) {
    return to_string(d);
  }

  unit_t haltEngine(unit_t) {
    engine.forceTerminateEngine();
    return unit_t();
  }

  F<F<F<string(int)>(int)>(string)> substring = [] (string& s) {
      return [&] (int& i) {
            return [&] (int& n) {
                return s.substr(i,n);
            };
      };
  };

  F<F<Collection<R_elem<double>>(const Collection<R_elem<double>>&)>(const Collection<R_elem<double>>&)> vector_add =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();

        Collection<R_elem<double>> result = Collection<R_elem<double>>(nullptr);

        for (auto i = 0; i < v1.size(); ++i) {
          cout << "I is" << i << endl;
          cout << "v1:" << v1[i].elem << endl;
          cout << "v2:" << v2[i].elem << endl;
          double d = v1[i].elem + v2[i].elem;
          cout << "d:" << d << endl;
          R_elem<double> r;
          r.elem = d;
          result.insert(r);
        }

        return result;
      };

  };

  F<F<Collection<R_elem<double>>(const Collection<R_elem<double>>&)>(const Collection<R_elem<double>>&)> vector_sub =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();
        Collection<R_elem<double>> result = Collection<R_elem<double>>(nullptr);
        for (auto i = 0; i < v1.size(); ++i) {
          double d = v1[i].elem + v2[i].elem;
          R_elem<double> r;
          r.elem = d;
          result.insert(r);
        }

        return result;
      };

  };

  F<F<double(const Collection<R_elem<double>>&)>(const Collection<R_elem<double>>&)> dot =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        double ans = 0;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();
        for (auto i = 0; i < v1.size(); ++i) {
          double d = v1[i].elem * v2[i].elem;
          ans += d;
        }

        return ans;
      };

  };

  F<F<double(const Collection<R_elem<double>>)>(const Collection<R_elem<double>>&)> squared_distance =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        double ans = 0;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();
        for (auto i = 0; i < v1.size(); ++i) {
          double d = v1[i].elem - v2[i].elem;
          ans += d * d;
        }

        return ans;
      };

  };

  Collection<R_elem<double>> zero_vector(int n) {
    Collection<R_elem<double>> c = Collection<R_elem<double>>(nullptr);
    for (auto i = 0; i < n; ++i) {
      R_elem<double> rec;
      rec.elem = 0.0;
      c.insert(rec);
    }
    return c;
  }

  F<F<Collection<R_elem<double>>(const Collection<R_elem<double>>&)>(const double&)> scalar_mult =
    [] (const double& d) {
      return [&] (const Collection<R_elem<double>>& c) {
        using namespace K3;
        vector<R_elem<double>> v1 = c.getContainer();
        Collection<R_elem<double>> result = Collection<R_elem<double>>(nullptr);
        for (auto i = 0; i < v1.size(); ++i) {
          cout << "d is :" << d << endl;
          cout << "elem: " << v1[i].elem << endl;
          double d2 = d * v1[i].elem;
          R_elem<double> r;
          r.elem = d2;
          result.insert(r);
        }

        return result;
      };

  };

  // ms
  int now(unit_t) {
    auto t = std::chrono::system_clock::now();
    auto elapsed =std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch());
    return elapsed.count();
  }

  // Map-specific template function to look up
  template <class E>
  F<shared_ptr<typename E::ValueType>(const typename E::KeyType&)> lookup(const Map<E>& map) {
    return [&] (const typename E::KeyType& key) -> shared_ptr<typename E::ValueType> {
      auto container = map.getContainer();
      auto it = container.find(key);
      if (it != container.end()) {
        return make_shared<typename E::ValueType>(it->second);
      } else {
        return nullptr;
      }
    };
  }

  template <class E>
  F<F<F<unit_t(F<typename E::ValueType(const typename E::ValueType&)>)>(const typename E::ValueType&)>(const typename E::KeyType&)>
  insert_with(const Map<E>& map) {
    return [&] (const typename E::KeyType& key) {
      return [&] (const typename E::ValueType& value) {
        return [&] (std::function<typename E::ValueType(const typename E::ValueType&)> f) {
          auto it = map.getContainer().find(key);
          if (it == map.end()) {
            map.insert(E(key, value));
          } else {
            map.insert(E(key, f(value)));
          }

          return unit_t();
        };
      };
    };
  }
} // namespace K3

#endif /* K3_RUNTIME_BUILTINS_H */
<commit_msg>builtins: fix for substring<commit_after>#ifndef K3_RUNTIME_BUILTINS_H
#define K3_RUNTIME_BUILTINS_H

#include <ctime>
#include <chrono>
#include <climits>
#include <fstream>
#include <sstream>
#include <string>
#include <functional>

#include "BaseTypes.hpp"

namespace K3 {
  //class Builtins: public __k3_context {
  //  public:

  //    Builtins() {
  //      // seed the random number generator
  //      std::srand(std::time(0));
  //    }

  //    int random(int x) { return std::rand(x); }

  //    double randomFraction(unit_t) { return (double)rand() / RAND_MAX; }

  //    <template t>
  //      int hash(t x) { return static_cast<int>std::hash<t>(x); }

  //    int truncate(double x) { return (int)x; }

  //    double real_of_int(int x) { return (double)x; }

  //    int get_max_int(unit_t x) { return INT_MAX; }
  //};

  F<F<F<unit_t(string)>(string)>(string)> openBuiltin =
    [] (string chan_id) {
      return [=] (string builtin_chan_id) {
        return [=] (string format) {
          engine.openBuiltin(chan_id, builtin_chan_id);
          return unit_t();
        };
      };
    };

  F<F<F<F<unit_t(string)>(string)>(string)>(string)> openFile =
    [] (string chan_id) {
      return [=] (string path) {
          return [=] (string fmt) {
              return [=] (string mode) {
                  IOMode iomode = engine.ioMode(mode);
                  engine.openFile(chan_id, path, iomode);
                  return unit_t();
              };
          };
      };
  };

  unit_t close(string chan_id) {
      engine.close(chan_id);
      return unit_t();
  }

  unit_t printLine(string message) {
    std::cout << message << endl;
    return unit_t();
  }

  string itos(int i) {
    return to_string(i);
  }

  string rtos(double d) {
    return to_string(d);
  }

  unit_t haltEngine(unit_t) {
    engine.forceTerminateEngine();
    return unit_t();
  }

  F<F<F<string(const int&)>(const int&)>(const string&)> substring = [] (const string& s) {
      return [&] (const int& i) {
            return [&] (const int& n) {
                return s.substr(i,n);
            };
      };
  };

  F<F<Collection<R_elem<double>>(const Collection<R_elem<double>>&)>(const Collection<R_elem<double>>&)> vector_add =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();

        Collection<R_elem<double>> result = Collection<R_elem<double>>(nullptr);

        for (auto i = 0; i < v1.size(); ++i) {
          cout << "I is" << i << endl;
          cout << "v1:" << v1[i].elem << endl;
          cout << "v2:" << v2[i].elem << endl;
          double d = v1[i].elem + v2[i].elem;
          cout << "d:" << d << endl;
          R_elem<double> r;
          r.elem = d;
          result.insert(r);
        }

        return result;
      };

  };

  F<F<Collection<R_elem<double>>(const Collection<R_elem<double>>&)>(const Collection<R_elem<double>>&)> vector_sub =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();
        Collection<R_elem<double>> result = Collection<R_elem<double>>(nullptr);
        for (auto i = 0; i < v1.size(); ++i) {
          double d = v1[i].elem + v2[i].elem;
          R_elem<double> r;
          r.elem = d;
          result.insert(r);
        }

        return result;
      };

  };

  F<F<double(const Collection<R_elem<double>>&)>(const Collection<R_elem<double>>&)> dot =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        double ans = 0;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();
        for (auto i = 0; i < v1.size(); ++i) {
          double d = v1[i].elem * v2[i].elem;
          ans += d;
        }

        return ans;
      };

  };

  F<F<double(const Collection<R_elem<double>>)>(const Collection<R_elem<double>>&)> squared_distance =
    [] (const Collection<R_elem<double>>& c1) {
      return [&] (const Collection<R_elem<double>>& c2) {
        using namespace K3;
        double ans = 0;
        vector<R_elem<double>> v1 = c1.getContainer();
        vector<R_elem<double>> v2 = c2.getContainer();
        for (auto i = 0; i < v1.size(); ++i) {
          double d = v1[i].elem - v2[i].elem;
          ans += d * d;
        }

        return ans;
      };

  };

  Collection<R_elem<double>> zero_vector(int n) {
    Collection<R_elem<double>> c = Collection<R_elem<double>>(nullptr);
    for (auto i = 0; i < n; ++i) {
      R_elem<double> rec;
      rec.elem = 0.0;
      c.insert(rec);
    }
    return c;
  }

  F<F<Collection<R_elem<double>>(const Collection<R_elem<double>>&)>(const double&)> scalar_mult =
    [] (const double& d) {
      return [&] (const Collection<R_elem<double>>& c) {
        using namespace K3;
        vector<R_elem<double>> v1 = c.getContainer();
        Collection<R_elem<double>> result = Collection<R_elem<double>>(nullptr);
        for (auto i = 0; i < v1.size(); ++i) {
          cout << "d is :" << d << endl;
          cout << "elem: " << v1[i].elem << endl;
          double d2 = d * v1[i].elem;
          R_elem<double> r;
          r.elem = d2;
          result.insert(r);
        }

        return result;
      };

  };

  // ms
  int now(unit_t) {
    auto t = std::chrono::system_clock::now();
    auto elapsed =std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch());
    return elapsed.count();
  }

  // Map-specific template function to look up
  template <class E>
  F<shared_ptr<typename E::ValueType>(const typename E::KeyType&)> lookup(const Map<E>& map) {
    return [&] (const typename E::KeyType& key) -> shared_ptr<typename E::ValueType> {
      auto container = map.getContainer();
      auto it = container.find(key);
      if (it != container.end()) {
        return make_shared<typename E::ValueType>(it->second);
      } else {
        return nullptr;
      }
    };
  }

  template <class E>
  F<F<F<unit_t(F<typename E::ValueType(const typename E::ValueType&)>)>(const typename E::ValueType&)>(const typename E::KeyType&)>
  insert_with(const Map<E>& map) {
    return [&] (const typename E::KeyType& key) {
      return [&] (const typename E::ValueType& value) {
        return [&] (std::function<typename E::ValueType(const typename E::ValueType&)> f) {
          auto it = map.getContainer().find(key);
          if (it == map.end()) {
            map.insert(E(key, value));
          } else {
            map.insert(E(key, f(value)));
          }

          return unit_t();
        };
      };
    };
  }
} // namespace K3

#endif /* K3_RUNTIME_BUILTINS_H */
<|endoftext|>


<commit_before>//===-- hwasan_report.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of HWAddressSanitizer.
//
// Error reporting.
//===----------------------------------------------------------------------===//

#include "hwasan.h"
#include "hwasan_allocator.h"
#include "hwasan_mapping.h"
#include "hwasan_thread.h"
#include "hwasan_thread_list.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_symbolizer.h"

using namespace __sanitizer;

namespace __hwasan {

static StackTrace GetStackTraceFromId(u32 id) {
  CHECK(id);
  StackTrace res = StackDepotGet(id);
  CHECK(res.trace);
  return res;
}

// A RAII object that holds a copy of the current thread stack ring buffer.
// The actual stack buffer may change while we are iterating over it (for
// example, Printf may call syslog() which can itself be built with hwasan).
class SavedStackAllocations {
 public:
  SavedStackAllocations(StackAllocationsRingBuffer *rb) {
    uptr size = rb->size() * sizeof(uptr);
    void *storage =
        MmapAlignedOrDieOnFatalError(size, size * 2, "saved stack allocations");
    new (&rb_) StackAllocationsRingBuffer(*rb, storage);
  }

  ~SavedStackAllocations() {
    StackAllocationsRingBuffer *rb = get();
    UnmapOrDie(rb->StartOfStorage(), rb->size() * sizeof(uptr));
  }

  StackAllocationsRingBuffer *get() {
    return (StackAllocationsRingBuffer *)&rb_;
  }

 private:
  uptr rb_;
};

class Decorator: public __sanitizer::SanitizerCommonDecorator {
 public:
  Decorator() : SanitizerCommonDecorator() { }
  const char *Access() { return Blue(); }
  const char *Allocation() const { return Magenta(); }
  const char *Origin() const { return Magenta(); }
  const char *Name() const { return Green(); }
  const char *Location() { return Green(); }
  const char *Thread() { return Green(); }
};

// Returns the index of the rb element that matches tagged_addr (plus one),
// or zero if found nothing.
uptr FindHeapAllocation(HeapAllocationsRingBuffer *rb,
                        uptr tagged_addr,
                        HeapAllocationRecord *har) {
  if (!rb) return 0;
  for (uptr i = 0, size = rb->size(); i < size; i++) {
    auto h = (*rb)[i];
    if (h.tagged_addr <= tagged_addr &&
        h.tagged_addr + h.requested_size > tagged_addr) {
      *har = h;
      return i + 1;
    }
  }
  return 0;
}

void PrintAddressDescription(
    uptr tagged_addr, uptr access_size,
    StackAllocationsRingBuffer *current_stack_allocations) {
  Decorator d;
  int num_descriptions_printed = 0;
  uptr untagged_addr = UntagAddr(tagged_addr);
  // Check if this looks like a heap buffer overflow by scanning
  // the shadow left and right and looking for the first adjacent
  // object with a different memory tag. If that tag matches addr_tag,
  // check the allocator if it has a live chunk there.
  tag_t addr_tag = GetTagFromPointer(tagged_addr);
  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
  if (*tag_ptr != addr_tag) { // should be true usually.
    tag_t *left = tag_ptr, *right = tag_ptr;
    // scan left.
    for (int i = 0; i < 1000 && *left == *tag_ptr; i++, left--){}
    // scan right.
    for (int i = 0; i < 1000 && *right == *tag_ptr; i++, right++){}
    // Chose the object that has addr_tag and that is closer to addr.
    tag_t *candidate = nullptr;
    if (*right == addr_tag && *left == addr_tag)
      candidate = right - tag_ptr < tag_ptr - left ? right : left;
    else if (*right == addr_tag)
      candidate = right;
    else if (*left == addr_tag)
      candidate = left;

    if (candidate) {
      uptr mem = ShadowToMem(reinterpret_cast<uptr>(candidate));
      HwasanChunkView chunk = FindHeapChunkByAddress(mem);
      if (chunk.IsAllocated()) {
        Printf("%s", d.Location());
        Printf(
            "%p is located %zd bytes to the %s of %zd-byte region [%p,%p)\n",
            untagged_addr,
            candidate == left ? untagged_addr - chunk.End()
            : chunk.Beg() - untagged_addr,
            candidate == right ? "left" : "right", chunk.UsedSize(),
            chunk.Beg(), chunk.End());
        Printf("%s", d.Allocation());
        Printf("allocated here:\n");
        Printf("%s", d.Default());
        GetStackTraceFromId(chunk.GetAllocStackId()).Print();
        num_descriptions_printed++;
      }
    }
  }

  hwasanThreadList().VisitAllLiveThreads([&](Thread *t) {
    // Scan all threads' ring buffers to find if it's a heap-use-after-free.
    HeapAllocationRecord har;
    if (uptr D = FindHeapAllocation(t->heap_allocations(), tagged_addr, &har)) {
      Printf("%s", d.Location());
      Printf("%p is located %zd bytes inside of %zd-byte region [%p,%p)\n",
             untagged_addr, untagged_addr - UntagAddr(har.tagged_addr),
             har.requested_size, UntagAddr(har.tagged_addr),
             UntagAddr(har.tagged_addr) + har.requested_size);
      Printf("%s", d.Allocation());
      Printf("freed by thread T%zd here:\n", t->unique_id());
      Printf("%s", d.Default());
      GetStackTraceFromId(har.free_context_id).Print();

      Printf("%s", d.Allocation());
      Printf("previously allocated here:\n", t);
      Printf("%s", d.Default());
      GetStackTraceFromId(har.alloc_context_id).Print();
      t->Announce();

      // Print a developer note: the index of this heap object
      // in the thread's deallocation ring buffer.
      Printf("hwasan_dev_note_heap_rb_distance: %zd %zd\n", D,
             flags()->heap_history_size);

      num_descriptions_printed++;
    }

    // Very basic check for stack memory.
    if (t->AddrIsInStack(untagged_addr)) {
      Printf("%s", d.Location());
      Printf("Address %p is located in stack of thread T%zd\n", untagged_addr,
             t->unique_id());
      Printf("%s", d.Default());
      t->Announce();

      // Temporary report section, needs to be improved.
      Printf("Previosly allocated frames:\n");
      auto *sa = (t == GetCurrentThread() && current_stack_allocations)
                     ? current_stack_allocations
                     : t->stack_allocations();
      uptr frames = Min((uptr)flags()->stack_history_size, sa->size());
      for (uptr i = 0; i < frames; i++) {
        uptr record = (*sa)[i];
        if (!record)
          break;
        uptr sp = (record >> 48) << 4;
        uptr pc_mask = (1ULL << 48) - 1;
        uptr pc = record & pc_mask;
        uptr fixed_pc = StackTrace::GetNextInstructionPc(pc);
        StackTrace stack(&fixed_pc, 1);
        Printf("record: %p pc: %p sp: %p", record, pc, sp);
        stack.Print();
      }

      num_descriptions_printed++;
    }
  });

  if (!num_descriptions_printed)
    // We exhausted our possibilities. Bail out.
    Printf("HWAddressSanitizer can not describe address in more detail.\n");
}

void ReportInvalidAccess(StackTrace *stack, u32 origin) {
  ScopedErrorReportLock l;

  Decorator d;
  Printf("%s", d.Warning());
  Report("WARNING: HWAddressSanitizer: invalid access\n");
  Printf("%s", d.Default());
  stack->Print();
  ReportErrorSummary("invalid-access", stack);
}

void ReportStats() {}

void ReportInvalidAccessInsideAddressRange(const char *what, const void *start,
                                           uptr size, uptr offset) {
  ScopedErrorReportLock l;
  SavedStackAllocations current_stack_allocations(
      GetCurrentThread()->stack_allocations());

  Decorator d;
  Printf("%s", d.Warning());
  Printf("%sTag mismatch in %s%s%s at offset %zu inside [%p, %zu)%s\n",
         d.Warning(), d.Name(), what, d.Warning(), offset, start, size,
         d.Default());
  PrintAddressDescription((uptr)start + offset, 1,
                          current_stack_allocations.get());
  // if (__sanitizer::Verbosity())
  //   DescribeMemoryRange(start, size);
}

static void PrintTagsAroundAddr(tag_t *tag_ptr) {
  Printf(
      "Memory tags around the buggy address (one tag corresponds to %zd "
      "bytes):\n", kShadowAlignment);

  const uptr row_len = 16;  // better be power of two.
  const uptr num_rows = 11;
  tag_t *center_row_beg = reinterpret_cast<tag_t *>(
      RoundDownTo(reinterpret_cast<uptr>(tag_ptr), row_len));
  tag_t *beg_row = center_row_beg - row_len * (num_rows / 2);
  tag_t *end_row = center_row_beg + row_len * (num_rows / 2);
  InternalScopedString s(GetPageSizeCached());
  for (tag_t *row = beg_row; row < end_row; row += row_len) {
    s.append("%s", row == center_row_beg ? "=>" : "  ");
    for (uptr i = 0; i < row_len; i++) {
      s.append("%s", row + i == tag_ptr ? "[" : " ");
      s.append("%02x", row[i]);
      s.append("%s", row + i == tag_ptr ? "]" : " ");
    }
    s.append("%s\n", row == center_row_beg ? "<=" : "  ");
    Printf("%s", s.data());
    s.clear();
  }
}

void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
  ScopedErrorReportLock l;
  uptr untagged_addr = UntagAddr(tagged_addr);
  tag_t ptr_tag = GetTagFromPointer(tagged_addr);
  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
  tag_t mem_tag = *tag_ptr;
  Decorator d;
  Printf("%s", d.Error());
  uptr pc = stack->size ? stack->trace[0] : 0;
  const char *bug_type = "invalid-free";
  Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
         untagged_addr, pc);
  Printf("%s", d.Access());
  Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
  Printf("%s", d.Default());

  stack->Print();

  PrintAddressDescription(tagged_addr, 0, nullptr);

  PrintTagsAroundAddr(tag_ptr);

  ReportErrorSummary(bug_type, stack);
  Die();
}

void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size,
                       bool is_store) {
  ScopedErrorReportLock l;
  SavedStackAllocations current_stack_allocations(
      GetCurrentThread()->stack_allocations());

  Decorator d;
  Printf("%s", d.Error());
  uptr untagged_addr = UntagAddr(tagged_addr);
  // TODO: when possible, try to print heap-use-after-free, etc.
  const char *bug_type = "tag-mismatch";
  uptr pc = stack->size ? stack->trace[0] : 0;
  Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
         untagged_addr, pc);

  Thread *t = GetCurrentThread();

  tag_t ptr_tag = GetTagFromPointer(tagged_addr);
  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
  tag_t mem_tag = *tag_ptr;
  Printf("%s", d.Access());
  Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n",
         is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
         mem_tag, t->unique_id());
  Printf("%s", d.Default());

  stack->Print();

  PrintAddressDescription(tagged_addr, access_size,
                          current_stack_allocations.get());
  t->Announce();

  PrintTagsAroundAddr(tag_ptr);

  ReportErrorSummary(bug_type, stack);
}

}  // namespace __hwasan
<commit_msg>[hwasan] print more tags around the buggy address, and do it with a single Printf<commit_after>//===-- hwasan_report.cc --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of HWAddressSanitizer.
//
// Error reporting.
//===----------------------------------------------------------------------===//

#include "hwasan.h"
#include "hwasan_allocator.h"
#include "hwasan_mapping.h"
#include "hwasan_thread.h"
#include "hwasan_thread_list.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_symbolizer.h"

using namespace __sanitizer;

namespace __hwasan {

static StackTrace GetStackTraceFromId(u32 id) {
  CHECK(id);
  StackTrace res = StackDepotGet(id);
  CHECK(res.trace);
  return res;
}

// A RAII object that holds a copy of the current thread stack ring buffer.
// The actual stack buffer may change while we are iterating over it (for
// example, Printf may call syslog() which can itself be built with hwasan).
class SavedStackAllocations {
 public:
  SavedStackAllocations(StackAllocationsRingBuffer *rb) {
    uptr size = rb->size() * sizeof(uptr);
    void *storage =
        MmapAlignedOrDieOnFatalError(size, size * 2, "saved stack allocations");
    new (&rb_) StackAllocationsRingBuffer(*rb, storage);
  }

  ~SavedStackAllocations() {
    StackAllocationsRingBuffer *rb = get();
    UnmapOrDie(rb->StartOfStorage(), rb->size() * sizeof(uptr));
  }

  StackAllocationsRingBuffer *get() {
    return (StackAllocationsRingBuffer *)&rb_;
  }

 private:
  uptr rb_;
};

class Decorator: public __sanitizer::SanitizerCommonDecorator {
 public:
  Decorator() : SanitizerCommonDecorator() { }
  const char *Access() { return Blue(); }
  const char *Allocation() const { return Magenta(); }
  const char *Origin() const { return Magenta(); }
  const char *Name() const { return Green(); }
  const char *Location() { return Green(); }
  const char *Thread() { return Green(); }
};

// Returns the index of the rb element that matches tagged_addr (plus one),
// or zero if found nothing.
uptr FindHeapAllocation(HeapAllocationsRingBuffer *rb,
                        uptr tagged_addr,
                        HeapAllocationRecord *har) {
  if (!rb) return 0;
  for (uptr i = 0, size = rb->size(); i < size; i++) {
    auto h = (*rb)[i];
    if (h.tagged_addr <= tagged_addr &&
        h.tagged_addr + h.requested_size > tagged_addr) {
      *har = h;
      return i + 1;
    }
  }
  return 0;
}

void PrintAddressDescription(
    uptr tagged_addr, uptr access_size,
    StackAllocationsRingBuffer *current_stack_allocations) {
  Decorator d;
  int num_descriptions_printed = 0;
  uptr untagged_addr = UntagAddr(tagged_addr);
  // Check if this looks like a heap buffer overflow by scanning
  // the shadow left and right and looking for the first adjacent
  // object with a different memory tag. If that tag matches addr_tag,
  // check the allocator if it has a live chunk there.
  tag_t addr_tag = GetTagFromPointer(tagged_addr);
  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
  if (*tag_ptr != addr_tag) { // should be true usually.
    tag_t *left = tag_ptr, *right = tag_ptr;
    // scan left.
    for (int i = 0; i < 1000 && *left == *tag_ptr; i++, left--){}
    // scan right.
    for (int i = 0; i < 1000 && *right == *tag_ptr; i++, right++){}
    // Chose the object that has addr_tag and that is closer to addr.
    tag_t *candidate = nullptr;
    if (*right == addr_tag && *left == addr_tag)
      candidate = right - tag_ptr < tag_ptr - left ? right : left;
    else if (*right == addr_tag)
      candidate = right;
    else if (*left == addr_tag)
      candidate = left;

    if (candidate) {
      uptr mem = ShadowToMem(reinterpret_cast<uptr>(candidate));
      HwasanChunkView chunk = FindHeapChunkByAddress(mem);
      if (chunk.IsAllocated()) {
        Printf("%s", d.Location());
        Printf(
            "%p is located %zd bytes to the %s of %zd-byte region [%p,%p)\n",
            untagged_addr,
            candidate == left ? untagged_addr - chunk.End()
            : chunk.Beg() - untagged_addr,
            candidate == right ? "left" : "right", chunk.UsedSize(),
            chunk.Beg(), chunk.End());
        Printf("%s", d.Allocation());
        Printf("allocated here:\n");
        Printf("%s", d.Default());
        GetStackTraceFromId(chunk.GetAllocStackId()).Print();
        num_descriptions_printed++;
      }
    }
  }

  hwasanThreadList().VisitAllLiveThreads([&](Thread *t) {
    // Scan all threads' ring buffers to find if it's a heap-use-after-free.
    HeapAllocationRecord har;
    if (uptr D = FindHeapAllocation(t->heap_allocations(), tagged_addr, &har)) {
      Printf("%s", d.Location());
      Printf("%p is located %zd bytes inside of %zd-byte region [%p,%p)\n",
             untagged_addr, untagged_addr - UntagAddr(har.tagged_addr),
             har.requested_size, UntagAddr(har.tagged_addr),
             UntagAddr(har.tagged_addr) + har.requested_size);
      Printf("%s", d.Allocation());
      Printf("freed by thread T%zd here:\n", t->unique_id());
      Printf("%s", d.Default());
      GetStackTraceFromId(har.free_context_id).Print();

      Printf("%s", d.Allocation());
      Printf("previously allocated here:\n", t);
      Printf("%s", d.Default());
      GetStackTraceFromId(har.alloc_context_id).Print();
      t->Announce();

      // Print a developer note: the index of this heap object
      // in the thread's deallocation ring buffer.
      Printf("hwasan_dev_note_heap_rb_distance: %zd %zd\n", D,
             flags()->heap_history_size);

      num_descriptions_printed++;
    }

    // Very basic check for stack memory.
    if (t->AddrIsInStack(untagged_addr)) {
      Printf("%s", d.Location());
      Printf("Address %p is located in stack of thread T%zd\n", untagged_addr,
             t->unique_id());
      Printf("%s", d.Default());
      t->Announce();

      // Temporary report section, needs to be improved.
      Printf("Previosly allocated frames:\n");
      auto *sa = (t == GetCurrentThread() && current_stack_allocations)
                     ? current_stack_allocations
                     : t->stack_allocations();
      uptr frames = Min((uptr)flags()->stack_history_size, sa->size());
      for (uptr i = 0; i < frames; i++) {
        uptr record = (*sa)[i];
        if (!record)
          break;
        uptr sp = (record >> 48) << 4;
        uptr pc_mask = (1ULL << 48) - 1;
        uptr pc = record & pc_mask;
        uptr fixed_pc = StackTrace::GetNextInstructionPc(pc);
        StackTrace stack(&fixed_pc, 1);
        Printf("record: %p pc: %p sp: %p", record, pc, sp);
        stack.Print();
      }

      num_descriptions_printed++;
    }
  });

  if (!num_descriptions_printed)
    // We exhausted our possibilities. Bail out.
    Printf("HWAddressSanitizer can not describe address in more detail.\n");
}

void ReportInvalidAccess(StackTrace *stack, u32 origin) {
  ScopedErrorReportLock l;

  Decorator d;
  Printf("%s", d.Warning());
  Report("WARNING: HWAddressSanitizer: invalid access\n");
  Printf("%s", d.Default());
  stack->Print();
  ReportErrorSummary("invalid-access", stack);
}

void ReportStats() {}

void ReportInvalidAccessInsideAddressRange(const char *what, const void *start,
                                           uptr size, uptr offset) {
  ScopedErrorReportLock l;
  SavedStackAllocations current_stack_allocations(
      GetCurrentThread()->stack_allocations());

  Decorator d;
  Printf("%s", d.Warning());
  Printf("%sTag mismatch in %s%s%s at offset %zu inside [%p, %zu)%s\n",
         d.Warning(), d.Name(), what, d.Warning(), offset, start, size,
         d.Default());
  PrintAddressDescription((uptr)start + offset, 1,
                          current_stack_allocations.get());
  // if (__sanitizer::Verbosity())
  //   DescribeMemoryRange(start, size);
}

static void PrintTagsAroundAddr(tag_t *tag_ptr) {
  Printf(
      "Memory tags around the buggy address (one tag corresponds to %zd "
      "bytes):\n", kShadowAlignment);

  const uptr row_len = 16;  // better be power of two.
  const uptr num_rows = 17;
  tag_t *center_row_beg = reinterpret_cast<tag_t *>(
      RoundDownTo(reinterpret_cast<uptr>(tag_ptr), row_len));
  tag_t *beg_row = center_row_beg - row_len * (num_rows / 2);
  tag_t *end_row = center_row_beg + row_len * (num_rows / 2);
  InternalScopedString s(GetPageSizeCached() * 8);
  for (tag_t *row = beg_row; row < end_row; row += row_len) {
    s.append("%s", row == center_row_beg ? "=>" : "  ");
    for (uptr i = 0; i < row_len; i++) {
      s.append("%s", row + i == tag_ptr ? "[" : " ");
      s.append("%02x", row[i]);
      s.append("%s", row + i == tag_ptr ? "]" : " ");
    }
    s.append("%s\n", row == center_row_beg ? "<=" : "  ");
  }
  Printf("%s", s.data());
}

void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
  ScopedErrorReportLock l;
  uptr untagged_addr = UntagAddr(tagged_addr);
  tag_t ptr_tag = GetTagFromPointer(tagged_addr);
  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
  tag_t mem_tag = *tag_ptr;
  Decorator d;
  Printf("%s", d.Error());
  uptr pc = stack->size ? stack->trace[0] : 0;
  const char *bug_type = "invalid-free";
  Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
         untagged_addr, pc);
  Printf("%s", d.Access());
  Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
  Printf("%s", d.Default());

  stack->Print();

  PrintAddressDescription(tagged_addr, 0, nullptr);

  PrintTagsAroundAddr(tag_ptr);

  ReportErrorSummary(bug_type, stack);
  Die();
}

void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size,
                       bool is_store) {
  ScopedErrorReportLock l;
  SavedStackAllocations current_stack_allocations(
      GetCurrentThread()->stack_allocations());

  Decorator d;
  Printf("%s", d.Error());
  uptr untagged_addr = UntagAddr(tagged_addr);
  // TODO: when possible, try to print heap-use-after-free, etc.
  const char *bug_type = "tag-mismatch";
  uptr pc = stack->size ? stack->trace[0] : 0;
  Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
         untagged_addr, pc);

  Thread *t = GetCurrentThread();

  tag_t ptr_tag = GetTagFromPointer(tagged_addr);
  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
  tag_t mem_tag = *tag_ptr;
  Printf("%s", d.Access());
  Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n",
         is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
         mem_tag, t->unique_id());
  Printf("%s", d.Default());

  stack->Print();

  PrintAddressDescription(tagged_addr, access_size,
                          current_stack_allocations.get());
  t->Announce();

  PrintTagsAroundAddr(tag_ptr);

  ReportErrorSummary(bug_type, stack);
}

}  // namespace __hwasan
<|endoftext|>


<commit_before>// Copyright (c) 2017 The Authors. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file, See the AUTHORS file for names of contributors.

#include "../criterion/entropy.h"
#include <vector>
#include <iostream>

using namespace std;
namespace tbm = tree_based_model;

int main(void)
{
  tbm::Entropy ent;
  // test sample
  int num_classes = 2;
  // Example in Method of Statistical Learining, Li Hang
  const vector<int> data{0,0,0,0,
                         0,0,0,1,
                         0,1,0,1,
                         0,1,1,0,
                         0,0,0,0,
                         1,0,0,0,
                         1,0,0,1,
                         1,1,1,1,
                         1,0,1,2,
                         1,0,1,2,
                         2,0,1,2,
                         2,0,1,1,
                         2,1,0,1,
                         2,1,0,2,
                         2,0,0,0};

  const vector<int> labels{0,0,1,1,0,0,0,1,1,1,1,1,1,1,0};

  vector<int> feat_idx{0,1,2,3};
  vector<int> data_idx;
  for(int i = 0; i < 15; ++i)
    data_idx.push_back(i);

  int best_feature_idx = 0;
  best_feature_idx = ent.BestInfoGain(data_idx, feat_idx, data, labels, num_classes);
  cout << "Use info gain, best feature index: " << best_feature_idx << endl;
  cout << "Impurity value:  " << ent.get_impurity() << endl;

  best_feature_idx = ent.BestInfoGainRatio(data_idx, feat_idx, data, labels, num_classes);
  cout << "Use info gain ratio, best feature index: " << best_feature_idx << endl;
  cout << "Impurity value:  " << ent.get_impurity() << endl;
  return 0;
}
<commit_msg>Delete entropy_test.cc<commit_after><|endoftext|>