<commit_before>#include "helpers/read_test_entries.h"
#include <assert.h>
#include <string>
#include <regex>
#include "helpers/file_helpers.h"

using std::move;
using std::regex;
using std::regex_search;
using std::regex_replace;
using std::regex_constants::extended;
using std::smatch;
using std::string;
using std::vector;

static string trim_output(const string &input) {
  string result(input);
  result = regex_replace(result, regex("[\n\t ]+", extended), string(" "));
  result = regex_replace(result, regex("^ ", extended), string(""));
  result = regex_replace(result, regex(" $", extended), string(""));
  result = regex_replace(result, regex("\\) \\)", extended), string("))"));
  return result;
}

static vector<TestEntry> parse_test_entries(string content) {
  regex header_pattern("(^|\n)===+\n"  "([^=]+)\n"  "===+\n", extended);
  regex separator_pattern("---+\r?\n", extended);
  vector<string> descriptions;
  vector<string> bodies;

  for (;;) {
    smatch matches;
    if (!regex_search(content, matches, header_pattern) || matches.empty())
      break;

    string description = matches[1].str();
    descriptions.push_back(description);

    if (!bodies.empty())
      bodies.back().erase(matches.position());
    content.erase(0, matches.position() + matches[0].length());
    bodies.push_back(content);
  }

  vector<TestEntry> result;
  for (size_t i = 0; i < descriptions.size(); i++) {
    string body = bodies[i];
    smatch matches;
    if (regex_search(body, matches, separator_pattern)) {
      result.push_back({
        descriptions[i],
        body.substr(0, matches.position() - 1),
        trim_output(body.substr(matches.position() + matches[0].length()))
      });
    } else {
      puts(("Invalid corpus entry with description: " + descriptions[i]).c_str());
      abort();
    }
  }

  return result;
}

vector<TestEntry> read_real_language_corpus(string language_name) {
  vector<TestEntry> result;

  string corpus_directory = join_path({"test", "fixtures", "grammars", language_name, "corpus"});
  for (string &test_filename : list_directory(corpus_directory)) {
    for (TestEntry &entry : parse_test_entries(read_file(join_path({corpus_directory, test_filename})))) {
      result.push_back(entry);
    }
  }

  string error_test_filename = join_path({"test", "fixtures", "error_corpus", language_name + "_errors.txt"});
  for (TestEntry &entry : parse_test_entries(read_file(error_test_filename))) {
    result.push_back(entry);
  }

  return result;
}

vector<TestEntry> read_test_language_corpus(string language_name) {
  vector<TestEntry> result;

  string test_directory = join_path({"test", "fixtures", "test_grammars", language_name});
  for (string &test_filename : list_directory(test_directory)) {
    for (TestEntry &entry : parse_test_entries(read_file(join_path({test_directory, test_filename})))) {
      result.push_back(entry);
    }
  }

  return result;
}

vector<ExampleEntry> examples_for_language(string language_name) {
  vector<ExampleEntry> result;
  string examples_directory = join_path({"test", "fixtures", "grammars", language_name, "examples"});
  for (string &filename : list_directory(examples_directory)) {
    auto content = read_file(join_path({examples_directory, filename}));
    if (!content.empty()) {
      result.push_back({filename, move(content)});
    }
  }
  return result;
}
<commit_msg>Fix capture of corpus descriptions in integration tests<commit_after>#include "helpers/read_test_entries.h"
#include <assert.h>
#include <string>
#include <regex>
#include "helpers/file_helpers.h"

using std::move;
using std::regex;
using std::regex_search;
using std::regex_replace;
using std::regex_constants::extended;
using std::smatch;
using std::string;
using std::vector;

static string trim_output(const string &input) {
  string result(input);
  result = regex_replace(result, regex("[\n\t ]+", extended), string(" "));
  result = regex_replace(result, regex("^ ", extended), string(""));
  result = regex_replace(result, regex(" $", extended), string(""));
  result = regex_replace(result, regex("\\) \\)", extended), string("))"));
  return result;
}

static vector<TestEntry> parse_test_entries(string content) {
  regex header_pattern("(^|\n)===+\n"  "([^=]+)\n"  "===+\n", extended);
  regex separator_pattern("---+\r?\n", extended);
  vector<string> descriptions;
  vector<string> bodies;

  for (;;) {
    smatch matches;
    if (!regex_search(content, matches, header_pattern) || matches.empty())
      break;

    string description = matches[2].str();
    descriptions.push_back(description);

    if (!bodies.empty())
      bodies.back().erase(matches.position());
    content.erase(0, matches.position() + matches[0].length());
    bodies.push_back(content);
  }

  vector<TestEntry> result;
  for (size_t i = 0; i < descriptions.size(); i++) {
    string body = bodies[i];
    smatch matches;
    if (regex_search(body, matches, separator_pattern)) {
      result.push_back({
        descriptions[i],
        body.substr(0, matches.position() - 1),
        trim_output(body.substr(matches.position() + matches[0].length()))
      });
    } else {
      puts(("Invalid corpus entry with description: " + descriptions[i]).c_str());
      abort();
    }
  }

  return result;
}

vector<TestEntry> read_real_language_corpus(string language_name) {
  vector<TestEntry> result;

  string corpus_directory = join_path({"test", "fixtures", "grammars", language_name, "corpus"});
  for (string &test_filename : list_directory(corpus_directory)) {
    for (TestEntry &entry : parse_test_entries(read_file(join_path({corpus_directory, test_filename})))) {
      result.push_back(entry);
    }
  }

  string error_test_filename = join_path({"test", "fixtures", "error_corpus", language_name + "_errors.txt"});
  for (TestEntry &entry : parse_test_entries(read_file(error_test_filename))) {
    result.push_back(entry);
  }

  return result;
}

vector<TestEntry> read_test_language_corpus(string language_name) {
  vector<TestEntry> result;

  string test_directory = join_path({"test", "fixtures", "test_grammars", language_name});
  for (string &test_filename : list_directory(test_directory)) {
    for (TestEntry &entry : parse_test_entries(read_file(join_path({test_directory, test_filename})))) {
      result.push_back(entry);
    }
  }

  return result;
}

vector<ExampleEntry> examples_for_language(string language_name) {
  vector<ExampleEntry> result;
  string examples_directory = join_path({"test", "fixtures", "grammars", language_name, "examples"});
  for (string &filename : list_directory(examples_directory)) {
    auto content = read_file(join_path({examples_directory, filename}));
    if (!content.empty()) {
      result.push_back({filename, move(content)});
    }
  }
  return result;
}
<|endoftext|>


<commit_before>
#include "TestGlobals.h"
#include "ChunkBuffer.h"

int main(int argc, char** argv)
{
	{
		cChunkBuffer buffer;

		// Empty chunks
		buffer.SetBlock(0,0,0, 0xAB);
		testassert(buffer.GetBlock(0,0,0) == 0xAB);
		buffer.SetMeta(0,16,0, 0xC);
		testassert(buffer.GetMeta(0,16,0) == 0xC);

		// loaded but not written segments
		testassert(buffer.GetBlock(1,0,0) == 0x0);
		testassert(buffer.GetMeta(1,16,0) == 0x0);

		// Notloaded segments
		testassert(buffer.GetBlock(0,32,0) == 0x0);
		testassert(buffer.GetMeta(0,48,0) == 0x0);

		// Out of Range
		CheckAsserts(
			buffer.SetBlock(-1, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, -1, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, 0, -1, 0);
		);
		CheckAsserts(
			buffer.SetBlock(256, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, 256, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, 0, 256, 0);
		);

		// Out of Range
		CheckAsserts(
			buffer.GetBlock(-1, 0, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, -1, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, 0, -1);
		);
		CheckAsserts(
			buffer.GetBlock(256, 0, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, 256, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, 0, 256);
		);

		// Out of Range
		CheckAsserts(
			buffer.SetMeta(-1, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, -1, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, 0, -1, 0);
		);
		CheckAsserts(
			buffer.SetMeta(256, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, 256, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, 0, 256, 0);
		);

		// Out of Range
		CheckAsserts(
			buffer.GetMeta(-1, 0, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, -1, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, 0, -1);
		);
		CheckAsserts(
			buffer.GetMeta(256, 0, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, 256, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, 0, 256);
		);
	}

	{
		cChunkBuffer buffer;

		// Zero's
		buffer.SetBlock(0,0,0, 0x0);
		buffer.SetBlock(0,0,1, 0xAB);
		testassert(buffer.GetBlock(0,0,0) == 0x0);
		testassert(buffer.GetBlock(0,0,1) == 0xAB);

		buffer.SetMeta(0,16,0, 0x0);
		buffer.SetMeta(0,16,1, 0xC);
		testassert(buffer.GetMeta(0,16,0) == 0x0);
		testassert(buffer.GetMeta(0,16,1) == 0xC);
	}

	{
		// Operator =
		cChunkBuffer buffer;
		buffer.SetBlock(0,0,0,0x42);
		cChunkBuffer copy;
		copy = std::move(buffer);
		testassert(copy.GetBlock(0,0,0) == 0x42);
		copy = std::move(copy);
		testassert(copy.GetBlock(0,0,0) == 0x42);
	}

	return 0;
}
<commit_msg>C++11<commit_after>
#include "TestGlobals.h"
#include "ChunkBuffer.h"

int main(int argc, char** argv)
{
	{
		cChunkBuffer buffer;

		// Empty chunks
		buffer.SetBlock(0,0,0, 0xAB);
		testassert(buffer.GetBlock(0,0,0) == 0xAB);
		buffer.SetMeta(0,16,0, 0xC);
		testassert(buffer.GetMeta(0,16,0) == 0xC);

		// loaded but not written segments
		testassert(buffer.GetBlock(1,0,0) == 0x0);
		testassert(buffer.GetMeta(1,16,0) == 0x0);

		// Notloaded segments
		testassert(buffer.GetBlock(0,32,0) == 0x0);
		testassert(buffer.GetMeta(0,48,0) == 0x0);

		// Out of Range
		CheckAsserts(
			buffer.SetBlock(-1, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, -1, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, 0, -1, 0);
		);
		CheckAsserts(
			buffer.SetBlock(256, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, 256, 0, 0);
		);
		CheckAsserts(
			buffer.SetBlock(0, 0, 256, 0);
		);

		// Out of Range
		CheckAsserts(
			buffer.GetBlock(-1, 0, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, -1, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, 0, -1);
		);
		CheckAsserts(
			buffer.GetBlock(256, 0, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, 256, 0);
		);
		CheckAsserts(
			buffer.GetBlock(0, 0, 256);
		);

		// Out of Range
		CheckAsserts(
			buffer.SetMeta(-1, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, -1, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, 0, -1, 0);
		);
		CheckAsserts(
			buffer.SetMeta(256, 0, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, 256, 0, 0);
		);
		CheckAsserts(
			buffer.SetMeta(0, 0, 256, 0);
		);

		// Out of Range
		CheckAsserts(
			buffer.GetMeta(-1, 0, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, -1, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, 0, -1);
		);
		CheckAsserts(
			buffer.GetMeta(256, 0, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, 256, 0);
		);
		CheckAsserts(
			buffer.GetMeta(0, 0, 256);
		);
	}

	{
		cChunkBuffer buffer;

		// Zero's
		buffer.SetBlock(0,0,0, 0x0);
		buffer.SetBlock(0,0,1, 0xAB);
		testassert(buffer.GetBlock(0,0,0) == 0x0);
		testassert(buffer.GetBlock(0,0,1) == 0xAB);

		buffer.SetMeta(0,16,0, 0x0);
		buffer.SetMeta(0,16,1, 0xC);
		testassert(buffer.GetMeta(0,16,0) == 0x0);
		testassert(buffer.GetMeta(0,16,1) == 0xC);
	}

	{
		// Operator =
		cChunkBuffer buffer;
		buffer.SetBlock(0,0,0,0x42);
		cChunkBuffer copy;
		#if __cplusplus < 201103L
		copy = buffer;
		#else
		copy = std::move(buffer);
		#endif
		testassert(copy.GetBlock(0,0,0) == 0x42);
		#if __cplusplus < 201103L
		copy = copy;
		#else
		copy = std::move(copy);
		#endif
		testassert(copy.GetBlock(0,0,0) == 0x42);
	}

	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkFrontBufferedStream.h"
#include "SkRefCnt.h"
#include "SkStream.h"
#include "SkTypes.h"
#include "Test.h"

static void test_read(skiatest::Reporter* reporter, SkStream* bufferedStream,
                      const void* expectations, size_t bytesToRead) {
    // output for reading bufferedStream.
    SkAutoMalloc storage(bytesToRead);

    const size_t bytesRead = bufferedStream->read(storage.get(), bytesToRead);
    REPORTER_ASSERT(reporter, bytesRead == bytesToRead || bufferedStream->isAtEnd());
    REPORTER_ASSERT(reporter, memcmp(storage.get(), expectations, bytesRead) == 0);
}

static void test_rewind(skiatest::Reporter* reporter,
                        SkStream* bufferedStream, bool shouldSucceed) {
    const bool success = bufferedStream->rewind();
    REPORTER_ASSERT(reporter, success == shouldSucceed);
}

// Test that hasLength() returns the correct value, based on the stream
// being wrapped. A length can only be known if the wrapped stream has a
// length and it has a position (so its initial position can be taken into
// account when computing the length).
static void test_hasLength(skiatest::Reporter* reporter,
                           const SkStream& bufferedStream,
                           const SkStream& streamBeingBuffered) {
    if (streamBeingBuffered.hasLength() && streamBeingBuffered.hasPosition()) {
        REPORTER_ASSERT(reporter, bufferedStream.hasLength());
    } else {
        REPORTER_ASSERT(reporter, !bufferedStream.hasLength());
    }
}

// All tests will buffer this string, and compare output to the original.
// The string is long to ensure that all of our lengths being tested are
// smaller than the string length.
const char gAbcs[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx";

// Tests reading the stream across boundaries of what has been buffered so far and what
// the total buffer size is.
static void test_incremental_buffering(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);

    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // First, test reading less than the max buffer size.
    test_read(reporter, bufferedStream, gAbcs, bufferSize / 2);

    // Now test rewinding back to the beginning and reading less than what was
    // already buffered.
    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize / 4);

    // Now test reading part of what was buffered, and buffering new data.
    test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 2);

    // Now test reading what was buffered, buffering new data, and
    // reading directly from the stream.
    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize << 1);

    // We have reached the end of the buffer, so rewinding will fail.
    // This test assumes that the stream is larger than the buffer; otherwise the
    // result of rewind should be true.
    test_rewind(reporter, bufferedStream, false);
}

static void test_perfectly_sized_buffer(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // Read exactly the amount that fits in the buffer.
    test_read(reporter, bufferedStream, gAbcs, bufferSize);

    // Rewinding should succeed.
    test_rewind(reporter, bufferedStream, true);

    // Once again reading buffered info should succeed
    test_read(reporter, bufferedStream, gAbcs, bufferSize);

    // Read past the size of the buffer. At this point, we cannot return.
    test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), 1);
    test_rewind(reporter, bufferedStream, false);
}

static void test_skipping(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // Skip half the buffer.
    bufferedStream->skip(bufferSize / 2);

    // Rewind, then read part of the buffer, which should have been read.
    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize / 4);

    // Now skip beyond the buffered piece, but still within the total buffer.
    bufferedStream->skip(bufferSize / 2);

    // Test that reading will still work.
    test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 4);

    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize);
}

// A custom class whose isAtEnd behaves the way Android's stream does - since it is an adaptor to a
// Java InputStream, it does not know that it is at the end until it has attempted to read beyond
// the end and failed. Used by test_read_beyond_buffer.
class AndroidLikeMemoryStream : public SkMemoryStream {
public:
    AndroidLikeMemoryStream(void* data, size_t size, bool ownMemory)
        : INHERITED(data, size, ownMemory)
        , fIsAtEnd(false) {}

    size_t read(void* dst, size_t requested) SK_OVERRIDE {
        size_t bytesRead = this->INHERITED::read(dst, requested);
        if (bytesRead < requested) {
            fIsAtEnd = true;
        }
        return bytesRead;
    }

    bool isAtEnd() const SK_OVERRIDE {
        return fIsAtEnd;
    }

private:
    bool fIsAtEnd;
    typedef SkMemoryStream INHERITED;
};

// This test ensures that buffering the exact length of the stream and attempting to read beyond it
// does not invalidate the buffer.
static void test_read_beyond_buffer(skiatest::Reporter* reporter, size_t bufferSize) {
    // Use a stream that behaves like Android's stream.
    AndroidLikeMemoryStream memStream((void*)gAbcs, bufferSize, false);

    // Create a buffer that matches the length of the stream.
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // Attempt to read one more than the bufferSize
    test_read(reporter, bufferedStream.get(), gAbcs, bufferSize + 1);
    test_rewind(reporter, bufferedStream.get(), true);

    // Ensure that the initial read did not invalidate the buffer.
    test_read(reporter, bufferedStream, gAbcs, bufferSize);
}

// Dummy stream that optionally has a length and/or position. Tests that FrontBufferedStream's
// length depends on the stream it's buffering having a length and position.
class LengthOptionalStream : public SkStream {
public:
    LengthOptionalStream(bool hasLength, bool hasPosition)
        : fHasLength(hasLength)
        , fHasPosition(hasPosition)
    {}

    virtual bool hasLength() const SK_OVERRIDE {
        return fHasLength;
    }

    virtual bool hasPosition() const SK_OVERRIDE {
        return fHasPosition;
    }

    virtual size_t read(void*, size_t) SK_OVERRIDE {
        return 0;
    }

    virtual bool isAtEnd() const SK_OVERRIDE {
        return true;
    }

private:
    const bool fHasLength;
    const bool fHasPosition;
};

// Test all possible combinations of the wrapped stream having a length and a position.
static void test_length_combos(skiatest::Reporter* reporter, size_t bufferSize) {
    for (int hasLen = 0; hasLen <= 1; hasLen++) {
        for (int hasPos = 0; hasPos <= 1; hasPos++) {
            LengthOptionalStream stream((bool) hasLen, (bool) hasPos);
            SkAutoTUnref<SkStream> buffered(SkFrontBufferedStream::Create(&stream, bufferSize));
            test_hasLength(reporter, *buffered.get(), stream);
        }
    }
}

// Test using a stream with an initial offset.
static void test_initial_offset(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);

    // Skip a few characters into the memStream, so that bufferedStream represents an offset into
    // the stream it wraps.
    const size_t arbitraryOffset = 17;
    memStream.skip(arbitraryOffset);
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));

    // Since SkMemoryStream has a length and a position, bufferedStream must also.
    REPORTER_ASSERT(reporter, bufferedStream->hasLength());

    const size_t amountToRead = 10;
    const size_t bufferedLength = bufferedStream->getLength();
    size_t currentPosition = bufferedStream->getPosition();
    REPORTER_ASSERT(reporter, 0 == currentPosition);

    // Read the stream in chunks. After each read, the position must match currentPosition,
    // which sums the amount attempted to read, unless the end of the stream has been reached.
    // Importantly, the end should not have been reached until currentPosition == bufferedLength.
    while (currentPosition < bufferedLength) {
        REPORTER_ASSERT(reporter, !bufferedStream->isAtEnd());
        test_read(reporter, bufferedStream, gAbcs + arbitraryOffset + currentPosition,
                  amountToRead);
        currentPosition = SkTMin(currentPosition + amountToRead, bufferedLength);
        REPORTER_ASSERT(reporter, bufferedStream->getPosition() == currentPosition);
    }
    REPORTER_ASSERT(reporter, bufferedStream->isAtEnd());
    REPORTER_ASSERT(reporter, bufferedLength == currentPosition);
}

static void test_buffers(skiatest::Reporter* reporter, size_t bufferSize) {
    test_incremental_buffering(reporter, bufferSize);
    test_perfectly_sized_buffer(reporter, bufferSize);
    test_skipping(reporter, bufferSize);
    test_read_beyond_buffer(reporter, bufferSize);
    test_length_combos(reporter, bufferSize);
    test_initial_offset(reporter, bufferSize);
}

DEF_TEST(FrontBufferedStream, reporter) {
    // Test 6 and 64, which are used by Android, as well as another arbitrary length.
    test_buffers(reporter, 6);
    test_buffers(reporter, 15);
    test_buffers(reporter, 64);
}
<commit_msg>Use SkToBool to fix a warning.<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkFrontBufferedStream.h"
#include "SkRefCnt.h"
#include "SkStream.h"
#include "SkTypes.h"
#include "Test.h"

static void test_read(skiatest::Reporter* reporter, SkStream* bufferedStream,
                      const void* expectations, size_t bytesToRead) {
    // output for reading bufferedStream.
    SkAutoMalloc storage(bytesToRead);

    const size_t bytesRead = bufferedStream->read(storage.get(), bytesToRead);
    REPORTER_ASSERT(reporter, bytesRead == bytesToRead || bufferedStream->isAtEnd());
    REPORTER_ASSERT(reporter, memcmp(storage.get(), expectations, bytesRead) == 0);
}

static void test_rewind(skiatest::Reporter* reporter,
                        SkStream* bufferedStream, bool shouldSucceed) {
    const bool success = bufferedStream->rewind();
    REPORTER_ASSERT(reporter, success == shouldSucceed);
}

// Test that hasLength() returns the correct value, based on the stream
// being wrapped. A length can only be known if the wrapped stream has a
// length and it has a position (so its initial position can be taken into
// account when computing the length).
static void test_hasLength(skiatest::Reporter* reporter,
                           const SkStream& bufferedStream,
                           const SkStream& streamBeingBuffered) {
    if (streamBeingBuffered.hasLength() && streamBeingBuffered.hasPosition()) {
        REPORTER_ASSERT(reporter, bufferedStream.hasLength());
    } else {
        REPORTER_ASSERT(reporter, !bufferedStream.hasLength());
    }
}

// All tests will buffer this string, and compare output to the original.
// The string is long to ensure that all of our lengths being tested are
// smaller than the string length.
const char gAbcs[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx";

// Tests reading the stream across boundaries of what has been buffered so far and what
// the total buffer size is.
static void test_incremental_buffering(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);

    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // First, test reading less than the max buffer size.
    test_read(reporter, bufferedStream, gAbcs, bufferSize / 2);

    // Now test rewinding back to the beginning and reading less than what was
    // already buffered.
    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize / 4);

    // Now test reading part of what was buffered, and buffering new data.
    test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 2);

    // Now test reading what was buffered, buffering new data, and
    // reading directly from the stream.
    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize << 1);

    // We have reached the end of the buffer, so rewinding will fail.
    // This test assumes that the stream is larger than the buffer; otherwise the
    // result of rewind should be true.
    test_rewind(reporter, bufferedStream, false);
}

static void test_perfectly_sized_buffer(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // Read exactly the amount that fits in the buffer.
    test_read(reporter, bufferedStream, gAbcs, bufferSize);

    // Rewinding should succeed.
    test_rewind(reporter, bufferedStream, true);

    // Once again reading buffered info should succeed
    test_read(reporter, bufferedStream, gAbcs, bufferSize);

    // Read past the size of the buffer. At this point, we cannot return.
    test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), 1);
    test_rewind(reporter, bufferedStream, false);
}

static void test_skipping(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // Skip half the buffer.
    bufferedStream->skip(bufferSize / 2);

    // Rewind, then read part of the buffer, which should have been read.
    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize / 4);

    // Now skip beyond the buffered piece, but still within the total buffer.
    bufferedStream->skip(bufferSize / 2);

    // Test that reading will still work.
    test_read(reporter, bufferedStream, gAbcs + bufferedStream->getPosition(), bufferSize / 4);

    test_rewind(reporter, bufferedStream, true);
    test_read(reporter, bufferedStream, gAbcs, bufferSize);
}

// A custom class whose isAtEnd behaves the way Android's stream does - since it is an adaptor to a
// Java InputStream, it does not know that it is at the end until it has attempted to read beyond
// the end and failed. Used by test_read_beyond_buffer.
class AndroidLikeMemoryStream : public SkMemoryStream {
public:
    AndroidLikeMemoryStream(void* data, size_t size, bool ownMemory)
        : INHERITED(data, size, ownMemory)
        , fIsAtEnd(false) {}

    size_t read(void* dst, size_t requested) SK_OVERRIDE {
        size_t bytesRead = this->INHERITED::read(dst, requested);
        if (bytesRead < requested) {
            fIsAtEnd = true;
        }
        return bytesRead;
    }

    bool isAtEnd() const SK_OVERRIDE {
        return fIsAtEnd;
    }

private:
    bool fIsAtEnd;
    typedef SkMemoryStream INHERITED;
};

// This test ensures that buffering the exact length of the stream and attempting to read beyond it
// does not invalidate the buffer.
static void test_read_beyond_buffer(skiatest::Reporter* reporter, size_t bufferSize) {
    // Use a stream that behaves like Android's stream.
    AndroidLikeMemoryStream memStream((void*)gAbcs, bufferSize, false);

    // Create a buffer that matches the length of the stream.
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));
    test_hasLength(reporter, *bufferedStream.get(), memStream);

    // Attempt to read one more than the bufferSize
    test_read(reporter, bufferedStream.get(), gAbcs, bufferSize + 1);
    test_rewind(reporter, bufferedStream.get(), true);

    // Ensure that the initial read did not invalidate the buffer.
    test_read(reporter, bufferedStream, gAbcs, bufferSize);
}

// Dummy stream that optionally has a length and/or position. Tests that FrontBufferedStream's
// length depends on the stream it's buffering having a length and position.
class LengthOptionalStream : public SkStream {
public:
    LengthOptionalStream(bool hasLength, bool hasPosition)
        : fHasLength(hasLength)
        , fHasPosition(hasPosition)
    {}

    virtual bool hasLength() const SK_OVERRIDE {
        return fHasLength;
    }

    virtual bool hasPosition() const SK_OVERRIDE {
        return fHasPosition;
    }

    virtual size_t read(void*, size_t) SK_OVERRIDE {
        return 0;
    }

    virtual bool isAtEnd() const SK_OVERRIDE {
        return true;
    }

private:
    const bool fHasLength;
    const bool fHasPosition;
};

// Test all possible combinations of the wrapped stream having a length and a position.
static void test_length_combos(skiatest::Reporter* reporter, size_t bufferSize) {
    for (int hasLen = 0; hasLen <= 1; hasLen++) {
        for (int hasPos = 0; hasPos <= 1; hasPos++) {
            LengthOptionalStream stream(SkToBool(hasLen), SkToBool(hasPos));
            SkAutoTUnref<SkStream> buffered(SkFrontBufferedStream::Create(&stream, bufferSize));
            test_hasLength(reporter, *buffered.get(), stream);
        }
    }
}

// Test using a stream with an initial offset.
static void test_initial_offset(skiatest::Reporter* reporter, size_t bufferSize) {
    SkMemoryStream memStream(gAbcs, strlen(gAbcs), false);

    // Skip a few characters into the memStream, so that bufferedStream represents an offset into
    // the stream it wraps.
    const size_t arbitraryOffset = 17;
    memStream.skip(arbitraryOffset);
    SkAutoTUnref<SkStream> bufferedStream(SkFrontBufferedStream::Create(&memStream, bufferSize));

    // Since SkMemoryStream has a length and a position, bufferedStream must also.
    REPORTER_ASSERT(reporter, bufferedStream->hasLength());

    const size_t amountToRead = 10;
    const size_t bufferedLength = bufferedStream->getLength();
    size_t currentPosition = bufferedStream->getPosition();
    REPORTER_ASSERT(reporter, 0 == currentPosition);

    // Read the stream in chunks. After each read, the position must match currentPosition,
    // which sums the amount attempted to read, unless the end of the stream has been reached.
    // Importantly, the end should not have been reached until currentPosition == bufferedLength.
    while (currentPosition < bufferedLength) {
        REPORTER_ASSERT(reporter, !bufferedStream->isAtEnd());
        test_read(reporter, bufferedStream, gAbcs + arbitraryOffset + currentPosition,
                  amountToRead);
        currentPosition = SkTMin(currentPosition + amountToRead, bufferedLength);
        REPORTER_ASSERT(reporter, bufferedStream->getPosition() == currentPosition);
    }
    REPORTER_ASSERT(reporter, bufferedStream->isAtEnd());
    REPORTER_ASSERT(reporter, bufferedLength == currentPosition);
}

static void test_buffers(skiatest::Reporter* reporter, size_t bufferSize) {
    test_incremental_buffering(reporter, bufferSize);
    test_perfectly_sized_buffer(reporter, bufferSize);
    test_skipping(reporter, bufferSize);
    test_read_beyond_buffer(reporter, bufferSize);
    test_length_combos(reporter, bufferSize);
    test_initial_offset(reporter, bufferSize);
}

DEF_TEST(FrontBufferedStream, reporter) {
    // Test 6 and 64, which are used by Android, as well as another arbitrary length.
    test_buffers(reporter, 6);
    test_buffers(reporter, 15);
    test_buffers(reporter, 64);
}
<|endoftext|>


<commit_before>#include "catch.hpp"

#include "PermutationSequence.hpp"

using namespace std;

TEST_CASE("Permutation Sequence") {
    PermutationSequence s;
    SECTION("Sample tests") {
        vector<string> expected{"123", "132", "213", "231", "312", "321"};

        for (int k = 1; k <= 6; k++)
            REQUIRE(s.getPermutation(3, k) == expected[k - 1]);
    }
}
<commit_msg>Refine Problem 60. Permutation Sequence<commit_after>#include "catch.hpp"

#include "PermutationSequence.hpp"

TEST_CASE("Permutation Sequence") {Permutation Sequence
    PermutationSequence s;
    SECTION("Sample tests") {
        vector<string> expected{"123", "132", "213", "231", "312", "321"};

        for (int k = 1; k <= 6; k++)
            REQUIRE(s.getPermutation(3, k) == expected[k - 1]);
    }
}
<|endoftext|>


<commit_before>
#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <CompositeTransformation.h>
#include <MetaEvent.h>

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

namespace test {

using namespace std;

using ::testing::_;
using ::testing::Return;
using ::testing::AtLeast;
using ::testing::UnorderedElementsAre;
using boost::filesystem::ofstream;
using boost::filesystem::current_path;
using boost::filesystem::path;

MATCHER(EqPtrContent, "") {
  return *get<0>(arg)==*get<1>(arg);
}
struct CompositeTransformSuite : public ::testing::Test {

  using EventTypes = Transformer::EventTypes;
  using TransPtr   = Transformation::TransPtr;

  static bool comp(const MetaEvent* const a, const MetaEvent* const b) {
    return *a==*b;
  }

  struct TestTransformer : public Transformer {
    string name;
    TestTransformer(const string& name, const EventType& out, const EventTypes& in,
                    map<string, TestTransformer*>& trans)
      : Transformer(out, in), name(name) {
      trans[name]=this;
    }
    MOCK_CONST_METHOD1(check, bool(const MetaEvent&));
    MOCK_CONST_METHOD1(call, Events(const MetaEvent&));
    virtual Events operator()(const MetaEvent& e) { return call(e); }
    virtual void print(ostream& o) const { o << name; }
  };

  struct TestTransformation : public Transformation {
    string name;
    TestTransformation(const string& name, size_t arity)
      : Transformation(Type::attribute, arity, EventID::any), name(name) { }

    MOCK_CONST_METHOD3(in, EventTypes(const EventType& goal, const EventType& provided, const MetaFilter& filter));
    MOCK_CONST_METHOD2(in, EventIDs(EventID goal, const MetaFilter& filter));
    MOCK_CONST_METHOD4(create, TransPtr(const EventType& out, const EventTypes& in, const AbstractPolicy& policy, const MetaFilter& filter));
    virtual void print(ostream& o) const { o << name; }
  };

  map<string, TestTransformer*> trans;
  TestTransformation a, c, d;
  CompositeTransformation compTrans, compTrans2;
  shared_ptr<const TestTransformation> b;
  EventType goal, provided, provided2, intermediate, intermediate2;

  struct Test0: public ::id::attribute::Base {
    static constexpr const ::id::attribute::ID value()  { return 251; }
  };
  struct Test1: public ::id::attribute::Base {
    static constexpr const ::id::attribute::ID value()  { return 252; }
  };

  CompositeTransformSuite()
    : a("a", 1), c("c", 2), d("d", 1), b(new TestTransformation("b", 1))
  {}

  void SetUp() {

    ValueType goalVT(id::type::Float::value(), 1, 1, false);

    AttributeType goalAT(Test0::value(), goalVT, Scale<>(), Dimensionless());
    AttributeType int2AT(Test1::value(), goalVT, Scale<std::ratio<1, 1000>>(), Dimensionless());
    AttributeType intAT = goalAT;
    AttributeType provAT = intAT;
    AttributeType prov2AT = int2AT;

    intAT.scale().denom(1000);
    provAT.scale().denom(1000);
    provAT.value().typeId(id::type::Int32::value());
    prov2AT.value().typeId(id::type::Int32::value());

    goal.add(goalAT);
    intermediate.add(intAT);
    provided.add(provAT);
    intermediate2.add(int2AT);
    provided2.add(prov2AT);

    ASSERT_NE(b, nullptr);
    EXPECT_CALL(a, in(goal, provided, _))
      .Times(1).WillOnce(Return(EventTypes({intermediate})));
    EXPECT_CALL(*b, in(intermediate, provided, _))
      .Times(AtLeast(1)).WillRepeatedly(Return(EventTypes({provided})));
    EXPECT_CALL(c, in(goal, _, _))
      .Times(1).WillOnce(Return(EventTypes({intermediate, intermediate2})));
    EXPECT_CALL(d, in(intermediate2, provided2, _))
      .Times(1).WillOnce(Return(EventTypes({provided2})));
    auto r0 = compTrans.add(&a, goal, provided);
    ASSERT_TRUE(r0.second);
    auto r1 = compTrans.add(b.get(), r0.first, intermediate, provided);
    ASSERT_TRUE(r1.second);
    ofstream out(current_path()/"doc"/"linTransformation.dot");
    out << compTrans;
    auto r2 = compTrans2.add(&c, goal, EventType());
    ASSERT_TRUE(r2.second);
    auto r3 = compTrans2.add(b.get(), r2.first, intermediate, provided);
    ASSERT_TRUE(r3.second);
    auto r4 = compTrans2.add(&d, r2.first, intermediate2, provided2);
    ASSERT_TRUE(r4.second);
    out.close();
    out.open(current_path()/"doc"/"treeTransformation.dot");
    out << compTrans2;
  }
};

TEST_F(CompositeTransformSuite, linearTest) {
  using Graph = CompositeTransformation::Graph;
  using Vertex = CompositeTransformation::Vertex;
  using Edge = Graph::edge_descriptor;
  const Graph& g = compTrans.graph();
  ASSERT_EQ(boost::num_vertices(g), 2U);
  auto v = boost::vertices(g);
  Vertex testAV = *v.first;
  const Transformation& testA = *g[testAV].trans();
  EXPECT_EQ(testA, a);
  auto out = out_edges(testAV, g);
  ASSERT_NE(out.first, out.second);
  Edge testBE = *out.first;
  Vertex testBV = target(testBE, g);
  const Transformation& testB = *g[testBV].trans();
  ASSERT_NE(b, nullptr);
  EXPECT_EQ(testB, *b);
}

TEST_F(CompositeTransformSuite, linearInTest) {
  auto result = compTrans.in();
  EXPECT_EQ(result, EventTypes({provided}));
}

TEST_F(CompositeTransformSuite, treeTest) {
  using Graph = CompositeTransformation::Graph;
  using Vertex = CompositeTransformation::Vertex;
  using Edge = Graph::edge_descriptor;
  const Graph& g = compTrans2.graph();
  ASSERT_EQ(boost::num_vertices(g), 3U);
  auto v = boost::vertices(g);
  Vertex testCV = *v.first;
  const Transformation& testC = *g[testCV].trans();
  EXPECT_EQ(testC, c);
  auto out = out_edges(testCV, g);
  ASSERT_NE(out.first, out.second);
  Edge testBE = *out.first;
  Vertex testBV = target(testBE, g);
  const Transformation& testB = *g[testBV].trans();
  ASSERT_NE(b, nullptr);
  EXPECT_EQ(testB, *b);
  Edge testDE = *++out.first;
  Vertex testDV = target(testDE, g);
  const Transformation& testD = *g[testDV].trans();
  ASSERT_NE(b, nullptr);
  EXPECT_EQ(testD, d);
}

TEST_F(CompositeTransformSuite, treeInTest) {
  auto result = compTrans2.in();
  ASSERT_FALSE(result.empty());
  EXPECT_EQ(result, EventTypes({provided, provided2}));
}

TEST_F(CompositeTransformSuite, linearCreateTest) {
  using Events = Transformer::Events;
  EXPECT_CALL(a, create(goal, EventTypes({intermediate}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("a", goal, EventTypes({intermediate}), trans))));
  ASSERT_NE(b, nullptr);
  EXPECT_CALL(*b, create(intermediate, EventTypes({provided}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("b", intermediate, EventTypes({provided}),trans))));
  TransPtr result = compTrans.create(AbstractPolicy());
  ASSERT_NE(result, nullptr);
  path file = current_path()/"doc"/"linearTransformer.dot";
  ofstream out(file);
  out << *result;
  MetaEvent eA(provided);
  eA.attribute(Test0::value())->value().set(0, 0, {1.1f});
  MetaEvent eB(intermediate);
  eB.attribute(Test0::value())->value().set(0, 0, {1100.0f});
  MetaEvent eC(goal);
  eC.attribute(Test0::value())->value().set(0, 0, {1100});
  EXPECT_CALL(*trans["b"], call(eA))
    .Times(1).WillOnce(Return(Events{eB}));
  EXPECT_CALL(*trans["a"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["a"], call(eB))
    .Times(1).WillOnce(Return(Events{eC}));
  Events res0 = (*result)(eA);
  ASSERT_GE(res0.size(), 1U) << "No events generated";
  EXPECT_EQ(res0.front(), eC);
}

TEST_F(CompositeTransformSuite, treeCreateTest) {
  using Events = Transformer::Events;
  EXPECT_CALL(c, create(goal, EventTypes({intermediate, intermediate2}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("c", goal, EventTypes({intermediate, intermediate2}), trans))));
  ASSERT_NE(b, nullptr);
  EXPECT_CALL(*b, create(intermediate, EventTypes({provided}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("b", intermediate, EventTypes({provided}),trans))));
  EXPECT_CALL(d, create(intermediate2, EventTypes({provided2}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("d", intermediate2, EventTypes({provided2}), trans))));
  TransPtr result = compTrans2.create(AbstractPolicy());
  ASSERT_NE(result, nullptr);
  path file = current_path()/"doc"/"treeTransformer.dot";
  ofstream out(file);
  out << *result;
  MetaEvent eA(provided);
  eA.attribute(Test0::value())->value().set(0, 0, {1.0f});
  MetaEvent eB(provided2);
  eB.attribute(Test1::value())->value().set(0, 0, {2.0f});
  MetaEvent eC(intermediate);
  eC.attribute(Test0::value())->value().set(0, 0, {3.0f});
  MetaEvent eD(intermediate2);
  eD.attribute(Test1::value())->value().set(0, 0, {4.0f});
  MetaEvent eE(goal);
  eE.attribute(Test0::value())->value().set(0, 0, {5.0f});
  EXPECT_CALL(*trans["b"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["b"], call(eA))
    .Times(1).WillOnce(Return(Events{eC}));
  EXPECT_CALL(*trans["d"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["d"], call(eB))
    .Times(1).WillOnce(Return(Events{eD}));
  EXPECT_CALL(*trans["c"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["c"], call(eD))
    .Times(1);
  EXPECT_CALL(*trans["c"], call(eC))
    .Times(1).WillOnce(Return(Events{eE}));
  Events res0 = (*result)(eA);
  Events res1 = (*result)(eB);
  move(res1.begin(), res1.end(), back_inserter(res0));
  ASSERT_GE(res0.size(), 1U) << "No events generated";
  EXPECT_EQ(res0.front(), eE);
}

TEST_F(CompositeTransformSuite, insertTest) {
  using Vertex = CompositeTransformation::Vertex;
  auto edges = boost::edges(compTrans.graph());
  ASSERT_NE(edges.first, edges.second);
  Vertex insertPoint = boost::target(*edges.first, compTrans.graph());
  ASSERT_NO_THROW(compTrans.add(move(compTrans2), insertPoint, compTrans.in().at(0)));
  path file = current_path()/"doc"/"insertCompTrans.dot";
  ofstream out(file);
  out << compTrans;
  ASSERT_EQ(out_degree(insertPoint, compTrans.graph()), 1U);
  auto outEdges = boost::out_edges(insertPoint, compTrans.graph());
  Vertex cV = boost::target(*outEdges.first, compTrans.graph());
  ASSERT_EQ(out_degree(cV, compTrans.graph()), 2U);
  outEdges = boost::out_edges(cV, compTrans.graph());
  Vertex bV = boost::target(*outEdges.first, compTrans.graph());
  Vertex dV = boost::target(*++outEdges.first, compTrans.graph());
  EXPECT_EQ(compTrans.graph()[cV].trans(), &c);
  EXPECT_EQ(compTrans.graph()[bV].trans(), b.get());
  EXPECT_EQ(compTrans.graph()[dV].trans(), &d);
  EXPECT_THAT(compTrans.in(), UnorderedElementsAre(provided, provided2));
}

}
<commit_msg>Doc: add documentation for Unit-Tests of CompositeTransformation<commit_after>
#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <CompositeTransformation.h>
#include <MetaEvent.h>

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

/** \class CompositeTransformation
 *
 *  \test CompositeTransformSuite testing creation of linear and tree-like
 *  CompositeTransformations. Additionally checks correctness of input
 *  EventTypes and created CompositeTransformers. Finally tests correct merging
 *  of two CompositeTransformations in ::tests::compTrans
 **/

namespace tests {
/** \brief CompositeTransformation Tests **/
namespace compTrans {
using namespace std;

using ::testing::_;
using ::testing::Return;
using ::testing::AtLeast;
using ::testing::UnorderedElementsAre;
using boost::filesystem::ofstream;
using boost::filesystem::current_path;
using boost::filesystem::path;

/** \brief Fixture for all CompositeTransformation UnitTests **/
struct CompositeTransformSuite : public ::testing::Test {

  /** \brief forward declaration of EventTypes **/
  using EventTypes = Transformer::EventTypes;
  /** \brief forward declaration of TransPtr **/
  using TransPtr   = Transformation::TransPtr;

  /** \brief helper function to compare MetaEvents based on their pointers
   *  \param a first MetaEvent pointer
   *  \param b second MetaEvent pointer
   *  \return true if equal according to MetaEvent::operator==, false otherwise
   **/
  static bool comp(const MetaEvent* const a, const MetaEvent* const b) {
    return *a==*b;
  }

  /// Mock-Implementation of Unary Transformer
  struct TestTransformer : public Transformer {
    /// Name of this Mock-Object
    string name;
    /** \brief Create Mock-Transformer
     *  \param name Name of this Mock-Object
     *  \param out Goal EventType
     *  \param in single elementary vector of input EventTypes
     *  \param trans Transformer lookup structure to register this instance
     **/
    TestTransformer(const string& name, const EventType& out, const EventTypes& in,
                    map<string, TestTransformer*>& trans)
      : Transformer(out, in), name(name) {
      trans[name]=this;
    }
    MOCK_CONST_METHOD1(check, bool(const MetaEvent&));
    MOCK_CONST_METHOD1(call, Events(const MetaEvent&));
    virtual Events operator()(const MetaEvent& e) { return call(e); }
    virtual void print(ostream& o) const { o << name; }
  };

  /// Mock-Implementation of Unary Transformation
  struct TestTransformation : public Transformation {
    /// Name of this Mock-Object
    string name;
    /** \brief Create Mock-Transformation
     *  \param name Name of this Mock-Object
     *  \param arity Arity of transformation
     **/
    TestTransformation(const string& name, size_t arity)
      : Transformation(Type::attribute, arity, EventID::any), name(name) { }

    MOCK_CONST_METHOD3(in, EventTypes(const EventType& goal, const EventType& provided, const MetaFilter& filter));
    MOCK_CONST_METHOD2(in, EventIDs(EventID goal, const MetaFilter& filter));
    MOCK_CONST_METHOD4(create, TransPtr(const EventType& out, const EventTypes& in, const AbstractPolicy& policy, const MetaFilter& filter));
    virtual void print(ostream& o) const { o << name; }
  };

  /// Lookup structure to map TestTransformation names to instances
  map<string, TestTransformer*> trans;
  /// Statically allocated unary TestTransformations
  TestTransformation a, c, d;
  /// Linear CompositeTransformation containing a and b
  CompositeTransformation compTrans;
  /// Tree-like CompositeTransformation containing c, b and d
  CompositeTransformation compTrans2;
  /// Dynamically allocated unary TestTransformation
  shared_ptr<const TestTransformation> b;
  /// Final goal EventType: single Attribute Test0 of certain 1x1 float
  EventType goal;
  /// Provided EventType: single Attribute Test0 of certain 1x1 int with scale 1/1000
  EventType provided;
  /// Provided EventType: single Attribute Test1 of certain 1x1 int with scale 1/1000
  EventType provided2;
  /// Intermediate EventType: single Attribute Test0 of certain 1x1 float with scale 1/1000
  EventType intermediate;
  /// Intermediate EventType: single Attribute Test1 of certain 1x1 float with scale 1/1000
  EventType intermediate2;

  /// Definition of non-static AttrID used only testing
  using Test0 = ::id::attribute::AttrID<251>;
  /// Definition of non-static AttrID used only testing
  using Test1 = ::id::attribute::AttrID<252>;

  /// Create four TestTransformations
  CompositeTransformSuite()
    : a("a", 1), c("c", 2), d("d", 1), b(new TestTransformation("b", 1))
  {}

  /// Create CompositeTransformations compTrans and compTrans2
  void SetUp() {

    ValueType goalVT(id::type::Float::value(), 1, 1, false);

    AttributeType goalAT(Test0::value(), goalVT, Scale<>(), Dimensionless());
    AttributeType int2AT(Test1::value(), goalVT, Scale<std::ratio<1, 1000>>(), Dimensionless());
    AttributeType intAT = goalAT;
    AttributeType provAT = intAT;
    AttributeType prov2AT = int2AT;

    intAT.scale().denom(1000);
    provAT.scale().denom(1000);
    provAT.value().typeId(id::type::Int32::value());
    prov2AT.value().typeId(id::type::Int32::value());

    goal.add(goalAT);
    intermediate.add(intAT);
    provided.add(provAT);
    intermediate2.add(int2AT);
    provided2.add(prov2AT);

    ASSERT_NE(b, nullptr);
    EXPECT_CALL(a, in(goal, provided, _))
      .Times(1).WillOnce(Return(EventTypes({intermediate})));
    EXPECT_CALL(*b, in(intermediate, provided, _))
      .Times(AtLeast(1)).WillRepeatedly(Return(EventTypes({provided})));
    EXPECT_CALL(c, in(goal, _, _))
      .Times(1).WillOnce(Return(EventTypes({intermediate, intermediate2})));
    EXPECT_CALL(d, in(intermediate2, provided2, _))
      .Times(1).WillOnce(Return(EventTypes({provided2})));
    auto r0 = compTrans.add(&a, goal, provided);
    ASSERT_TRUE(r0.second);
    auto r1 = compTrans.add(b.get(), r0.first, intermediate, provided);
    ASSERT_TRUE(r1.second);
    ofstream out(current_path()/"doc"/"linTransformation.dot");
    out << compTrans;
    auto r2 = compTrans2.add(&c, goal, EventType());
    ASSERT_TRUE(r2.second);
    auto r3 = compTrans2.add(b.get(), r2.first, intermediate, provided);
    ASSERT_TRUE(r3.second);
    auto r4 = compTrans2.add(&d, r2.first, intermediate2, provided2);
    ASSERT_TRUE(r4.second);
    out.close();
    out.open(current_path()/"doc"/"treeTransformation.dot");
    out << compTrans2;
  }
};

/** \brief Unit-Test testing creation of a linear CompositeTransformation **/
TEST_F(CompositeTransformSuite, linearTest) {
  using Graph = CompositeTransformation::Graph;
  using Vertex = CompositeTransformation::Vertex;
  using Edge = Graph::edge_descriptor;
  const Graph& g = compTrans.graph();
  ASSERT_EQ(boost::num_vertices(g), 2U);
  auto v = boost::vertices(g);
  Vertex testAV = *v.first;
  const Transformation& testA = *g[testAV].trans();
  EXPECT_EQ(testA, a);
  auto out = out_edges(testAV, g);
  ASSERT_NE(out.first, out.second);
  Edge testBE = *out.first;
  Vertex testBV = target(testBE, g);
  const Transformation& testB = *g[testBV].trans();
  ASSERT_NE(b, nullptr);
  EXPECT_EQ(testB, *b);
}

/** \brief Unit-Test checking correctness of input EventTypes of a linear CompositeTransformation**/
TEST_F(CompositeTransformSuite, linearInTest) {
  auto result = compTrans.in();
  EXPECT_EQ(result, EventTypes({provided}));
}

/** \brief Unit-Test testing creation of a tree-like CompositeTransformation **/
TEST_F(CompositeTransformSuite, treeTest) {
  using Graph = CompositeTransformation::Graph;
  using Vertex = CompositeTransformation::Vertex;
  using Edge = Graph::edge_descriptor;
  const Graph& g = compTrans2.graph();
  ASSERT_EQ(boost::num_vertices(g), 3U);
  auto v = boost::vertices(g);
  Vertex testCV = *v.first;
  const Transformation& testC = *g[testCV].trans();
  EXPECT_EQ(testC, c);
  auto out = out_edges(testCV, g);
  ASSERT_NE(out.first, out.second);
  Edge testBE = *out.first;
  Vertex testBV = target(testBE, g);
  const Transformation& testB = *g[testBV].trans();
  ASSERT_NE(b, nullptr);
  EXPECT_EQ(testB, *b);
  Edge testDE = *++out.first;
  Vertex testDV = target(testDE, g);
  const Transformation& testD = *g[testDV].trans();
  ASSERT_NE(b, nullptr);
  EXPECT_EQ(testD, d);
}

/** \brief Unit-Test checking correctness of input EventTypes of a tree-like CompositeTransformation**/
TEST_F(CompositeTransformSuite, treeInTest) {
  auto result = compTrans2.in();
  ASSERT_FALSE(result.empty());
  EXPECT_EQ(result, EventTypes({provided, provided2}));
}

/** \brief Unit-Test checking correct creation of CompositeTransformer from linear CompositeTransformation **/
TEST_F(CompositeTransformSuite, linearCreateTest) {
  using Events = Transformer::Events;
  EXPECT_CALL(a, create(goal, EventTypes({intermediate}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("a", goal, EventTypes({intermediate}), trans))));
  ASSERT_NE(b, nullptr);
  EXPECT_CALL(*b, create(intermediate, EventTypes({provided}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("b", intermediate, EventTypes({provided}),trans))));
  TransPtr result = compTrans.create(AbstractPolicy());
  ASSERT_NE(result, nullptr);
  path file = current_path()/"doc"/"linearTransformer.dot";
  ofstream out(file);
  out << *result;
  MetaEvent eA(provided);
  eA.attribute(Test0::value())->value().set(0, 0, {1.1f});
  MetaEvent eB(intermediate);
  eB.attribute(Test0::value())->value().set(0, 0, {1100.0f});
  MetaEvent eC(goal);
  eC.attribute(Test0::value())->value().set(0, 0, {1100});
  EXPECT_CALL(*trans["b"], call(eA))
    .Times(1).WillOnce(Return(Events{eB}));
  EXPECT_CALL(*trans["a"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["a"], call(eB))
    .Times(1).WillOnce(Return(Events{eC}));
  Events res0 = (*result)(eA);
  ASSERT_GE(res0.size(), 1U) << "No events generated";
  EXPECT_EQ(res0.front(), eC);
}

/** \brief Unit-Test checking correct creation of CompositeTransformer from tree-like CompositeTransformation **/
TEST_F(CompositeTransformSuite, treeCreateTest) {
  using Events = Transformer::Events;
  EXPECT_CALL(c, create(goal, EventTypes({intermediate, intermediate2}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("c", goal, EventTypes({intermediate, intermediate2}), trans))));
  ASSERT_NE(b, nullptr);
  EXPECT_CALL(*b, create(intermediate, EventTypes({provided}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("b", intermediate, EventTypes({provided}),trans))));
  EXPECT_CALL(d, create(intermediate2, EventTypes({provided2}), _, _))
    .Times(1).WillOnce(Return(TransPtr(new TestTransformer("d", intermediate2, EventTypes({provided2}), trans))));
  TransPtr result = compTrans2.create(AbstractPolicy());
  ASSERT_NE(result, nullptr);
  path file = current_path()/"doc"/"treeTransformer.dot";
  ofstream out(file);
  out << *result;
  MetaEvent eA(provided);
  eA.attribute(Test0::value())->value().set(0, 0, {1.0f});
  MetaEvent eB(provided2);
  eB.attribute(Test1::value())->value().set(0, 0, {2.0f});
  MetaEvent eC(intermediate);
  eC.attribute(Test0::value())->value().set(0, 0, {3.0f});
  MetaEvent eD(intermediate2);
  eD.attribute(Test1::value())->value().set(0, 0, {4.0f});
  MetaEvent eE(goal);
  eE.attribute(Test0::value())->value().set(0, 0, {5.0f});
  EXPECT_CALL(*trans["b"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["b"], call(eA))
    .Times(1).WillOnce(Return(Events{eC}));
  EXPECT_CALL(*trans["d"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["d"], call(eB))
    .Times(1).WillOnce(Return(Events{eD}));
  EXPECT_CALL(*trans["c"], call(_))
    .WillRepeatedly(Return(Events{}));
  EXPECT_CALL(*trans["c"], call(eD))
    .Times(1);
  EXPECT_CALL(*trans["c"], call(eC))
    .Times(1).WillOnce(Return(Events{eE}));
  Events res0 = (*result)(eA);
  Events res1 = (*result)(eB);
  move(res1.begin(), res1.end(), back_inserter(res0));
  ASSERT_GE(res0.size(), 1U) << "No events generated";
  EXPECT_EQ(res0.front(), eE);
}

/** \brief Unit-Test checking correct merging of linear and tree-like CompositeTransformation **/
TEST_F(CompositeTransformSuite, insertTest) {
  using Vertex = CompositeTransformation::Vertex;
  auto edges = boost::edges(compTrans.graph());
  ASSERT_NE(edges.first, edges.second);
  Vertex insertPoint = boost::target(*edges.first, compTrans.graph());
  ASSERT_NO_THROW(compTrans.add(move(compTrans2), insertPoint, compTrans.in().at(0)));
  path file = current_path()/"doc"/"insertCompTrans.dot";
  ofstream out(file);
  out << compTrans;
  ASSERT_EQ(out_degree(insertPoint, compTrans.graph()), 1U);
  auto outEdges = boost::out_edges(insertPoint, compTrans.graph());
  Vertex cV = boost::target(*outEdges.first, compTrans.graph());
  ASSERT_EQ(out_degree(cV, compTrans.graph()), 2U);
  outEdges = boost::out_edges(cV, compTrans.graph());
  Vertex bV = boost::target(*outEdges.first, compTrans.graph());
  Vertex dV = boost::target(*++outEdges.first, compTrans.graph());
  EXPECT_EQ(compTrans.graph()[cV].trans(), &c);
  EXPECT_EQ(compTrans.graph()[bV].trans(), b.get());
  EXPECT_EQ(compTrans.graph()[dV].trans(), &d);
  EXPECT_THAT(compTrans.in(), UnorderedElementsAre(provided, provided2));
}

}}
<|endoftext|>


<commit_before>/*! @file zerocrossings.cc
 *  @brief Tests for SoundFeatureExtraction::Transforms::ZeroCrossings.
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include <gtest/gtest.h>
#include <math.h>
#include "src/transforms/zerocrossings.h"

using SoundFeatureExtraction::Formats::WindowF;
using SoundFeatureExtraction::Formats::WindowFormatF;
using SoundFeatureExtraction::BuffersBase;
using SoundFeatureExtraction::Transforms::ZeroCrossings;

class ZeroCrossingsTest : public ZeroCrossings, public testing::Test {
 public:
  BuffersBase<WindowF> Input;
  BuffersBase<int32_t> Output;
  int Size;

  virtual void SetUp() {
    Size = 450;
    Input.Initialize(1, Size);
    for (int i = 0; i < Size; i++) {
      // Always liked exotic functions
      Input[0]->Data.get()[i] = sinf(i * M_PI / 2);
    }
    Input[0]->Data.get()[Size - 1] = 0;
    Input[0]->Data.get()[Size - 2] = 0;
    auto format = std::make_shared<WindowFormatF>(Size * 1000 / 18000, 18000);
    SetInputFormat(format);
    InitializeBuffers(Input, &Output);
  }
};

TEST_F(ZeroCrossingsTest, Do) {
  Do(Input, &Output);
  ASSERT_EQ(Size / 2 + 1, *Output[0]);
}

#define CLASS_NAME ZeroCrossingsTest
#define ITER_COUNT 400000
#define NO_OUTPUT
#include "src/primitives/energy.h"
#include "tests/transforms/benchmark.inc"

#include "tests/google/src/gtest_main.cc"
<commit_msg>Added non-SIMD test to ZeroCrossings<commit_after>/*! @file zerocrossings.cc
 *  @brief Tests for SoundFeatureExtraction::Transforms::ZeroCrossings.
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include <gtest/gtest.h>
#include <math.h>
#include "src/transforms/zerocrossings.h"

using SoundFeatureExtraction::Formats::WindowF;
using SoundFeatureExtraction::Formats::WindowFormatF;
using SoundFeatureExtraction::BuffersBase;
using SoundFeatureExtraction::Transforms::ZeroCrossings;

class ZeroCrossingsTest : public ZeroCrossings, public testing::Test {
 public:
  BuffersBase<WindowF> Input;
  BuffersBase<int32_t> Output;
  int Size;

  virtual void SetUp() {
    Size = 450;
    Input.Initialize(1, Size);
    for (int i = 0; i < Size; i++) {
      // Always liked exotic functions
      Input[0]->Data.get()[i] = sinf(i * M_PI / 2);
    }
    Input[0]->Data.get()[Size - 1] = 0;
    Input[0]->Data.get()[Size - 2] = 0;
    auto format = std::make_shared<WindowFormatF>(Size * 1000 / 18000, 18000);
    SetInputFormat(format);
    InitializeBuffers(Input, &Output);
  }
};

TEST_F(ZeroCrossingsTest, Do) {
  Do(Input, &Output);
  ASSERT_EQ(Size / 2 + 1, *Output[0]);
  int slowres = Do(false, Input[0]->Data.get(), Size);
  ASSERT_EQ(Size / 2 + 1, slowres);
}

#define CLASS_NAME ZeroCrossingsTest
#define ITER_COUNT 400000
#define NO_OUTPUT
#include "src/primitives/energy.h"
#include "tests/transforms/benchmark.inc"

#include "tests/google/src/gtest_main.cc"
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: versionhelper.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 12:08:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <stdlib.h>
#include "versionhelper.hxx"

#include <rtl/ustring.hxx>
#include <rtl/string.hxx>

// -----------------------------------------------------------------------------
VersionHelper::VersionHelper(rtl::OUString const& _sDLLName, GetOpt & _aOptions)
        :DynamicLibraryHelper(_sDLLName, _aOptions),
         m_pInfo(NULL)
{
    // try to get the entry pointer
    FktGetVersionInfoPtr pFunc = (FktGetVersionInfoPtr) m_pModule->getSymbol( rtl::OUString::createFromAscii( "GetVersionInfo" ) );

    if (pFunc)
    {
        const VersionInfo *pVersion = (pFunc)();
        m_pInfo = pVersion;
    }
}

//# void VersionHelper::print(std::ostream &stream)
//# {
//#     stream << "  Time:" << getTime()   << std::endl;
//#     stream << "  Date:" << getDate()   << std::endl;
//#     stream << "   Upd:" << getUpd()    << std::endl;
//#     stream << " Minor:" << getMinor()  << std::endl;
//#     stream << " Build:" << getBuild()  << std::endl;
//#     stream << "Inpath:" << getInpath() << std::endl;
//# }
//#
//# std::ostream & operator <<( std::ostream &stream, VersionHelper &_aVersion )
//# {
//#     _aVersion.print (stream);
//#     return stream;
//# }
//#
// -----------------------------------------------------------------------------

bool VersionHelper::isOk() const
{
    if (m_pInfo != NULL) return true;
    return false;
}

rtl::OString VersionHelper::getTime() const
{
    return m_pInfo->pTime;
}
rtl::OString VersionHelper::getDate() const
{
    return m_pInfo->pDate;
}
rtl::OString VersionHelper::getUpd() const
{
    return m_pInfo->pUpd;
}
rtl::OString VersionHelper::getMinor() const
{
    return m_pInfo->pMinor;
}
rtl::OString VersionHelper::getBuild() const
{
    return m_pInfo->pBuild;
}
rtl::OString VersionHelper::getInpath() const
{
    return m_pInfo->pInpath;
}

void VersionHelper::printall(FILE * out)
{
    if (isOk())
    {
        rtl::OString aStr = getTime();
        fprintf(out, "  Time:%s\n", aStr.getStr()  );
        fprintf(out, "  Date:%s\n", getDate().getStr()  );
        fprintf(out, "   Upd:%s\n", getUpd().getStr()   );
        fprintf(out, " Minor:%s\n", getMinor().getStr() );
        fprintf(out, " Build:%s\n", getBuild().getStr() );
        fprintf(out, "Inpath:%s\n", getInpath().getStr());

        fflush(out);
    }
    else
    {
        fprintf(stderr, "error: No version info found.\n");
    }
}

<commit_msg>INTEGRATION: CWS warnings01 (1.6.50); FILE MERGED 2005/09/22 22:38:44 sb 1.6.50.2: RESYNC: (1.6-1.7); FILE MERGED 2005/09/14 10:21:53 sb 1.6.50.1: #i53898# Made code warning-free.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: versionhelper.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 02:28:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <stdlib.h>
#include "versionhelper.hxx"

#include <rtl/ustring.hxx>
#include <rtl/string.hxx>

// -----------------------------------------------------------------------------
VersionHelper::VersionHelper(rtl::OUString const& _sDLLName, GetOpt & _aOptions)
        :DynamicLibraryHelper(_sDLLName, _aOptions),
         m_pInfo(NULL)
{
    // try to get the entry pointer
    FktGetVersionInfoPtr pFunc = (FktGetVersionInfoPtr)
        m_pModule->getFunctionSymbol(
            rtl::OUString::createFromAscii( "GetVersionInfo" ) );

    if (pFunc)
    {
        const VersionInfo *pVersion = (pFunc)();
        m_pInfo = pVersion;
    }
}

//# void VersionHelper::print(std::ostream &stream)
//# {
//#     stream << "  Time:" << getTime()   << std::endl;
//#     stream << "  Date:" << getDate()   << std::endl;
//#     stream << "   Upd:" << getUpd()    << std::endl;
//#     stream << " Minor:" << getMinor()  << std::endl;
//#     stream << " Build:" << getBuild()  << std::endl;
//#     stream << "Inpath:" << getInpath() << std::endl;
//# }
//#
//# std::ostream & operator <<( std::ostream &stream, VersionHelper &_aVersion )
//# {
//#     _aVersion.print (stream);
//#     return stream;
//# }
//#
// -----------------------------------------------------------------------------

bool VersionHelper::isOk() const
{
    if (m_pInfo != NULL) return true;
    return false;
}

rtl::OString VersionHelper::getTime() const
{
    return m_pInfo->pTime;
}
rtl::OString VersionHelper::getDate() const
{
    return m_pInfo->pDate;
}
rtl::OString VersionHelper::getUpd() const
{
    return m_pInfo->pUpd;
}
rtl::OString VersionHelper::getMinor() const
{
    return m_pInfo->pMinor;
}
rtl::OString VersionHelper::getBuild() const
{
    return m_pInfo->pBuild;
}
rtl::OString VersionHelper::getInpath() const
{
    return m_pInfo->pInpath;
}

void VersionHelper::printall(FILE * out)
{
    if (isOk())
    {
        rtl::OString aStr = getTime();
        fprintf(out, "  Time:%s\n", aStr.getStr()  );
        fprintf(out, "  Date:%s\n", getDate().getStr()  );
        fprintf(out, "   Upd:%s\n", getUpd().getStr()   );
        fprintf(out, " Minor:%s\n", getMinor().getStr() );
        fprintf(out, " Build:%s\n", getBuild().getStr() );
        fprintf(out, "Inpath:%s\n", getInpath().getStr());

        fflush(out);
    }
    else
    {
        fprintf(stderr, "error: No version info found.\n");
    }
}

<|endoftext|>


<commit_before>#ifndef __FUTURE_HPP__
#define __FUTURE_HPP__

#include "latch.hpp"

namespace process {

template <typename T>
class Promise;

template <typename T>
class Future
{
public:
  Future();
  Future(const T& _t);
  Future(const Future<T>& that);
  Future<T>& operator = (const Future<T>& that);
  virtual ~Future();
  bool ready() const;
  bool await(double secs = 0) const;
  T get() const;
  operator T () const;

private:
  friend class Promise<T>;

  void set(const T& _t);

  int* refs;
  T** t;
  Latch* latch;
};

template <typename T>
Future<T>::Future()
{
  refs = new int;
  *refs = 1;
  t = new T*;
  *t = NULL;
  latch = new Latch();
}

template <typename T>
Future<T>::Future(const T& _t)
{
  refs = new int;
  *refs = 1;
  t = new T*;
  *t = NULL;
  latch = new Latch();
  set(_t);
}

template <typename T>
Future<T>::Future(const Future<T>& that)
{
  assert(that.refs > 0);
  __sync_fetch_and_add(that.refs, 1);
  refs = that.refs;
  t = that.t;
  latch = that.latch;
}

template <typename T>
Future<T>& Future<T>::operator = (const Future<T>& that)
{
  if (this != &that) {
    // Destructor ...
    assert(refs != NULL);
    if (__sync_sub_and_fetch(refs, 1) == 0) {
      delete refs;
      assert(t != NULL);
      if (*t != NULL)
        delete *t;
      assert(latch != NULL);
      delete latch;
    }

    // Copy constructor ...
    assert(that.refs > 0);
    __sync_fetch_and_add(that.refs, 1);
    refs = that.refs;
    t = that.t;
    latch = that.latch;
  }
}

template <typename T>
Future<T>::~Future()
{
  assert(refs != NULL);
  if (__sync_sub_and_fetch(refs, 1) == 0) {
    delete refs;
    assert(t != NULL);
    if (*t != NULL)
      delete *t;
    assert(latch != NULL);
    delete latch;
  }
}

template <typename T>
bool Future<T>::ready() const
{
  assert(t != NULL);
  if (*t != NULL)
    return true;
  return false;
}

template <typename T>
bool Future<T>::await(double secs) const
{
  if (ready())
    return true;
  assert(latch != NULL);
  return latch->await(secs);
}

template <typename T>
T Future<T>::get() const
{
  if (ready())
    return **t;
  await();
  assert(t != NULL && *t != NULL);
  return **t;
}

template <typename T>
Future<T>::operator T () const
{
  return get();
}

template <typename T>
void Future<T>::set(const T& _t)
{
  assert(t != NULL && *t == NULL);
  *t = new T(_t);
  latch->trigger();
}

}  // namespace process {

#endif // __FUTURE_HPP__
<commit_msg>Added support for creating a Future out of a Promise.<commit_after>#ifndef __FUTURE_HPP__
#define __FUTURE_HPP__

#include "latch.hpp"

namespace process {

template <typename T>
class Promise;

template <typename T>
class Future
{
public:
  Future();
  Future(Promise<T>* promise);
  Future(const T& _t);
  Future(const Future<T>& that);
  Future<T>& operator = (const Future<T>& that);
  virtual ~Future();
  bool ready() const;
  bool await(double secs = 0) const;
  T get() const;
  operator T () const;

private:
  friend class Promise<T>;

  void set(const T& _t);

  int* refs;
  T** t;
  Latch* latch;
};

template <typename T>
Future<T>::Future()
{
  refs = new int;
  *refs = 1;
  t = new T*;
  *t = NULL;
  latch = new Latch();
}

template <typename T>
Future<T>::Future(Promise<T>* promise)
{
  refs = new int;
  *refs = 1;
  t = new T*;
  *t = NULL;
  latch = new Latch();
  assert(promise != NULL);
  promise->associate(*this);
}

template <typename T>
Future<T>::Future(const T& _t)
{
  refs = new int;
  *refs = 1;
  t = new T*;
  *t = NULL;
  latch = new Latch();
  set(_t);
}

template <typename T>
Future<T>::Future(const Future<T>& that)
{
  assert(that.refs > 0);
  __sync_fetch_and_add(that.refs, 1);
  refs = that.refs;
  t = that.t;
  latch = that.latch;
}

template <typename T>
Future<T>& Future<T>::operator = (const Future<T>& that)
{
  if (this != &that) {
    // Destructor ...
    assert(refs != NULL);
    if (__sync_sub_and_fetch(refs, 1) == 0) {
      delete refs;
      assert(t != NULL);
      if (*t != NULL)
        delete *t;
      assert(latch != NULL);
      delete latch;
    }

    // Copy constructor ...
    assert(that.refs > 0);
    __sync_fetch_and_add(that.refs, 1);
    refs = that.refs;
    t = that.t;
    latch = that.latch;
  }
}

template <typename T>
Future<T>::~Future()
{
  assert(refs != NULL);
  if (__sync_sub_and_fetch(refs, 1) == 0) {
    delete refs;
    assert(t != NULL);
    if (*t != NULL)
      delete *t;
    assert(latch != NULL);
    delete latch;
  }
}

template <typename T>
bool Future<T>::ready() const
{
  assert(t != NULL);
  if (*t != NULL)
    return true;
  return false;
}

template <typename T>
bool Future<T>::await(double secs) const
{
  if (ready())
    return true;
  assert(latch != NULL);
  return latch->await(secs);
}

template <typename T>
T Future<T>::get() const
{
  if (ready())
    return **t;
  await();
  assert(t != NULL && *t != NULL);
  return **t;
}

template <typename T>
Future<T>::operator T () const
{
  return get();
}

template <typename T>
void Future<T>::set(const T& _t)
{
  assert(t != NULL && *t == NULL);
  *t = new T(_t);
  latch->trigger();
}

}  // namespace process {

#endif // __FUTURE_HPP__
<|endoftext|>


<commit_before>/*
    Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "notificationcollector.h"
#include "storage/datastore.h"
#include "storage/entity.h"
#include "handlerhelper.h"

#include <QtCore/QDebug>

using namespace Akonadi;

NotificationCollector::NotificationCollector(QObject* parent) :
  QObject( parent ),
  mDb( 0 )
{
}

Akonadi::NotificationCollector::NotificationCollector(DataStore * db) :
  QObject( db ),
  mDb( db )
{
  connect( db, SIGNAL(transactionCommitted()), SLOT(transactionCommitted()) );
  connect( db, SIGNAL(transactionRolledBack()), SLOT(transactionRolledBack()) );
}

Akonadi::NotificationCollector::~NotificationCollector()
{
}

void Akonadi::NotificationCollector::itemAdded( const PimItem &item,
                                                const Collection &collection,
                                                const QString & mimeType,
                                                const QByteArray & resource )
{
  itemNotification( NotificationMessage::Add, item, collection, Collection(), mimeType, resource );
}

void Akonadi::NotificationCollector::itemChanged( const PimItem &item,
                                                  const QSet<QByteArray> &changedParts,
                                                  const Collection &collection,
                                                  const QString & mimeType,
                                                  const QByteArray & resource )
{
  itemNotification( NotificationMessage::Modify, item, collection, Collection(), mimeType, resource, changedParts );
}

void Akonadi::NotificationCollector::itemMoved( const PimItem &item,
                                                const Collection &collectionSrc,
                                                const Collection &collectionDest,
                                                const QString &mimeType,
                                                const QByteArray &sourceResource )
{
  itemNotification( NotificationMessage::Move, item, collectionSrc, collectionDest, mimeType, sourceResource );
}

void Akonadi::NotificationCollector::itemRemoved( const PimItem &item,
                                                  const Collection &collection,
                                                  const QString & mimeType,
                                                  const QByteArray & resource )
{
  itemNotification( NotificationMessage::Remove, item, collection, Collection(), mimeType, resource );
}

void NotificationCollector::itemLinked(const PimItem & item, const Collection & collection)
{
  itemNotification( NotificationMessage::Link, item, collection, Collection(), QString(), QByteArray() );
}

void NotificationCollector::itemUnlinked(const PimItem & item, const Collection & collection)
{
  itemNotification( NotificationMessage::Unlink, item, collection, Collection(), QString(), QByteArray() );
}

void Akonadi::NotificationCollector::collectionAdded( const Collection &collection,
                                                      const QByteArray &resource )
{
  collectionNotification( NotificationMessage::Add, collection, collection.parentId(), -1, resource );
}

void Akonadi::NotificationCollector::collectionChanged( const Collection &collection,
                                                        const QList<QByteArray> &changes,
                                                        const QByteArray &resource )
{
  collectionNotification( NotificationMessage::Modify, collection, collection.parentId(), -1, resource, changes.toSet() );
}

void NotificationCollector::collectionMoved( const Collection &collection,
                                             const Collection &source,
                                             const QByteArray &resource,
                                             const QByteArray &destResource )
{
  collectionNotification( NotificationMessage::Move, collection, source.id(), collection.parentId(), resource, QSet<QByteArray>(), destResource );
}

void Akonadi::NotificationCollector::collectionRemoved( const Collection &collection,
                                                        const QByteArray &resource )
{
  collectionNotification( NotificationMessage::Remove, collection, collection.parentId(), -1, resource );
}

void NotificationCollector::collectionSubscribed( const Collection& collection,
                                                  const QByteArray& resource )
{
  collectionNotification( NotificationMessage::Subscribe, collection, collection.parentId(), -1, resource, QSet<QByteArray>() );
}

void NotificationCollector::collectionUnsubscribed( const Collection& collection,
                                                    const QByteArray& resource )
{
  collectionNotification( NotificationMessage::Unsubscribe, collection, collection.parentId(), -1, resource, QSet<QByteArray>() );
}

void Akonadi::NotificationCollector::transactionCommitted()
{
  dispatchNotifications();
}

void Akonadi::NotificationCollector::transactionRolledBack()
{
  clear();
}

void Akonadi::NotificationCollector::clear()
{
  mNotifications.clear();
}

void NotificationCollector::setSessionId(const QByteArray &sessionId)
{
  mSessionId = sessionId;
}

void NotificationCollector::itemNotification( NotificationMessage::Operation op,
                                              const PimItem & item,
                                              const Collection & collection,
                                              const Collection & collectionDest,
                                              const QString & mimeType,
                                              const QByteArray & resource,
                                              const QSet<QByteArray> &parts )
{
  NotificationMessage msg;
  msg.setSessionId( mSessionId );
  msg.setType( NotificationMessage::Item );
  msg.setOperation( op );
  msg.setUid( item.id() );
  msg.setRemoteId( item.remoteId() );
  msg.setItemParts( parts );

  //HACK: store remoteRevision in itemparts for deletion
  if ( op == NotificationMessage::Remove )
    msg.setItemParts( QSet<QByteArray>() << item.remoteRevision().toUtf8() );

  msg.setDestinationResource( collectionDest.resource().name().toLatin1() );

  Collection col = collection;
  if ( !col.isValid() )
    col = item.collection();
  msg.setParentCollection( col.id() );
  // will be valid if it is a move message
  msg.setParentDestCollection( collectionDest.id() );
  QString mt = mimeType;
  if ( mt.isEmpty() )
    mt = item.mimeType().name();
  msg.setMimeType( mt );
  QByteArray res = resource;
  if ( res.isEmpty() )
    res = col.resource().name().toLatin1();
  msg.setResource( res );
  dispatchNotification( msg );
}

void NotificationCollector::collectionNotification( NotificationMessage::Operation op,
                                                    const Collection & collection,
                                                    Collection::Id source,
                                                    Collection::Id destination,
                                                    const QByteArray & resource,
                                                    const QSet<QByteArray> &changes,
                                                    const QByteArray & destResource )
{
  NotificationMessage msg;
  msg.setType( NotificationMessage::Collection );
  msg.setOperation( op );
  msg.setSessionId( mSessionId );
  msg.setUid( collection.id() );
  msg.setRemoteId( collection.remoteId() );
  msg.setParentCollection( source );
  msg.setParentDestCollection( destination );
  msg.setDestinationResource( destResource );
  msg.setItemParts( changes );

  //HACK: store remoteRevision in itemparts for deletion
  if ( op == NotificationMessage::Remove )
    msg.setItemParts( QSet<QByteArray>() << collection.remoteRevision().toUtf8() );

  QByteArray res = resource;
  if ( res.isEmpty() )
    res = collection.resource().name().toLatin1();
  msg.setResource( res );
  dispatchNotification( msg );
}

void NotificationCollector::dispatchNotification(const NotificationMessage & msg)
{
  if ( !mDb || mDb->inTransaction() ) {
    NotificationMessage::appendAndCompress( mNotifications, msg );
  } else {
    NotificationMessage::List l;
    l << msg;
    emit notify( l );
  }
}

void NotificationCollector::dispatchNotifications()
{
  emit notify( mNotifications );
  clear();
}

#include "notificationcollector.moc"
<commit_msg>Only set the destination resource if we are moving.<commit_after>/*
    Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "notificationcollector.h"
#include "storage/datastore.h"
#include "storage/entity.h"
#include "handlerhelper.h"

#include <QtCore/QDebug>

using namespace Akonadi;

NotificationCollector::NotificationCollector(QObject* parent) :
  QObject( parent ),
  mDb( 0 )
{
}

Akonadi::NotificationCollector::NotificationCollector(DataStore * db) :
  QObject( db ),
  mDb( db )
{
  connect( db, SIGNAL(transactionCommitted()), SLOT(transactionCommitted()) );
  connect( db, SIGNAL(transactionRolledBack()), SLOT(transactionRolledBack()) );
}

Akonadi::NotificationCollector::~NotificationCollector()
{
}

void Akonadi::NotificationCollector::itemAdded( const PimItem &item,
                                                const Collection &collection,
                                                const QString & mimeType,
                                                const QByteArray & resource )
{
  itemNotification( NotificationMessage::Add, item, collection, Collection(), mimeType, resource );
}

void Akonadi::NotificationCollector::itemChanged( const PimItem &item,
                                                  const QSet<QByteArray> &changedParts,
                                                  const Collection &collection,
                                                  const QString & mimeType,
                                                  const QByteArray & resource )
{
  itemNotification( NotificationMessage::Modify, item, collection, Collection(), mimeType, resource, changedParts );
}

void Akonadi::NotificationCollector::itemMoved( const PimItem &item,
                                                const Collection &collectionSrc,
                                                const Collection &collectionDest,
                                                const QString &mimeType,
                                                const QByteArray &sourceResource )
{
  itemNotification( NotificationMessage::Move, item, collectionSrc, collectionDest, mimeType, sourceResource );
}

void Akonadi::NotificationCollector::itemRemoved( const PimItem &item,
                                                  const Collection &collection,
                                                  const QString & mimeType,
                                                  const QByteArray & resource )
{
  itemNotification( NotificationMessage::Remove, item, collection, Collection(), mimeType, resource );
}

void NotificationCollector::itemLinked(const PimItem & item, const Collection & collection)
{
  itemNotification( NotificationMessage::Link, item, collection, Collection(), QString(), QByteArray() );
}

void NotificationCollector::itemUnlinked(const PimItem & item, const Collection & collection)
{
  itemNotification( NotificationMessage::Unlink, item, collection, Collection(), QString(), QByteArray() );
}

void Akonadi::NotificationCollector::collectionAdded( const Collection &collection,
                                                      const QByteArray &resource )
{
  collectionNotification( NotificationMessage::Add, collection, collection.parentId(), -1, resource );
}

void Akonadi::NotificationCollector::collectionChanged( const Collection &collection,
                                                        const QList<QByteArray> &changes,
                                                        const QByteArray &resource )
{
  collectionNotification( NotificationMessage::Modify, collection, collection.parentId(), -1, resource, changes.toSet() );
}

void NotificationCollector::collectionMoved( const Collection &collection,
                                             const Collection &source,
                                             const QByteArray &resource,
                                             const QByteArray &destResource )
{
  collectionNotification( NotificationMessage::Move, collection, source.id(), collection.parentId(), resource, QSet<QByteArray>(), destResource );
}

void Akonadi::NotificationCollector::collectionRemoved( const Collection &collection,
                                                        const QByteArray &resource )
{
  collectionNotification( NotificationMessage::Remove, collection, collection.parentId(), -1, resource );
}

void NotificationCollector::collectionSubscribed( const Collection& collection,
                                                  const QByteArray& resource )
{
  collectionNotification( NotificationMessage::Subscribe, collection, collection.parentId(), -1, resource, QSet<QByteArray>() );
}

void NotificationCollector::collectionUnsubscribed( const Collection& collection,
                                                    const QByteArray& resource )
{
  collectionNotification( NotificationMessage::Unsubscribe, collection, collection.parentId(), -1, resource, QSet<QByteArray>() );
}

void Akonadi::NotificationCollector::transactionCommitted()
{
  dispatchNotifications();
}

void Akonadi::NotificationCollector::transactionRolledBack()
{
  clear();
}

void Akonadi::NotificationCollector::clear()
{
  mNotifications.clear();
}

void NotificationCollector::setSessionId(const QByteArray &sessionId)
{
  mSessionId = sessionId;
}

void NotificationCollector::itemNotification( NotificationMessage::Operation op,
                                              const PimItem & item,
                                              const Collection & collection,
                                              const Collection & collectionDest,
                                              const QString & mimeType,
                                              const QByteArray & resource,
                                              const QSet<QByteArray> &parts )
{
  NotificationMessage msg;
  msg.setSessionId( mSessionId );
  msg.setType( NotificationMessage::Item );
  msg.setOperation( op );
  msg.setUid( item.id() );
  msg.setRemoteId( item.remoteId() );
  msg.setItemParts( parts );

  //HACK: store remoteRevision in itemparts for deletion
  if ( op == NotificationMessage::Remove )
    msg.setItemParts( QSet<QByteArray>() << item.remoteRevision().toUtf8() );

  if ( collectionDest.isValid() ) // only relevant for moves
    msg.setDestinationResource( collectionDest.resource().name().toLatin1() );

  Collection col = collection;
  if ( !col.isValid() )
    col = item.collection();
  msg.setParentCollection( col.id() );
  // will be valid if it is a move message
  msg.setParentDestCollection( collectionDest.id() );
  QString mt = mimeType;
  if ( mt.isEmpty() )
    mt = item.mimeType().name();
  msg.setMimeType( mt );
  QByteArray res = resource;
  if ( res.isEmpty() )
    res = col.resource().name().toLatin1();
  msg.setResource( res );
  dispatchNotification( msg );
}

void NotificationCollector::collectionNotification( NotificationMessage::Operation op,
                                                    const Collection & collection,
                                                    Collection::Id source,
                                                    Collection::Id destination,
                                                    const QByteArray & resource,
                                                    const QSet<QByteArray> &changes,
                                                    const QByteArray & destResource )
{
  NotificationMessage msg;
  msg.setType( NotificationMessage::Collection );
  msg.setOperation( op );
  msg.setSessionId( mSessionId );
  msg.setUid( collection.id() );
  msg.setRemoteId( collection.remoteId() );
  msg.setParentCollection( source );
  msg.setParentDestCollection( destination );
  msg.setDestinationResource( destResource );
  msg.setItemParts( changes );

  //HACK: store remoteRevision in itemparts for deletion
  if ( op == NotificationMessage::Remove )
    msg.setItemParts( QSet<QByteArray>() << collection.remoteRevision().toUtf8() );

  QByteArray res = resource;
  if ( res.isEmpty() )
    res = collection.resource().name().toLatin1();
  msg.setResource( res );
  dispatchNotification( msg );
}

void NotificationCollector::dispatchNotification(const NotificationMessage & msg)
{
  if ( !mDb || mDb->inTransaction() ) {
    NotificationMessage::appendAndCompress( mNotifications, msg );
  } else {
    NotificationMessage::List l;
    l << msg;
    emit notify( l );
  }
}

void NotificationCollector::dispatchNotifications()
{
  emit notify( mNotifications );
  clear();
}

#include "notificationcollector.moc"
<|endoftext|>