<commit_before>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/app/atom_main.h"

#include <stdlib.h>
#include <string.h>

#if defined(OS_WIN)
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

#include <windows.h>
#include <shellscalingapi.h>
#include <tchar.h>
#include <shellapi.h>

#include "atom/app/atom_main_delegate.h"
#include "atom/common/crash_reporter/win/crash_service_main.h"
#include "base/environment.h"
#include "base/win/windows_version.h"
#include "content/public/app/startup_helper_win.h"
#include "sandbox/win/src/sandbox_types.h"
#include "ui/gfx/win/dpi.h"
#elif defined(OS_LINUX)  // defined(OS_WIN)
#include "atom/app/atom_main_delegate.h"  // NOLINT
#include "content/public/app/content_main.h"
#else  // defined(OS_LINUX)
#include "atom/app/atom_library_main.h"
#endif  // defined(OS_MACOSX)

#include "atom/app/node_main.h"
#include "atom/common/atom_command_line.h"
#include "base/i18n/icu_util.h"

#if defined(OS_WIN)

namespace {

// Win8.1 supports monitor-specific DPI scaling.
bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
  typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
  SetProcessDpiAwarenessPtr set_process_dpi_awareness_func =
      reinterpret_cast<SetProcessDpiAwarenessPtr>(
          GetProcAddress(GetModuleHandleA("user32.dll"),
                         "SetProcessDpiAwarenessInternal"));
  if (set_process_dpi_awareness_func) {
    HRESULT hr = set_process_dpi_awareness_func(value);
    if (SUCCEEDED(hr)) {
      VLOG(1) << "SetProcessDpiAwareness succeeded.";
      return true;
    } else if (hr == E_ACCESSDENIED) {
      LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. "
          "Function called twice, or manifest was used.";
    }
  }
  return false;
}

// This function works for Windows Vista through Win8. Win8.1 must use
// SetProcessDpiAwareness[Wrapper].
BOOL SetProcessDPIAwareWrapper() {
  typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
  SetProcessDPIAwarePtr set_process_dpi_aware_func =
      reinterpret_cast<SetProcessDPIAwarePtr>(
      GetProcAddress(GetModuleHandleA("user32.dll"),
                      "SetProcessDPIAware"));
  return set_process_dpi_aware_func &&
    set_process_dpi_aware_func();
}

void EnableHighDPISupport() {
  if (!SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) {
    SetProcessDPIAwareWrapper();
  }
}

}  // namespace

int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
  int argc = 0;
  wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);

  scoped_ptr<base::Environment> env(base::Environment::Create());

  // Make output work in console if we are not in cygiwn.
  std::string os;
  if (env->GetVar("OS", &os) && os != "cygwin") {
    AttachConsole(ATTACH_PARENT_PROCESS);

    FILE* dontcare, *out, *err;
    out = fopen("out.txt", "w");
    err = fopen("err.txt", "w");
    freopen_s(&out, "CON", "w", stdout);
    freopen_s(&err, "CON", "w", stderr);
    freopen_s(&dontcare, "CON", "r", stdin);
  }

  // Convert argv to to UTF8
  char** argv = new char*[argc];
  for (int i = 0; i < argc; i++) {
    // Compute the size of the required buffer
    DWORD size = WideCharToMultiByte(CP_UTF8,
                                     0,
                                     wargv[i],
                                     -1,
                                     NULL,
                                     0,
                                     NULL,
                                     NULL);
    if (size == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
    // Do the actual conversion
    argv[i] = new char[size];
    DWORD result = WideCharToMultiByte(CP_UTF8,
                                       0,
                                       wargv[i],
                                       -1,
                                       argv[i],
                                       size,
                                       NULL,
                                       NULL);
    if (result == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
  }

  std::string node_indicator, crash_service_indicator;
  if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
      node_indicator == "1") {
    // Now that argv conversion is done, we can finally start.
    base::i18n::InitializeICU();
    return atom::NodeMain(argc, argv);
  } else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
                         &crash_service_indicator) &&
      crash_service_indicator == "1") {
    return crash_service::Main(cmd);
  }

  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);
  atom::AtomMainDelegate delegate;

  // We don't want to set DPI awareness on pre-Win7 because we don't support
  // DirectWrite there. GDI fonts are kerned very badly, so better to leave
  // DPI-unaware and at effective 1.0. See also ShouldUseDirectWrite().
  if (base::win::GetVersion() >= base::win::VERSION_WIN7)
    EnableHighDPISupport();

  content::ContentMainParams params(&delegate);
  params.instance = instance;
  params.sandbox_info = &sandbox_info;
  atom::AtomCommandLine::Init(argc, argv);
  return content::ContentMain(params);
}

#elif defined(OS_LINUX)  // defined(OS_WIN)

int main(int argc, const char* argv[]) {
  char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
  if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
    base::i18n::InitializeICU();
    return atom::NodeMain(argc, const_cast<char**>(argv));
  }

  atom::AtomMainDelegate delegate;
  content::ContentMainParams params(&delegate);
  params.argc = argc;
  params.argv = argv;
  atom::AtomCommandLine::Init(argc, argv);
  return content::ContentMain(params);
}

#else  // defined(OS_LINUX)

int main(int argc, const char* argv[]) {
  char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
  if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
    return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
  }

  return AtomMain(argc, argv);
}

#endif  // defined(OS_MACOSX)
<commit_msg>Resetting debug changes<commit_after>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/app/atom_main.h"

#include <stdlib.h>
#include <string.h>

#if defined(OS_WIN)
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

#include <windows.h>
#include <shellscalingapi.h>
#include <tchar.h>
#include <shellapi.h>

#include "atom/app/atom_main_delegate.h"
#include "atom/common/crash_reporter/win/crash_service_main.h"
#include "base/environment.h"
#include "base/win/windows_version.h"
#include "content/public/app/startup_helper_win.h"
#include "sandbox/win/src/sandbox_types.h"
#include "ui/gfx/win/dpi.h"
#elif defined(OS_LINUX)  // defined(OS_WIN)
#include "atom/app/atom_main_delegate.h"  // NOLINT
#include "content/public/app/content_main.h"
#else  // defined(OS_LINUX)
#include "atom/app/atom_library_main.h"
#endif  // defined(OS_MACOSX)

#include "atom/app/node_main.h"
#include "atom/common/atom_command_line.h"
#include "base/i18n/icu_util.h"

#if defined(OS_WIN)

namespace {

// Win8.1 supports monitor-specific DPI scaling.
bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
  typedef HRESULT(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
  SetProcessDpiAwarenessPtr set_process_dpi_awareness_func =
      reinterpret_cast<SetProcessDpiAwarenessPtr>(
          GetProcAddress(GetModuleHandleA("user32.dll"),
                         "SetProcessDpiAwarenessInternal"));
  if (set_process_dpi_awareness_func) {
    HRESULT hr = set_process_dpi_awareness_func(value);
    if (SUCCEEDED(hr)) {
      VLOG(1) << "SetProcessDpiAwareness succeeded.";
      return true;
    } else if (hr == E_ACCESSDENIED) {
      LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. "
          "Function called twice, or manifest was used.";
    }
  }
  return false;
}

// This function works for Windows Vista through Win8. Win8.1 must use
// SetProcessDpiAwareness[Wrapper].
BOOL SetProcessDPIAwareWrapper() {
  typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
  SetProcessDPIAwarePtr set_process_dpi_aware_func =
      reinterpret_cast<SetProcessDPIAwarePtr>(
      GetProcAddress(GetModuleHandleA("user32.dll"),
                      "SetProcessDPIAware"));
  return set_process_dpi_aware_func &&
    set_process_dpi_aware_func();
}

void EnableHighDPISupport() {
  if (!SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) {
    SetProcessDPIAwareWrapper();
  }
}

}  // namespace

int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
  int argc = 0;
  wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);

  scoped_ptr<base::Environment> env(base::Environment::Create());

  // Make output work in console if we are not in cygiwn.
  std::string os;
  if (env->GetVar("OS", &os) && os != "cygwin") {
    AttachConsole(ATTACH_PARENT_PROCESS);

    FILE* dontcare;
    freopen_s(&dontcare, "CON", "w", stdout);
    freopen_s(&dontcare, "CON", "w", stderr);
  }

  // Convert argv to to UTF8
  char** argv = new char*[argc];
  for (int i = 0; i < argc; i++) {
    // Compute the size of the required buffer
    DWORD size = WideCharToMultiByte(CP_UTF8,
                                     0,
                                     wargv[i],
                                     -1,
                                     NULL,
                                     0,
                                     NULL,
                                     NULL);
    if (size == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
    // Do the actual conversion
    argv[i] = new char[size];
    DWORD result = WideCharToMultiByte(CP_UTF8,
                                       0,
                                       wargv[i],
                                       -1,
                                       argv[i],
                                       size,
                                       NULL,
                                       NULL);
    if (result == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
  }

  std::string node_indicator, crash_service_indicator;
  if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
      node_indicator == "1") {
    // Now that argv conversion is done, we can finally start.
    base::i18n::InitializeICU();
    return atom::NodeMain(argc, argv);
  } else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
                         &crash_service_indicator) &&
      crash_service_indicator == "1") {
    return crash_service::Main(cmd);
  }

  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);
  atom::AtomMainDelegate delegate;

  // We don't want to set DPI awareness on pre-Win7 because we don't support
  // DirectWrite there. GDI fonts are kerned very badly, so better to leave
  // DPI-unaware and at effective 1.0. See also ShouldUseDirectWrite().
  if (base::win::GetVersion() >= base::win::VERSION_WIN7)
    EnableHighDPISupport();

  content::ContentMainParams params(&delegate);
  params.instance = instance;
  params.sandbox_info = &sandbox_info;
  atom::AtomCommandLine::Init(argc, argv);
  return content::ContentMain(params);
}

#elif defined(OS_LINUX)  // defined(OS_WIN)

int main(int argc, const char* argv[]) {
  char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
  if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
    base::i18n::InitializeICU();
    return atom::NodeMain(argc, const_cast<char**>(argv));
  }

  atom::AtomMainDelegate delegate;
  content::ContentMainParams params(&delegate);
  params.argc = argc;
  params.argv = argv;
  atom::AtomCommandLine::Init(argc, argv);
  return content::ContentMain(params);
}

#else  // defined(OS_LINUX)

int main(int argc, const char* argv[]) {
  char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
  if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
    return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
  }

  return AtomMain(argc, argv);
}

#endif  // defined(OS_MACOSX)
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "testing/gtest/include/gtest/gtest.h"

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_util.h"
#include "build/build_config.h"
#include "chrome/browser/importer/firefox_profile_lock.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/file_test_utils.h"

class FirefoxProfileLockTest : public testing::Test {
 public:
 protected:
  virtual void SetUp() {
    ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_path_));
    std::wstring dir_name(L"FirefoxProfileLockTest");
    dir_name.append(StringPrintf(L"-%d", base::GetCurrentProcId()));
    test_path_ = test_path_.Append(FilePath::FromWStringHack(dir_name));
    file_util::Delete(test_path_, true);
    file_util::CreateDirectory(test_path_);
  }

  virtual void TearDown() {
    ASSERT_TRUE(file_util::Delete(test_path_, true));
    ASSERT_FALSE(file_util::PathExists(test_path_));
  }

  FilePath test_path_;
};

TEST_F(FirefoxProfileLockTest, LockTest) {
  FirefoxProfileLock lock1(test_path_.ToWStringHack());
  ASSERT_TRUE(lock1.HasAcquired());
  lock1.Unlock();
  ASSERT_FALSE(lock1.HasAcquired());
  lock1.Lock();
  ASSERT_TRUE(lock1.HasAcquired());
}

// Tests basic functionality and verifies that the lock file is deleted after
// use.
TEST_F(FirefoxProfileLockTest, ProfileLock) {
  std::wstring test_path;
  file_util::CreateNewTempDirectory(L"firefox_profile", &test_path);
  FilePath lock_file_path = FilePath::FromWStringHack(test_path);
  FileAutoDeleter deleter(lock_file_path);
  lock_file_path = lock_file_path.Append(FirefoxProfileLock::kLockFileName);

  scoped_ptr<FirefoxProfileLock> lock;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock.get());
  EXPECT_FALSE(file_util::PathExists(lock_file_path));
  lock.reset(new FirefoxProfileLock(test_path));
  EXPECT_TRUE(lock->HasAcquired());
  EXPECT_TRUE(file_util::PathExists(lock_file_path));
  lock->Unlock();
  EXPECT_FALSE(lock->HasAcquired());

  // In the posix code, we don't delete the file when releasing the lock.
#if !defined(OS_POSIX)
  EXPECT_FALSE(file_util::PathExists(lock_file_path));
#endif  // !defined(OS_POSIX)
  lock->Lock();
  EXPECT_TRUE(lock->HasAcquired());
  EXPECT_TRUE(file_util::PathExists(lock_file_path));
  lock->Lock();
  EXPECT_TRUE(lock->HasAcquired());
  lock->Unlock();
  EXPECT_FALSE(lock->HasAcquired());
  // In the posix code, we don't delete the file when releasing the lock.
#if !defined(OS_POSIX)
  EXPECT_FALSE(file_util::PathExists(lock_file_path));
#endif  // !defined(OS_POSIX)
}

// If for some reason the lock file is left behind by the previous owner, we
// should still be able to lock it, at least in the Windows implementation.
TEST_F(FirefoxProfileLockTest, ProfileLockOrphaned) {
  FilePath test_path;
  file_util::CreateNewTempDirectory(FILE_PATH_LITERAL("firefox_profile"),
                                    &test_path);
  FilePath lock_file_path = test_path;
  FileAutoDeleter deleter(lock_file_path);
  lock_file_path = lock_file_path.Append(FirefoxProfileLock::kLockFileName);

  // Create the orphaned lock file.
  FILE* lock_file = file_util::OpenFile(lock_file_path, "w");
  ASSERT_TRUE(lock_file);
  file_util::CloseFile(lock_file);
  EXPECT_TRUE(file_util::PathExists(lock_file_path));

  scoped_ptr<FirefoxProfileLock> lock;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock.get());
  lock.reset(new FirefoxProfileLock(test_path.ToWStringHack()));
  EXPECT_TRUE(lock->HasAcquired());
  lock->Unlock();
  EXPECT_FALSE(lock->HasAcquired());
}

// This is broken on POSIX since the same process is allowed to reacquire a
// lock.
#if !defined(OS_POSIX)
// Tests two locks contending for the same lock file.
TEST_F(FirefoxProfileLockTest, ProfileLockContention) {
  std::wstring test_path;
  file_util::CreateNewTempDirectory(L"firefox_profile", &test_path);
  FileAutoDeleter deleter(FilePath::FromWStringHack(test_path));

  scoped_ptr<FirefoxProfileLock> lock1;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock1.get());
  lock1.reset(new FirefoxProfileLock(test_path));
  EXPECT_TRUE(lock1->HasAcquired());

  scoped_ptr<FirefoxProfileLock> lock2;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock2.get());
  lock2.reset(new FirefoxProfileLock(test_path));
  EXPECT_FALSE(lock2->HasAcquired());

  lock1->Unlock();
  EXPECT_FALSE(lock1->HasAcquired());

  lock2->Lock();
  EXPECT_TRUE(lock2->HasAcquired());
  lock2->Unlock();
  EXPECT_FALSE(lock2->HasAcquired());
}
#endif
<commit_msg>Coverity: Check CreateNewTempDirectory return value.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "testing/gtest/include/gtest/gtest.h"

#include "base/file_util.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_util.h"
#include "build/build_config.h"
#include "chrome/browser/importer/firefox_profile_lock.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/file_test_utils.h"

class FirefoxProfileLockTest : public testing::Test {
 public:
 protected:
  virtual void SetUp() {
    ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_path_));
    std::wstring dir_name(L"FirefoxProfileLockTest");
    dir_name.append(StringPrintf(L"-%d", base::GetCurrentProcId()));
    test_path_ = test_path_.Append(FilePath::FromWStringHack(dir_name));
    file_util::Delete(test_path_, true);
    file_util::CreateDirectory(test_path_);
  }

  virtual void TearDown() {
    ASSERT_TRUE(file_util::Delete(test_path_, true));
    ASSERT_FALSE(file_util::PathExists(test_path_));
  }

  FilePath test_path_;
};

TEST_F(FirefoxProfileLockTest, LockTest) {
  FirefoxProfileLock lock1(test_path_.ToWStringHack());
  ASSERT_TRUE(lock1.HasAcquired());
  lock1.Unlock();
  ASSERT_FALSE(lock1.HasAcquired());
  lock1.Lock();
  ASSERT_TRUE(lock1.HasAcquired());
}

// Tests basic functionality and verifies that the lock file is deleted after
// use.
TEST_F(FirefoxProfileLockTest, ProfileLock) {
  std::wstring test_path;
  ASSERT_TRUE(file_util::CreateNewTempDirectory(L"firefox_profile",
                                                &test_path));
  FilePath lock_file_path = FilePath::FromWStringHack(test_path);
  FileAutoDeleter deleter(lock_file_path);
  lock_file_path = lock_file_path.Append(FirefoxProfileLock::kLockFileName);

  scoped_ptr<FirefoxProfileLock> lock;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock.get());
  EXPECT_FALSE(file_util::PathExists(lock_file_path));
  lock.reset(new FirefoxProfileLock(test_path));
  EXPECT_TRUE(lock->HasAcquired());
  EXPECT_TRUE(file_util::PathExists(lock_file_path));
  lock->Unlock();
  EXPECT_FALSE(lock->HasAcquired());

  // In the posix code, we don't delete the file when releasing the lock.
#if !defined(OS_POSIX)
  EXPECT_FALSE(file_util::PathExists(lock_file_path));
#endif  // !defined(OS_POSIX)
  lock->Lock();
  EXPECT_TRUE(lock->HasAcquired());
  EXPECT_TRUE(file_util::PathExists(lock_file_path));
  lock->Lock();
  EXPECT_TRUE(lock->HasAcquired());
  lock->Unlock();
  EXPECT_FALSE(lock->HasAcquired());
  // In the posix code, we don't delete the file when releasing the lock.
#if !defined(OS_POSIX)
  EXPECT_FALSE(file_util::PathExists(lock_file_path));
#endif  // !defined(OS_POSIX)
}

// If for some reason the lock file is left behind by the previous owner, we
// should still be able to lock it, at least in the Windows implementation.
TEST_F(FirefoxProfileLockTest, ProfileLockOrphaned) {
  FilePath test_path;
  ASSERT_TRUE(file_util::CreateNewTempDirectory(
      FILE_PATH_LITERAL("firefox_profile"), &test_path));
  FilePath lock_file_path = test_path;
  FileAutoDeleter deleter(lock_file_path);
  lock_file_path = lock_file_path.Append(FirefoxProfileLock::kLockFileName);

  // Create the orphaned lock file.
  FILE* lock_file = file_util::OpenFile(lock_file_path, "w");
  ASSERT_TRUE(lock_file);
  file_util::CloseFile(lock_file);
  EXPECT_TRUE(file_util::PathExists(lock_file_path));

  scoped_ptr<FirefoxProfileLock> lock;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock.get());
  lock.reset(new FirefoxProfileLock(test_path.ToWStringHack()));
  EXPECT_TRUE(lock->HasAcquired());
  lock->Unlock();
  EXPECT_FALSE(lock->HasAcquired());
}

// This is broken on POSIX since the same process is allowed to reacquire a
// lock.
#if !defined(OS_POSIX)
// Tests two locks contending for the same lock file.
TEST_F(FirefoxProfileLockTest, ProfileLockContention) {
  std::wstring test_path;
  ASSERT_TRUE(file_util::CreateNewTempDirectory(L"firefox_profile",
                                                &test_path));
  FileAutoDeleter deleter(FilePath::FromWStringHack(test_path));

  scoped_ptr<FirefoxProfileLock> lock1;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock1.get());
  lock1.reset(new FirefoxProfileLock(test_path));
  EXPECT_TRUE(lock1->HasAcquired());

  scoped_ptr<FirefoxProfileLock> lock2;
  EXPECT_EQ(static_cast<FirefoxProfileLock*>(NULL), lock2.get());
  lock2.reset(new FirefoxProfileLock(test_path));
  EXPECT_FALSE(lock2->HasAcquired());

  lock1->Unlock();
  EXPECT_FALSE(lock1->HasAcquired());

  lock2->Lock();
  EXPECT_TRUE(lock2->HasAcquired());
  lock2->Unlock();
  EXPECT_FALSE(lock2->HasAcquired());
}
#endif
<|endoftext|>


<commit_before>/// @file
/// @author  Kresimir Spes
/// @author  Boris Mikic
/// @author  Ivan Vucica
/// @version 3.0
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php
///
/// @section DESCRIPTION
///
/// Represents an implementation of the AudioManager for OpenAL.

#ifdef HAVE_OPENAL
#include <string.h>

#ifndef __APPLE__
#include <AL/al.h>
#include <AL/alc.h>
#else
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <TargetConditionals.h>
#endif

#include <hltypes/exception.h>
#include <hltypes/hdir.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hstring.h>

#include "Buffer.h"
#include "Category.h"
#include "OpenAL_AudioManager.h"
#include "OpenAL_Player.h"
#include "xal.h"

#ifdef _IOS
void OpenAL_iOS_init();
void OpenAL_iOS_destroy();
static bool gAudioSuspended = false; // iOS specific hack as well
#endif

namespace xal
{
	OpenAL_AudioManager::OpenAL_AudioManager(chstr systemName, void* backendId, bool threaded, float updateTime, chstr deviceName) :
		AudioManager(systemName, backendId, threaded, updateTime, deviceName), device(NULL), context(NULL)
	{
		hlog::write(xal::logTag, "Initializing OpenAL.");
		ALCdevice* currentDevice = alcOpenDevice(deviceName.c_str());
		if (alcGetError(currentDevice) != ALC_NO_ERROR)
		{
			hlog::error(xal::logTag, "Could not create device!");
			return;
		}
		this->deviceName = alcGetString(currentDevice, ALC_DEVICE_SPECIFIER);
		hlog::write(xal::logTag, "Audio device: " + this->deviceName);
		ALCcontext* currentContext = alcCreateContext(currentDevice, NULL);
		if (alcGetError(currentDevice) != ALC_NO_ERROR)
		{
			hlog::error(xal::logTag, "Could not create context!");
			return;
		}
		alcMakeContextCurrent(currentContext);
		if (alcGetError(currentDevice) != ALC_NO_ERROR)
		{
			hlog::error(xal::logTag, "Could not set context as current!");
			return;
		}
		this->device = currentDevice;
		this->context = currentContext;
		this->enabled = true;
#ifdef _IOS
		OpenAL_iOS_init();
#endif
	}

	OpenAL_AudioManager::~OpenAL_AudioManager()
	{
		hlog::write(xal::logTag, "Destroying OpenAL.");
#ifdef _IOS
		OpenAL_iOS_destroy();
#endif
		if (this->device != NULL)
		{
			alcMakeContextCurrent(NULL);
			alcDestroyContext(this->context);
			alcCloseDevice(this->device);
		}
	}

	Player* OpenAL_AudioManager::_createSystemPlayer(Sound* sound)
	{
		return new OpenAL_Player(sound);
	}

	unsigned int OpenAL_AudioManager::_allocateSourceId()
	{
		unsigned int id = 0;
		alGenSources(1, &id);
		if (alGetError() != AL_NO_ERROR)
		{
			hlog::warn(xal::logTag, "Unable to allocate audio source!");
			return 0;
		}
		return id;
	}

	void OpenAL_AudioManager::_releaseSourceId(unsigned int sourceId)
	{
		alDeleteSources(1, &sourceId);
	}

	void OpenAL_AudioManager::suspendOpenALContext() // TODO - iOS specific hack, should be removed later
	{
#ifdef _IOS
		this->_lock();
		hlog::debug(xal::logTag, "Suspending OpenAL Context.");
		gAudioSuspended = this->isSuspended();
		if (!gAudioSuspended)
		{
			this->_suspendAudio();
		}
		alcSuspendContext(this->context);
		alcMakeContextCurrent(NULL);
		this->_unlock();
#else
		hlog::debug(xal::logTag, "Not iOS, suspendOpenALContext does nothing.");
#endif
	}

	void OpenAL_AudioManager::resumeOpenALContext() // TODO - iOS specific hack, should be removed later
	{
#ifdef _IOS
		this->_lock();
		hlog::debug(xal::logTag, "Resuming OpenAL Context.");
		alcMakeContextCurrent(this->context);
		alcProcessContext(this->context);
		if (!gAudioSuspended)
		{
			this->_resumeAudio();
		}
		this->_unlock();
#else
		hlog::debug(xal::logTag, "Not iOS, resumeOpenALContext does nothing.");
#endif
	}
}
#endif
<commit_msg>OpenAL debuging functions<commit_after>/// @file
/// @author  Kresimir Spes
/// @author  Boris Mikic
/// @author  Ivan Vucica
/// @version 3.0
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php
///
/// @section DESCRIPTION
///
/// Represents an implementation of the AudioManager for OpenAL.

#ifdef HAVE_OPENAL
#include <string.h>

#ifndef __APPLE__
#include <AL/al.h>
#include <AL/alc.h>
#else
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <TargetConditionals.h>
#endif

#include <hltypes/exception.h>
#include <hltypes/hdir.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hstring.h>

#include "Buffer.h"
#include "Category.h"
#include "OpenAL_AudioManager.h"
#include "OpenAL_Player.h"
#include "xal.h"

#ifdef _IOS
void OpenAL_iOS_init();
void OpenAL_iOS_destroy();
static bool gAudioSuspended = false; // iOS specific hack as well
#endif

static hstr alGetErrorString(ALenum error)
{
	switch (error)
    {
        case AL_NO_ERROR:
            return "AL_NO_ERROR";
        case AL_INVALID_NAME:
            return "AL_INVALID_NAME";
        case AL_INVALID_ENUM:
            return "AL_INVALID_ENUM";
        case AL_INVALID_VALUE:
            return "AL_INVALID_VALUE";
        case AL_INVALID_OPERATION:
            return "AL_INVALID_OPERATION";
        case AL_OUT_OF_MEMORY:
            return "AL_OUT_OF_MEMORY";
		default:
			return "UNKNOWN";
    };
}

static hstr alcGetErrorStrirg(ALenum error)
{
    switch (error)
    {
        case ALC_NO_ERROR:
            return "AL_NO_ERROR";
        case ALC_INVALID_DEVICE:
            return "ALC_INVALID_DEVICE";
        case ALC_INVALID_CONTEXT:
            return "ALC_INVALID_CONTEXT";
        case ALC_INVALID_ENUM:
            return "ALC_INVALID_ENUM";
        case ALC_INVALID_VALUE:
            return "ALC_INVALID_VALUE";
        case ALC_OUT_OF_MEMORY:
            return "ALC_OUT_OF_MEMORY";
		default:
			return "UNKNOWN";
    };
}

namespace xal
{
	OpenAL_AudioManager::OpenAL_AudioManager(chstr systemName, void* backendId, bool threaded, float updateTime, chstr deviceName) :
		AudioManager(systemName, backendId, threaded, updateTime, deviceName), device(NULL), context(NULL)
	{
		hlog::write(xal::logTag, "Initializing OpenAL.");
		ALCdevice* currentDevice = alcOpenDevice(deviceName.c_str());
		ALenum error = alcGetError(currentDevice);
		if (error != ALC_NO_ERROR)
		{
			hlog::error(xal::logTag, "Could not create device!, " + alcGetErrorStrirg(error));
			return;
		}
		this->deviceName = alcGetString(currentDevice, ALC_DEVICE_SPECIFIER);
		hlog::write(xal::logTag, "Audio device: " + this->deviceName);
		ALCcontext* currentContext = alcCreateContext(currentDevice, NULL);
		error = alcGetError(currentDevice);
		if (error != ALC_NO_ERROR)
		{
			hlog::error(xal::logTag, "Could not create context!, " + alcGetErrorStrirg(error));
			return;
		}
		alcMakeContextCurrent(currentContext);
		error = alcGetError(currentDevice);
		if (error != ALC_NO_ERROR)
		{
			hlog::error(xal::logTag, "Could not set context as current!, " + alcGetErrorStrirg(error));
			return;
		}
		this->device = currentDevice;
		this->context = currentContext;
		this->enabled = true;
#ifdef _IOS
		OpenAL_iOS_init();
#endif
	}

	OpenAL_AudioManager::~OpenAL_AudioManager()
	{
		hlog::write(xal::logTag, "Destroying OpenAL.");
#ifdef _IOS
		OpenAL_iOS_destroy();
#endif
		if (this->device != NULL)
		{
			alcMakeContextCurrent(NULL);
			alcDestroyContext(this->context);
			alcCloseDevice(this->device);
		}
	}

	Player* OpenAL_AudioManager::_createSystemPlayer(Sound* sound)
	{
		return new OpenAL_Player(sound);
	}

	unsigned int OpenAL_AudioManager::_allocateSourceId()
	{
		unsigned int id = 0;
		alGenSources(1, &id);
		ALenum error = alGetError();
		if (error != AL_NO_ERROR)
		{
			hlog::warn(xal::logTag, "Unable to allocate audio source!, " + alGetErrorString(error));
			return 0;
		}
		return id;
	}

	void OpenAL_AudioManager::_releaseSourceId(unsigned int sourceId)
	{
		alDeleteSources(1, &sourceId);
	}

	void OpenAL_AudioManager::suspendOpenALContext() // TODO - iOS specific hack, should be removed later
	{
#ifdef _IOS
		this->_lock();
		hlog::debug(xal::logTag, "Suspending OpenAL Context.");
		gAudioSuspended = this->isSuspended();
		if (!gAudioSuspended)
		{
			this->_suspendAudio();
		}
		alcSuspendContext(this->context);
		alcMakeContextCurrent(NULL);
		this->_unlock();
#else
		hlog::debug(xal::logTag, "Not iOS, suspendOpenALContext does nothing.");
#endif
	}

	void OpenAL_AudioManager::resumeOpenALContext() // TODO - iOS specific hack, should be removed later
	{
#ifdef _IOS
		this->_lock();
		hlog::debug(xal::logTag, "Resuming OpenAL Context.");
		alcMakeContextCurrent(this->context);
		alcProcessContext(this->context);
		if (!gAudioSuspended)
		{
			this->_resumeAudio();
		}
		this->_unlock();
#else
		hlog::debug(xal::logTag, "Not iOS, resumeOpenALContext does nothing.");
#endif
	}
}
#endif
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "MockupInputManager.hpp"
#include "MockupInputEventListener.hpp"
#include "MockupKey.hpp"

using namespace rd;

//-- Class for the setup of each test
//--------------------------------------------------------------------------------------
class MockupInputManagerTest : public testing::Test
{
    public:
        virtual void SetUp()
        {
            ASSERT_TRUE(MockupInputManager::RegisterManager());
            inputManager = (MockupInputManager *) MockupInputManager::getInputManager(MockupInputManager::id);
            ASSERT_TRUE(inputManager);
        }

        virtual void TearDown()
        {
            ASSERT_TRUE(MockupInputManager::destroyInputManager());
        }

    protected:
        MockupInputManager * inputManager;
};

//-- Things that are being tested
//-----------------------------------------------------------------------------------------------------
TEST_F(MockupInputManagerTest, SingleControlKeyPressSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));
    ASSERT_EQ(1, inputManager->getNumListeners());

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey enter_key(RdKey::KEY_ENTER);
    ASSERT_TRUE(inputManager->sendKeyPress(enter_key));

    //-- Check if keypress was received
    ASSERT_EQ(1,listener.getNumKeyDownPresses());
    ASSERT_EQ(1,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(1,keys_down_received.size());
    ASSERT_EQ(1,keys_up_received.size());

    ASSERT_EQ(enter_key.getValue(), keys_down_received[0].getValue());
    ASSERT_EQ(enter_key.getValue(), keys_up_received[0].getValue());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_EQ(0, inputManager->getNumListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}

TEST_F(MockupInputManagerTest, SinglePrintableKeyPressSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey d_key('d');
    ASSERT_TRUE(inputManager->sendKeyPress(d_key));

    //-- Check if keypress was received
    ASSERT_EQ(1,listener.getNumKeyDownPresses());
    ASSERT_EQ(1,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(1,keys_down_received.size());
    ASSERT_EQ(1,keys_up_received.size());

    ASSERT_EQ(d_key.getChar(), keys_down_received[0].getChar());
    ASSERT_EQ(d_key.getChar(), keys_up_received[0].getChar());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}

TEST_F(MockupInputManagerTest, SeveralControlKeyPressesSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey enter_key(RdKey::KEY_ENTER);
    MockupKey arrow_key(RdKey::KEY_ARROW_DOWN);
    ASSERT_TRUE(inputManager->sendKeyPress(enter_key));
    ASSERT_TRUE(inputManager->sendKeyPress(arrow_key));

    //-- Check if keypress was received
    ASSERT_EQ(2,listener.getNumKeyDownPresses());
    ASSERT_EQ(2,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(2,keys_down_received.size());
    ASSERT_EQ(2,keys_up_received.size());

    ASSERT_EQ(enter_key.getValue(), keys_down_received[0].getValue());
    ASSERT_EQ(enter_key.getValue(), keys_up_received[0].getValue());
    ASSERT_EQ(arrow_key.getValue(), keys_down_received[1].getValue());
    ASSERT_EQ(arrow_key.getValue(), keys_up_received[1].getValue());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}

TEST_F(MockupInputManagerTest, SeveralPrintableKeyPressesSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey r_key('r');
    MockupKey d_key('d');
    ASSERT_TRUE(inputManager->sendKeyPress(r_key));
    ASSERT_TRUE(inputManager->sendKeyPress(d_key));

    //-- Check if keypress was received
    ASSERT_EQ(2,listener.getNumKeyDownPresses());
    ASSERT_EQ(2,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(2,keys_down_received.size());
    ASSERT_EQ(2,keys_up_received.size());

    ASSERT_EQ(r_key.getChar(), keys_down_received[0].getChar());
    ASSERT_EQ(r_key.getChar(), keys_up_received[0].getChar());
    ASSERT_EQ(d_key.getChar(), keys_down_received[1].getChar());
    ASSERT_EQ(d_key.getChar(), keys_up_received[1].getChar());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}
<commit_msg>Add failing test for new feature (KeyUp/KeyDown emulation) in MockupInputManager<commit_after>#include "gtest/gtest.h"
#include "MockupInputManager.hpp"
#include "MockupInputEventListener.hpp"
#include "MockupKey.hpp"

using namespace rd;

//-- Class for the setup of each test
//--------------------------------------------------------------------------------------
class MockupInputManagerTest : public testing::Test
{
    public:
        virtual void SetUp()
        {
            ASSERT_TRUE(MockupInputManager::RegisterManager());
            inputManager = (MockupInputManager *) MockupInputManager::getInputManager(MockupInputManager::id);
            ASSERT_TRUE(inputManager);
        }

        virtual void TearDown()
        {
            ASSERT_TRUE(MockupInputManager::destroyInputManager());
        }

    protected:
        MockupInputManager * inputManager;
};

//-- Things that are being tested
//-----------------------------------------------------------------------------------------------------
TEST_F(MockupInputManagerTest, SingleControlKeyPressSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));
    ASSERT_EQ(1, inputManager->getNumListeners());

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey enter_key(RdKey::KEY_ENTER);
    ASSERT_TRUE(inputManager->sendKeyPress(enter_key));

    //-- Check if keypress was received
    ASSERT_EQ(1,listener.getNumKeyDownPresses());
    ASSERT_EQ(1,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(1,keys_down_received.size());
    ASSERT_EQ(1,keys_up_received.size());

    ASSERT_EQ(enter_key.getValue(), keys_down_received[0].getValue());
    ASSERT_EQ(enter_key.getValue(), keys_up_received[0].getValue());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_EQ(0, inputManager->getNumListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}

TEST_F(MockupInputManagerTest, SinglePrintableKeyPressSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey d_key('d');
    ASSERT_TRUE(inputManager->sendKeyPress(d_key));

    //-- Check if keypress was received
    ASSERT_EQ(1,listener.getNumKeyDownPresses());
    ASSERT_EQ(1,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(1,keys_down_received.size());
    ASSERT_EQ(1,keys_up_received.size());

    ASSERT_EQ(d_key.getChar(), keys_down_received[0].getChar());
    ASSERT_EQ(d_key.getChar(), keys_up_received[0].getChar());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}

TEST_F(MockupInputManagerTest, SeveralControlKeyPressesSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey enter_key(RdKey::KEY_ENTER);
    MockupKey arrow_key(RdKey::KEY_ARROW_DOWN);
    ASSERT_TRUE(inputManager->sendKeyPress(enter_key));
    ASSERT_TRUE(inputManager->sendKeyPress(arrow_key));

    //-- Check if keypress was received
    ASSERT_EQ(2,listener.getNumKeyDownPresses());
    ASSERT_EQ(2,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(2,keys_down_received.size());
    ASSERT_EQ(2,keys_up_received.size());

    ASSERT_EQ(enter_key.getValue(), keys_down_received[0].getValue());
    ASSERT_EQ(enter_key.getValue(), keys_up_received[0].getValue());
    ASSERT_EQ(arrow_key.getValue(), keys_down_received[1].getValue());
    ASSERT_EQ(arrow_key.getValue(), keys_up_received[1].getValue());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}

TEST_F(MockupInputManagerTest, SeveralPrintableKeyPressesSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a control keypress
    MockupKey r_key('r');
    MockupKey d_key('d');
    ASSERT_TRUE(inputManager->sendKeyPress(r_key));
    ASSERT_TRUE(inputManager->sendKeyPress(d_key));

    //-- Check if keypress was received
    ASSERT_EQ(2,listener.getNumKeyDownPresses());
    ASSERT_EQ(2,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(2,keys_down_received.size());
    ASSERT_EQ(2,keys_up_received.size());

    ASSERT_EQ(r_key.getChar(), keys_down_received[0].getChar());
    ASSERT_EQ(r_key.getChar(), keys_up_received[0].getChar());
    ASSERT_EQ(d_key.getChar(), keys_down_received[1].getChar());
    ASSERT_EQ(d_key.getChar(), keys_up_received[1].getChar());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}

TEST_F(MockupInputManagerTest, KeyUpAndKeyDownSentAndReceivedCorrectly)
{
    MockupInputEventListener listener;
    RdInputEventListener * plistener = (RdInputEventListener *) &listener;
    ASSERT_TRUE(((RdInputManager*)inputManager)->addInputEventListener(plistener));

    ASSERT_TRUE(inputManager->start());
    ASSERT_FALSE(inputManager->isStopped());

    //-- Fake a key down
    MockupKey enter_key(RdKey::KEY_ENTER);
    MockupKey d_key('d');
    ASSERT_TRUE(inputManager->sendKeyDown(enter_key));
    ASSERT_TRUE(inputManager->sendKeyDown(d_key));

    //-- Check if keypress was received
    ASSERT_EQ(2,listener.getNumKeyDownPresses());
    ASSERT_EQ(0,listener.getNumKeyUpPresses());

    //-- Fake a key up
    ASSERT_TRUE(inputManager->sendKeyUp(enter_key));
    ASSERT_TRUE(inputManager->sendKeyUp(d_key));

    //-- Check if keypress was received
    ASSERT_EQ(2,listener.getNumKeyDownPresses());
    ASSERT_EQ(2,listener.getNumKeyUpPresses());

    //-- Check if keypress received is correct
    std::vector<RdKey> keys_down_received = listener.getStoredKeyDownPresses();
    std::vector<RdKey> keys_up_received = listener.getStoredKeyDownPresses();
    ASSERT_EQ(2,keys_down_received.size());
    ASSERT_EQ(2,keys_up_received.size());

    ASSERT_EQ(enter_key.getValue(), keys_down_received[0].getValue());
    ASSERT_EQ(enter_key.getValue(), keys_up_received[0].getValue());
    ASSERT_EQ(d_key.getChar(), keys_down_received[1].getChar());
    ASSERT_EQ(d_key.getChar(), keys_up_received[1].getChar());

    //-- Cleanup
    ASSERT_TRUE(inputManager->removeInputEventListeners());
    ASSERT_TRUE(inputManager->stop());
    ASSERT_TRUE(inputManager->isStopped());
}
<|endoftext|>


<commit_before>// Hossein Moein
// September 12, 2017
// Copyright (C) 2018-2019 Hossein Moein
// Distributed under the BSD Software License (see file License)

#include "DataFrame.h"
#include <tuple>

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

namespace hmdf
{

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

template<typename TS, typename HETERO>
template<typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
join_by_index (const RHS_T &rhs, join_policy mp) const  {

    static_assert(std::is_base_of<StdDataFrame<TS>, RHS_T>::value ||
                      std::is_base_of<DataFrameView<TS>, RHS_T>::value,
                  "The rhs argument to join_by_index() can only be "
                  "StdDataFrame<TS> or DataFrameView<TS>");

    switch(mp)  {
        case join_policy::inner_join:
            return (index_inner_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
        case join_policy::left_join:
            return (index_left_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
        case join_policy::right_join:
            return (index_right_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
        case join_policy::left_right_join:
        default:
            return (index_left_right_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
    }
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
join_helper_(const LHS_T &lhs,
             const RHS_T &rhs,
             const IndexIdxVector &joined_index_idx)  {

    StdDataFrame<TS>    result;
    std::vector<TS>     result_index;

    // Load the index
    result_index.reserve(joined_index_idx.size());
    for (const auto &citer : joined_index_idx)  {
        const size_type left_i = std::get<0>(citer);

        result_index.push_back(
            left_i != std::numeric_limits<size_type>::max()
                ? lhs.indices_[left_i] : rhs.indices_[std::get<1>(citer)]);
    }
    result.load_index(std::move(result_index));

    // Load the common and lhs columns
    for (auto &iter : lhs.data_tb_)  {
        auto    rhs_citer = rhs.data_tb_.find(iter.first);

        // Common column between two frames
        if (rhs_citer != rhs.data_tb_.end())  {
            index_join_functor_common_<types ...> functor (iter.first.c_str(),
                                                           rhs,
                                                           joined_index_idx,
                                                           result);

            lhs.data_[iter.second].change(functor);

        }
        else  {  // lhs only column
            // 0 = Left
            index_join_functor_oneside_<0, types ...> functor (
                iter.first.c_str(),
                joined_index_idx,
                result);

            lhs.data_[iter.second].change(functor);
        }
    }

    // Load the rhs columns
    for (auto &iter : rhs.data_tb_)  {
        auto    lhs_citer = lhs.data_tb_.find(iter.first);

        if (lhs_citer == lhs.data_tb_.end())  {  // rhs only column
            // 1 = Right
            index_join_functor_oneside_<1, types ...> functor (
                iter.first.c_str(),
                joined_index_idx,
                result);

            rhs.data_[iter.second].change(functor);
        }
    }

    return(result);
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_inner_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(std::min(lhs_end, rhs_end));
    while (lhs_current != lhs_end && rhs_current != rhs_end) {
        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])
            lhs_current += 1;
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_left_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(lhs_end);
    while (lhs_current != lhs_end || rhs_current != rhs_end) {
        if (lhs_current >= lhs_end)  break;
        if (rhs_current >= rhs_end)  {
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
            continue;
        }

        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_right_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(rhs_end);
    while (lhs_current != lhs_end || rhs_current != rhs_end) {
        if (rhs_current >= rhs_end)  break;
        if (lhs_current >= lhs_end)  {
            joined_index_idx.emplace_back(
                std::numeric_limits<size_type>::max(),
                rhs_current++);
            continue;
        }

        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])
            lhs_current += 1;
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            else
                joined_index_idx.emplace_back(
                    std::numeric_limits<size_type>::max(),
                    rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_left_right_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(std::max(lhs_end, rhs_end));
    while (lhs_current != lhs_end || rhs_current != rhs_end) {
        if (lhs_current >= lhs_end && rhs_current < rhs_end)  {
            joined_index_idx.emplace_back(
                std::numeric_limits<size_type>::max(),
                rhs_current++);
            continue;
        }
        if (rhs_current >= rhs_end && lhs_current < lhs_end)  {
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
            continue;
        }

        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])  {
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
        }
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            else
                joined_index_idx.emplace_back(
                    std::numeric_limits<size_type>::max(),
                    rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

} // namespace hmdf

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

// Local Variables:
// mode:C++
// tab-width:4
// c-basic-offset:4
// End:
<commit_msg>Windows problem<commit_after>// Hossein Moein
// September 12, 2017
// Copyright (C) 2018-2019 Hossein Moein
// Distributed under the BSD Software License (see file License)

#if defined(_WIN32) || defined(WIN32)
#define NOMINMAX
#endif // defined(_WIN32) || defined(WIN32)
#include "DataFrame.h"
#include <tuple>

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

namespace hmdf
{

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

template<typename TS, typename HETERO>
template<typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
join_by_index (const RHS_T &rhs, join_policy mp) const  {

    static_assert(std::is_base_of<StdDataFrame<TS>, RHS_T>::value ||
                      std::is_base_of<DataFrameView<TS>, RHS_T>::value,
                  "The rhs argument to join_by_index() can only be "
                  "StdDataFrame<TS> or DataFrameView<TS>");

    switch(mp)  {
        case join_policy::inner_join:
            return (index_inner_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
        case join_policy::left_join:
            return (index_left_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
        case join_policy::right_join:
            return (index_right_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
        case join_policy::left_right_join:
        default:
            return (index_left_right_join_
                        <decltype(*this), decltype(rhs), types ...>
                            (*this, rhs));
            break;
    }
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
join_helper_(const LHS_T &lhs,
             const RHS_T &rhs,
             const IndexIdxVector &joined_index_idx)  {

    StdDataFrame<TS>    result;
    std::vector<TS>     result_index;

    // Load the index
    result_index.reserve(joined_index_idx.size());
    for (const auto &citer : joined_index_idx)  {
        const size_type left_i = std::get<0>(citer);

        result_index.push_back(
            left_i != std::numeric_limits<size_type>::max()
                ? lhs.indices_[left_i] : rhs.indices_[std::get<1>(citer)]);
    }
    result.load_index(std::move(result_index));

    // Load the common and lhs columns
    for (auto &iter : lhs.data_tb_)  {
        auto    rhs_citer = rhs.data_tb_.find(iter.first);

        // Common column between two frames
        if (rhs_citer != rhs.data_tb_.end())  {
            index_join_functor_common_<types ...> functor (iter.first.c_str(),
                                                           rhs,
                                                           joined_index_idx,
                                                           result);

            lhs.data_[iter.second].change(functor);

        }
        else  {  // lhs only column
            // 0 = Left
            index_join_functor_oneside_<0, types ...> functor (
                iter.first.c_str(),
                joined_index_idx,
                result);

            lhs.data_[iter.second].change(functor);
        }
    }

    // Load the rhs columns
    for (auto &iter : rhs.data_tb_)  {
        auto    lhs_citer = lhs.data_tb_.find(iter.first);

        if (lhs_citer == lhs.data_tb_.end())  {  // rhs only column
            // 1 = Right
            index_join_functor_oneside_<1, types ...> functor (
                iter.first.c_str(),
                joined_index_idx,
                result);

            rhs.data_[iter.second].change(functor);
        }
    }

    return(result);
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_inner_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(std::min(lhs_end, rhs_end));
    while (lhs_current != lhs_end && rhs_current != rhs_end) {
        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])
            lhs_current += 1;
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_left_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(lhs_end);
    while (lhs_current != lhs_end || rhs_current != rhs_end) {
        if (lhs_current >= lhs_end)  break;
        if (rhs_current >= rhs_end)  {
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
            continue;
        }

        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_right_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(rhs_end);
    while (lhs_current != lhs_end || rhs_current != rhs_end) {
        if (rhs_current >= rhs_end)  break;
        if (lhs_current >= lhs_end)  {
            joined_index_idx.emplace_back(
                std::numeric_limits<size_type>::max(),
                rhs_current++);
            continue;
        }

        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])
            lhs_current += 1;
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            else
                joined_index_idx.emplace_back(
                    std::numeric_limits<size_type>::max(),
                    rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

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

template<typename TS, typename HETERO>
template<typename LHS_T, typename RHS_T, typename ... types>
StdDataFrame<TS> DataFrame<TS, HETERO>::
index_left_right_join_(const LHS_T &lhs, const RHS_T &rhs)  {

    size_type       lhs_current = 0;
    const size_type lhs_end = lhs.indices_.size();
    size_type       rhs_current = 0;
    const size_type rhs_end = rhs.indices_.size();

    IndexIdxVector  joined_index_idx;

    joined_index_idx.reserve(std::max(lhs_end, rhs_end));
    while (lhs_current != lhs_end || rhs_current != rhs_end) {
        if (lhs_current >= lhs_end && rhs_current < rhs_end)  {
            joined_index_idx.emplace_back(
                std::numeric_limits<size_type>::max(),
                rhs_current++);
            continue;
        }
        if (rhs_current >= rhs_end && lhs_current < lhs_end)  {
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
            continue;
        }

        if (lhs.indices_[lhs_current] < rhs.indices_[rhs_current])  {
            joined_index_idx.emplace_back(
                lhs_current++,
                std::numeric_limits<size_type>::max());
        }
        else  {
            if (lhs.indices_[lhs_current] == rhs.indices_[rhs_current])
                joined_index_idx.emplace_back(lhs_current++, rhs_current);
            else
                joined_index_idx.emplace_back(
                    std::numeric_limits<size_type>::max(),
                    rhs_current);
            rhs_current += 1;
        }
    }

    return (join_helper_<LHS_T, RHS_T, types ...>(lhs, rhs, joined_index_idx));
}

} // namespace hmdf

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

// Local Variables:
// mode:C++
// tab-width:4
// c-basic-offset:4
// End:
<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/win/windows_version.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/media/webrtc_browsertest_base.h"
#include "chrome/browser/media/webrtc_browsertest_common.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/ui/ui_test.h"
#include "content/public/test/browser_test_utils.h"
#include "media/base/media_switches.h"
#include "net/test/python_utils.h"

// You need this solution to run this test. The solution will download appengine
// and the apprtc code for you.
const char kAdviseOnGclientSolution[] =
    "You need to add this solution to your .gclient to run this test:\n"
    "{\n"
    "  \"name\"        : \"webrtc.DEPS\",\n"
    "  \"url\"         : \"svn://svn.chromium.org/chrome/trunk/deps/"
    "third_party/webrtc/webrtc.DEPS\",\n"
    "}";
const char kTitlePageOfAppEngineAdminPage[] = "Instances";

// WebRTC-AppRTC integration test. Requires a real webcam and microphone
// on the running system. This test is not meant to run in the main browser
// test suite since normal tester machines do not have webcams. Chrome will use
// this camera for the regular AppRTC test whereas Firefox will use it in the
// Firefox interop test (where case Chrome will use its built-in fake device).
//
// This test will bring up a AppRTC instance on localhost and verify that the
// call gets up when connecting to the same room from two tabs in a browser.
class WebrtcApprtcBrowserTest : public WebRtcTestBase {
 public:
  WebrtcApprtcBrowserTest()
      : dev_appserver_(base::kNullProcessHandle),
        firefox_(base::kNullProcessHandle) {
  }

  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));

    // The video playback will not work without a GPU, so force its use here.
    command_line->AppendSwitch(switches::kUseGpuInTests);
  }

  virtual void TearDown() OVERRIDE {
    // Kill any processes we may have brought up.
    if (dev_appserver_ != base::kNullProcessHandle)
      base::KillProcess(dev_appserver_, 0, false);
    // TODO(phoglund): Find some way to shut down Firefox cleanly on Windows.
    if (firefox_ != base::kNullProcessHandle)
      base::KillProcess(firefox_, 0, false);
  }

 protected:
  bool LaunchApprtcInstanceOnLocalhost() {
    base::FilePath appengine_dev_appserver =
        GetSourceDir().Append(
            FILE_PATH_LITERAL("../google_appengine/dev_appserver.py"));
    if (!base::PathExists(appengine_dev_appserver)) {
      LOG(ERROR) << "Missing appengine sdk at " <<
          appengine_dev_appserver.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }

    base::FilePath apprtc_dir =
        GetSourceDir().Append(FILE_PATH_LITERAL("out/apprtc"));
    if (!base::PathExists(apprtc_dir)) {
      LOG(ERROR) << "Missing AppRTC code at " <<
          apprtc_dir.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }

    CommandLine command_line(CommandLine::NO_PROGRAM);
    EXPECT_TRUE(GetPythonCommand(&command_line));

    command_line.AppendArgPath(appengine_dev_appserver);
    command_line.AppendArgPath(apprtc_dir);
    command_line.AppendArg("--port=9999");
    command_line.AppendArg("--admin_port=9998");
    command_line.AppendArg("--skip_sdk_update_check");

    VLOG(1) << "Running " << command_line.GetCommandLineString();
    return base::LaunchProcess(command_line, base::LaunchOptions(),
                               &dev_appserver_);
  }

  bool LocalApprtcInstanceIsUp() {
    // Load the admin page and see if we manage to load it right.
    ui_test_utils::NavigateToURL(browser(), GURL("localhost:9998"));
    content::WebContents* tab_contents =
        browser()->tab_strip_model()->GetActiveWebContents();
    std::string javascript =
        "window.domAutomationController.send(document.title)";
    std::string result;
    if (!content::ExecuteScriptAndExtractString(tab_contents, javascript,
                                                &result))
      return false;

    return result == kTitlePageOfAppEngineAdminPage;
  }

  bool WaitForCallToComeUp(content::WebContents* tab_contents) {
    // Apprtc will set remoteVideo.style.opacity to 1 when the call comes up.
    std::string javascript =
        "window.domAutomationController.send(remoteVideo.style.opacity)";
    return PollingWaitUntil(javascript, "1", tab_contents);
  }

  base::FilePath GetSourceDir() {
    base::FilePath source_dir;
    PathService::Get(base::DIR_SOURCE_ROOT, &source_dir);
    return source_dir;
  }

  bool LaunchFirefoxWithUrl(const GURL& url) {
    base::FilePath firefox_binary =
        GetSourceDir().Append(
            FILE_PATH_LITERAL("../firefox-nightly/firefox/firefox"));
    if (!base::PathExists(firefox_binary)) {
      LOG(ERROR) << "Missing firefox binary at " <<
          firefox_binary.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }
    base::FilePath firefox_launcher =
        GetSourceDir().Append(
            FILE_PATH_LITERAL("../webrtc.DEPS/run_firefox_webrtc.py"));
    if (!base::PathExists(firefox_launcher)) {
      LOG(ERROR) << "Missing firefox launcher at " <<
          firefox_launcher.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }

    CommandLine command_line(firefox_launcher);
    command_line.AppendSwitchPath("--binary", firefox_binary);
    command_line.AppendSwitchASCII("--webpage", url.spec());

    VLOG(1) << "Running " << command_line.GetCommandLineString();
    return base::LaunchProcess(command_line, base::LaunchOptions(),
                               &firefox_);

    return true;
  }

 private:
  base::ProcessHandle dev_appserver_;
  base::ProcessHandle firefox_;
};

IN_PROC_BROWSER_TEST_F(WebrtcApprtcBrowserTest, MANUAL_WorksOnApprtc) {
  // TODO(mcasas): Remove Win version filtering when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=2703
#if defined(OS_WIN)
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return;
#endif
  DetectErrorsInJavaScript();
  ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost());
  while (!LocalApprtcInstanceIsUp())
    VLOG(1) << "Waiting for AppRTC to come up...";

  GURL room_url = GURL(base::StringPrintf("localhost:9999?r=room_%d",
                                          base::RandInt(0, 65536)));

  chrome::AddTabAt(browser(), GURL(), -1, true);
  content::WebContents* left_tab = OpenPageAndAcceptUserMedia(room_url);
  // TODO(phoglund): Remove when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=1742
  SleepInJavascript(left_tab, 5000);
  chrome::AddTabAt(browser(), GURL(), -1, true);
  content::WebContents* right_tab = OpenPageAndAcceptUserMedia(room_url);

  ASSERT_TRUE(WaitForCallToComeUp(left_tab));
  ASSERT_TRUE(WaitForCallToComeUp(right_tab));
}

#if defined(OS_LINUX)
#define MAYBE_MANUAL_FirefoxApprtcInteropTest MANUAL_FirefoxApprtcInteropTest
#else
// Not implemented yet on Windows and Mac.
#define MAYBE_MANUAL_FirefoxApprtcInteropTest DISABLED_MANUAL_FirefoxApprtcInteropTest
#endif

IN_PROC_BROWSER_TEST_F(WebrtcApprtcBrowserTest,
                       MAYBE_MANUAL_FirefoxApprtcInteropTest) {
  // TODO(mcasas): Remove Win version filtering when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=2703
#if defined(OS_WIN)
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return;
#endif

  DetectErrorsInJavaScript();
  ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost());
  while (!LocalApprtcInstanceIsUp())
    VLOG(1) << "Waiting for AppRTC to come up...";

  // Run Chrome with a fake device to avoid having the browsers fight over the
  // camera (we'll just give that to firefox here).
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kUseFakeDeviceForMediaStream);

  GURL room_url = GURL(base::StringPrintf("http://localhost:9999?r=room_%d",
                                          base::RandInt(0, 65536)));
  content::WebContents* chrome_tab = OpenPageAndAcceptUserMedia(room_url);

  // TODO(phoglund): Remove when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=1742
  SleepInJavascript(chrome_tab, 5000);

  ASSERT_TRUE(LaunchFirefoxWithUrl(room_url));

  ASSERT_TRUE(WaitForCallToComeUp(chrome_tab));
}
<commit_msg>Corrected Webrtc-Apprtc test name.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/win/windows_version.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/media/webrtc_browsertest_base.h"
#include "chrome/browser/media/webrtc_browsertest_common.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/ui/ui_test.h"
#include "content/public/test/browser_test_utils.h"
#include "media/base/media_switches.h"
#include "net/test/python_utils.h"

// You need this solution to run this test. The solution will download appengine
// and the apprtc code for you.
const char kAdviseOnGclientSolution[] =
    "You need to add this solution to your .gclient to run this test:\n"
    "{\n"
    "  \"name\"        : \"webrtc.DEPS\",\n"
    "  \"url\"         : \"svn://svn.chromium.org/chrome/trunk/deps/"
    "third_party/webrtc/webrtc.DEPS\",\n"
    "}";
const char kTitlePageOfAppEngineAdminPage[] = "Instances";

// WebRTC-AppRTC integration test. Requires a real webcam and microphone
// on the running system. This test is not meant to run in the main browser
// test suite since normal tester machines do not have webcams. Chrome will use
// this camera for the regular AppRTC test whereas Firefox will use it in the
// Firefox interop test (where case Chrome will use its built-in fake device).
//
// This test will bring up a AppRTC instance on localhost and verify that the
// call gets up when connecting to the same room from two tabs in a browser.
class WebRtcApprtcBrowserTest : public WebRtcTestBase {
 public:
  WebRtcApprtcBrowserTest()
      : dev_appserver_(base::kNullProcessHandle),
        firefox_(base::kNullProcessHandle) {
  }

  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));

    // The video playback will not work without a GPU, so force its use here.
    command_line->AppendSwitch(switches::kUseGpuInTests);
  }

  virtual void TearDown() OVERRIDE {
    // Kill any processes we may have brought up.
    if (dev_appserver_ != base::kNullProcessHandle)
      base::KillProcess(dev_appserver_, 0, false);
    // TODO(phoglund): Find some way to shut down Firefox cleanly on Windows.
    if (firefox_ != base::kNullProcessHandle)
      base::KillProcess(firefox_, 0, false);
  }

 protected:
  bool LaunchApprtcInstanceOnLocalhost() {
    base::FilePath appengine_dev_appserver =
        GetSourceDir().Append(
            FILE_PATH_LITERAL("../google_appengine/dev_appserver.py"));
    if (!base::PathExists(appengine_dev_appserver)) {
      LOG(ERROR) << "Missing appengine sdk at " <<
          appengine_dev_appserver.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }

    base::FilePath apprtc_dir =
        GetSourceDir().Append(FILE_PATH_LITERAL("out/apprtc"));
    if (!base::PathExists(apprtc_dir)) {
      LOG(ERROR) << "Missing AppRTC code at " <<
          apprtc_dir.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }

    CommandLine command_line(CommandLine::NO_PROGRAM);
    EXPECT_TRUE(GetPythonCommand(&command_line));

    command_line.AppendArgPath(appengine_dev_appserver);
    command_line.AppendArgPath(apprtc_dir);
    command_line.AppendArg("--port=9999");
    command_line.AppendArg("--admin_port=9998");
    command_line.AppendArg("--skip_sdk_update_check");

    VLOG(1) << "Running " << command_line.GetCommandLineString();
    return base::LaunchProcess(command_line, base::LaunchOptions(),
                               &dev_appserver_);
  }

  bool LocalApprtcInstanceIsUp() {
    // Load the admin page and see if we manage to load it right.
    ui_test_utils::NavigateToURL(browser(), GURL("localhost:9998"));
    content::WebContents* tab_contents =
        browser()->tab_strip_model()->GetActiveWebContents();
    std::string javascript =
        "window.domAutomationController.send(document.title)";
    std::string result;
    if (!content::ExecuteScriptAndExtractString(tab_contents, javascript,
                                                &result))
      return false;

    return result == kTitlePageOfAppEngineAdminPage;
  }

  bool WaitForCallToComeUp(content::WebContents* tab_contents) {
    // Apprtc will set remoteVideo.style.opacity to 1 when the call comes up.
    std::string javascript =
        "window.domAutomationController.send(remoteVideo.style.opacity)";
    return PollingWaitUntil(javascript, "1", tab_contents);
  }

  base::FilePath GetSourceDir() {
    base::FilePath source_dir;
    PathService::Get(base::DIR_SOURCE_ROOT, &source_dir);
    return source_dir;
  }

  bool LaunchFirefoxWithUrl(const GURL& url) {
    base::FilePath firefox_binary =
        GetSourceDir().Append(
            FILE_PATH_LITERAL("../firefox-nightly/firefox/firefox"));
    if (!base::PathExists(firefox_binary)) {
      LOG(ERROR) << "Missing firefox binary at " <<
          firefox_binary.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }
    base::FilePath firefox_launcher =
        GetSourceDir().Append(
            FILE_PATH_LITERAL("../webrtc.DEPS/run_firefox_webrtc.py"));
    if (!base::PathExists(firefox_launcher)) {
      LOG(ERROR) << "Missing firefox launcher at " <<
          firefox_launcher.value() << ". " << kAdviseOnGclientSolution;
      return false;
    }

    CommandLine command_line(firefox_launcher);
    command_line.AppendSwitchPath("--binary", firefox_binary);
    command_line.AppendSwitchASCII("--webpage", url.spec());

    VLOG(1) << "Running " << command_line.GetCommandLineString();
    return base::LaunchProcess(command_line, base::LaunchOptions(),
                               &firefox_);

    return true;
  }

 private:
  base::ProcessHandle dev_appserver_;
  base::ProcessHandle firefox_;
};

IN_PROC_BROWSER_TEST_F(WebRtcApprtcBrowserTest, MANUAL_WorksOnApprtc) {
  // TODO(mcasas): Remove Win version filtering when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=2703
#if defined(OS_WIN)
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return;
#endif
  DetectErrorsInJavaScript();
  ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost());
  while (!LocalApprtcInstanceIsUp())
    VLOG(1) << "Waiting for AppRTC to come up...";

  GURL room_url = GURL(base::StringPrintf("localhost:9999?r=room_%d",
                                          base::RandInt(0, 65536)));

  chrome::AddTabAt(browser(), GURL(), -1, true);
  content::WebContents* left_tab = OpenPageAndAcceptUserMedia(room_url);
  // TODO(phoglund): Remove when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=1742
  SleepInJavascript(left_tab, 5000);
  chrome::AddTabAt(browser(), GURL(), -1, true);
  content::WebContents* right_tab = OpenPageAndAcceptUserMedia(room_url);

  ASSERT_TRUE(WaitForCallToComeUp(left_tab));
  ASSERT_TRUE(WaitForCallToComeUp(right_tab));
}

#if defined(OS_LINUX)
#define MAYBE_MANUAL_FirefoxApprtcInteropTest MANUAL_FirefoxApprtcInteropTest
#else
// Not implemented yet on Windows and Mac.
#define MAYBE_MANUAL_FirefoxApprtcInteropTest DISABLED_MANUAL_FirefoxApprtcInteropTest
#endif

IN_PROC_BROWSER_TEST_F(WebRtcApprtcBrowserTest,
                       MAYBE_MANUAL_FirefoxApprtcInteropTest) {
  // TODO(mcasas): Remove Win version filtering when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=2703
#if defined(OS_WIN)
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return;
#endif

  DetectErrorsInJavaScript();
  ASSERT_TRUE(LaunchApprtcInstanceOnLocalhost());
  while (!LocalApprtcInstanceIsUp())
    VLOG(1) << "Waiting for AppRTC to come up...";

  // Run Chrome with a fake device to avoid having the browsers fight over the
  // camera (we'll just give that to firefox here).
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kUseFakeDeviceForMediaStream);

  GURL room_url = GURL(base::StringPrintf("http://localhost:9999?r=room_%d",
                                          base::RandInt(0, 65536)));
  content::WebContents* chrome_tab = OpenPageAndAcceptUserMedia(room_url);

  // TODO(phoglund): Remove when this bug gets fixed:
  // http://code.google.com/p/webrtc/issues/detail?id=1742
  SleepInJavascript(chrome_tab, 5000);

  ASSERT_TRUE(LaunchFirefoxWithUrl(room_url));

  ASSERT_TRUE(WaitForCallToComeUp(chrome_tab));
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef _SYMBOL_LOADER_HXX
#define _SYMBOL_LOADER_HXX

#include <iostream>
#include <osl/module.h>
#include <rtl/ustring.hxx>

#define SYM_MAP(a) { #a, (SymbolFunc *)&a }

typedef void (*SymbolFunc) (void);

struct ApiMap
{
    const char *symName;
    SymbolFunc *refValue;
};

namespace
{
    const char *libNames[] = {
        "libvlc.so.5",
        "libvlccore.so.5"
    };

    template<size_t N>
    bool tryLink( oslModule &aModule, const ApiMap ( &pMap )[N] )
    {
        for (uint i = 0; i < N; ++i)
        {
            SymbolFunc aMethod = ( SymbolFunc )osl_getFunctionSymbol
                ( aModule, OUString::createFromAscii ( pMap[ i ].symName ).pData );
            if ( !aMethod )
                return false;

            *pMap[ i ].refValue = aMethod;
        }

        return true;
    }
}

template<size_t N>
bool InitApiMap( const ApiMap ( &pMap )[N]  )
{
    oslModule aModule;

    for (uint j = 0; j < sizeof(libNames) / sizeof(libNames[0]); ++j)
    {
        aModule = osl_loadModule( OUString::createFromAscii
                                  ( libNames[ j ] ).pData,
                                  SAL_LOADMODULE_DEFAULT );

        if( aModule == NULL)
            continue;

        tryLink( aModule, pMap );

        osl_unloadModule( aModule );
    }

    return false;
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Finding libvlc in Mac OS/Windows platforms<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef _SYMBOL_LOADER_HXX
#define _SYMBOL_LOADER_HXX

#include <iostream>
#include <osl/module.h>
#include <rtl/ustring.hxx>

#define SYM_MAP(a) { #a, (SymbolFunc *)&a }

typedef void (*SymbolFunc) (void);

struct ApiMap
{
    const char *symName;
    SymbolFunc *refValue;
};

namespace
{
    const char *libNames[] = {
        "libvlc.so.5",
        "libvlccore.so.5",
        "libvlc.dll",
        "libvlc.dylib"
    };

    template<size_t N>
    bool tryLink( oslModule &aModule, const ApiMap ( &pMap )[N] )
    {
        for (uint i = 0; i < N; ++i)
        {
            SymbolFunc aMethod = ( SymbolFunc )osl_getFunctionSymbol
                ( aModule, OUString::createFromAscii( pMap[ i ].symName ).pData );
            if ( !aMethod )
                return false;

            *pMap[ i ].refValue = aMethod;
        }

        return true;
    }
}

template<size_t N>
bool InitApiMap( const ApiMap ( &pMap )[N]  )
{
    oslModule aModule;

    for (uint j = 0; j < sizeof(libNames) / sizeof(libNames[0]); ++j)
    {
        aModule = osl_loadModule( OUString::createFromAscii
                                  ( libNames[ j ] ).pData,
                                  SAL_LOADMODULE_DEFAULT );

        if( aModule == NULL)
            continue;

        tryLink( aModule, pMap );

        osl_unloadModule( aModule );
    }

    return false;
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Data definitions.
@ingroup data
*/

#pragma once

#include <Hord/config.hpp>
#include <Hord/utility.hpp>
#include <Hord/String.hpp>
#include <Hord/serialization.hpp>
#include <Hord/Object/Defs.hpp>

#include <type_traits>

namespace Hord {
namespace Data {

// Forward declarations
enum class ValueType : std::uint8_t;
enum class ValueFlag : std::uint8_t;
enum class Size : std::uint8_t;
struct Type;

/**
	@addtogroup data
	@{
*/

/**
	Type value type.
*/
using TypeValue = std::uint8_t;

/**
	Data value types.
*/
enum class ValueType : Data::TypeValue {
	/**
		Empty type.

		@note This is for special purposes.
	*/
	null,

	/** Type-stored value. */
	dynamic,

	/** Integer. */
	integer,

	/** Floating-point type. */
	decimal,

	/** Object ID. */
	object_id,

	/** String. */
	string,
};

/**
	Data value flags.
*/
enum class ValueFlag : Data::TypeValue {
	/** Empty flag. */
	none = 0u,

	/** Make ValueType::integer signed. */
	integer_signed = 1 << 0,
};

/**
	Data value size in bits.

	@note Size has no effect on @c ValueType::object_id.
	Size is a storage hint for @c ValueType::dynamic. Variably-sized
	types (e.g., string) only use b64 as a storage hint. The maximum
	variably-sized size value is b32.
*/
enum class Size : Data::TypeValue {
	/** 8 bits. */
	b8,
	/** 16 bits. */
	b16,
	/** 32 bits. */
	b32,
	/** 64 bits. */
	b64,
};

/** @cond INTERNAL */
constexpr auto const
value_type_first{Data::ValueType::null},
value_type_last{Data::ValueType::object_id};
/** @endcond */ // INTERNAL

/**
	Type.
*/
struct Type {
private:
	enum : unsigned {
		mask_type = 0x07,
		mask_flags = 0x07,
		shift_flags = 4,
		shift_size = 6,
	};

	static constexpr Data::TypeValue
	make_value(
		Data::ValueType const value_type,
		Data::ValueFlag const value_flags,
		Data::Size const size
	) noexcept {
		return
			(enum_cast(value_type)) |
			(enum_cast(value_flags) << shift_flags) |
			(enum_cast(size) << shift_size)
		;
	}

	enum : Data::TypeValue {
		value_null
			= (enum_cast(Data::ValueType::null))
			| (enum_cast(Data::ValueFlag::none) << shift_flags)
			| (enum_cast(Data::Size::b8) << shift_size)
		,
	};

	Data::TypeValue m_value{value_null};

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~Type() noexcept = default;

	/** Default constructor. */
	constexpr Type() = default;
	/** Copy constructor. */
	constexpr Type(Type const&) = default;
	/** Copy assignment operator. */
	Type& operator=(Type const&) = default;
	/** Move constructor. */
	constexpr Type(Type&&) = default;
	/** Move assignment operator. */
	Type& operator=(Type&&) = default;

	/**
		Construct with data value type and size.
	*/
	constexpr
	Type(
		Data::ValueType const value_type,
		Data::Size const size = Data::Size::b8
	) noexcept
		: m_value(make_value(value_type, Data::ValueFlag::none, size))
	{}

	/**
		Construct with data value type, flags, and size.
	*/
	constexpr
	Type(
		Data::ValueType const value_type,
		Data::ValueFlag const value_flags,
		Data::Size const size = Data::Size::b8
	) noexcept
		: m_value(make_value(value_type, value_flags, size))
	{}
/// @}

/** @name Operators */ /// @{
	/**
		Equal-to operator.
	*/
	constexpr bool
	operator==(
		Type const& rhs
	) const noexcept {
		return value() == rhs.value();
	}

	/**
		Not-equal-to operator.
	*/
	constexpr bool
	operator!=(
		Type const& rhs
	) const noexcept {
		return value() != rhs.value();
	}
/// @}

/** @name Properties */ /// @{
	/**
		Get value type.
	*/
	constexpr Data::ValueType
	type() const noexcept {
		return static_cast<Data::ValueType>(m_value & mask_type);
	}

	/**
		Get value flags.
	*/
	constexpr Data::ValueFlag
	flags() const noexcept {
		return static_cast<Data::ValueFlag>((m_value >> shift_flags) & mask_flags);
	}

	/**
		Get value size.
	*/
	constexpr Data::Size
	size() const noexcept {
		return static_cast<Data::Size>(m_value >> shift_size);
	}

	/**
		Get value.

		@remarks This is the serial form.
	*/
	constexpr Data::TypeValue
	value() const noexcept {
		return m_value;
	}

	/**
		Set value.

		@remarks This is the serial form.
	*/
	void
	set_value(
		Data::TypeValue const value
	) noexcept {
		m_value = value;
	}
/// @}

/** @name Serialization */ /// @{
	/**
		Serialize.

		@throws SerializerError{..}
		If a serialization operation failed.
	*/
	template<class Ser>
	ser_result_type
	serialize(
		ser_tag_serialize,
		Ser& ser
	) {
		auto& self = const_safe<Ser>(*this);
		ser(self.m_value);
	}
/// @}
};

/** @cond INTERNAL */
namespace {

template<class>
struct type_traits_impl {
	static constexpr Data::Type
	value() { return {Data::ValueType::null}; }
};

#define HORD_DEFINE_TYPE_TO_DATA_TYPE(T, VT, VF, SZ)				\
	template<> struct type_traits_impl<T> {							\
		static constexpr Data::Type									\
		value() {													\
			return {												\
				Data::ValueType:: VT,								\
				Data::ValueFlag:: VF,								\
				Data::Size:: SZ										\
			};														\
		}															\
	} //

HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int8_t , integer, integer_signed, b8);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int16_t, integer, integer_signed, b16);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int32_t, integer, integer_signed, b32);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int64_t, integer, integer_signed, b64);

HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint8_t , integer, none, b8);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint16_t, integer, none, b16);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint32_t, integer, none, b32);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint64_t, integer, none, b64);

HORD_DEFINE_TYPE_TO_DATA_TYPE(float , decimal, none, b32);
HORD_DEFINE_TYPE_TO_DATA_TYPE(double, decimal, none, b64);

#undef HORD_DEFINE_TYPE_TO_DATA_TYPE

template<Object::BaseType const B>
struct type_traits_impl<Object::GenID<B>> {
	static constexpr Data::Type const
	value() { return {Data::ValueType::object_id}; }
};

} // anonymous namespace
/** @endcond */ // INTERNAL

/**
	Get data type for type.

	@note @c value will be Data::Type::null if the type does not have
	a conversion to Data::Type.
*/
template<class T>
struct type_traits {
	static constexpr Data::Type
	value() {
		return {Data::type_traits_impl<typename std::remove_const<T>::type>::value()};
	}
};

/** @} */ // end of doc-group data

} // namespace Data
} // namespace Hord
<commit_msg>Data::Type: added Data::ValueType equality operators.<commit_after>/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Data definitions.
@ingroup data
*/

#pragma once

#include <Hord/config.hpp>
#include <Hord/utility.hpp>
#include <Hord/String.hpp>
#include <Hord/serialization.hpp>
#include <Hord/Object/Defs.hpp>

#include <type_traits>

namespace Hord {
namespace Data {

// Forward declarations
enum class ValueType : std::uint8_t;
enum class ValueFlag : std::uint8_t;
enum class Size : std::uint8_t;
struct Type;

/**
	@addtogroup data
	@{
*/

/**
	Type value type.
*/
using TypeValue = std::uint8_t;

/**
	Data value types.
*/
enum class ValueType : Data::TypeValue {
	/**
		Empty type.

		@note This is for special purposes.
	*/
	null,

	/** Type-stored value. */
	dynamic,

	/** Integer. */
	integer,

	/** Floating-point type. */
	decimal,

	/** Object ID. */
	object_id,

	/** String. */
	string,
};

/**
	Data value flags.
*/
enum class ValueFlag : Data::TypeValue {
	/** Empty flag. */
	none = 0u,

	/** Make ValueType::integer signed. */
	integer_signed = 1 << 0,
};

/**
	Data value size in bits.

	@note Size has no effect on @c ValueType::object_id.
	Size is a storage hint for @c ValueType::dynamic. Variably-sized
	types (e.g., string) only use b64 as a storage hint. The maximum
	variably-sized size value is b32.
*/
enum class Size : Data::TypeValue {
	/** 8 bits. */
	b8,
	/** 16 bits. */
	b16,
	/** 32 bits. */
	b32,
	/** 64 bits. */
	b64,
};

/** @cond INTERNAL */
constexpr auto const
value_type_first{Data::ValueType::null},
value_type_last{Data::ValueType::object_id};
/** @endcond */ // INTERNAL

/**
	Type.
*/
struct Type {
private:
	enum : unsigned {
		mask_type = 0x07,
		mask_flags = 0x07,
		shift_flags = 4,
		shift_size = 6,
	};

	static constexpr Data::TypeValue
	make_value(
		Data::ValueType const value_type,
		Data::ValueFlag const value_flags,
		Data::Size const size
	) noexcept {
		return
			(enum_cast(value_type)) |
			(enum_cast(value_flags) << shift_flags) |
			(enum_cast(size) << shift_size)
		;
	}

	enum : Data::TypeValue {
		value_null
			= (enum_cast(Data::ValueType::null))
			| (enum_cast(Data::ValueFlag::none) << shift_flags)
			| (enum_cast(Data::Size::b8) << shift_size)
		,
	};

	Data::TypeValue m_value{value_null};

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~Type() noexcept = default;

	/** Default constructor. */
	constexpr Type() = default;
	/** Copy constructor. */
	constexpr Type(Type const&) = default;
	/** Copy assignment operator. */
	Type& operator=(Type const&) = default;
	/** Move constructor. */
	constexpr Type(Type&&) = default;
	/** Move assignment operator. */
	Type& operator=(Type&&) = default;

	/**
		Construct with data value type and size.
	*/
	constexpr
	Type(
		Data::ValueType const value_type,
		Data::Size const size = Data::Size::b8
	) noexcept
		: m_value(make_value(value_type, Data::ValueFlag::none, size))
	{}

	/**
		Construct with data value type, flags, and size.
	*/
	constexpr
	Type(
		Data::ValueType const value_type,
		Data::ValueFlag const value_flags,
		Data::Size const size = Data::Size::b8
	) noexcept
		: m_value(make_value(value_type, value_flags, size))
	{}
/// @}

/** @name Operators */ /// @{
	/**
		Equal-to operator.
	*/
	constexpr bool
	operator==(
		Data::Type const& rhs
	) const noexcept {
		return value() == rhs.value();
	}

	/**
		Not-equal-to operator.
	*/
	constexpr bool
	operator!=(
		Data::Type const& rhs
	) const noexcept {
		return value() != rhs.value();
	}

	/**
		Equal-to operator (ValueType).
	*/
	constexpr bool
	operator==(
		Data::ValueType const& rhs
	) const noexcept {
		return type() == rhs;
	}

	/**
		Not-equal-to operator (ValueType).
	*/
	constexpr bool
	operator!=(
		Data::ValueType const& rhs
	) const noexcept {
		return type() != rhs;
	}
/// @}

/** @name Properties */ /// @{
	/**
		Get value type.
	*/
	constexpr Data::ValueType
	type() const noexcept {
		return static_cast<Data::ValueType>(m_value & mask_type);
	}

	/**
		Get value flags.
	*/
	constexpr Data::ValueFlag
	flags() const noexcept {
		return static_cast<Data::ValueFlag>((m_value >> shift_flags) & mask_flags);
	}

	/**
		Get value size.
	*/
	constexpr Data::Size
	size() const noexcept {
		return static_cast<Data::Size>(m_value >> shift_size);
	}

	/**
		Get value.

		@remarks This is the serial form.
	*/
	constexpr Data::TypeValue
	value() const noexcept {
		return m_value;
	}

	/**
		Set value.

		@remarks This is the serial form.
	*/
	void
	set_value(
		Data::TypeValue const value
	) noexcept {
		m_value = value;
	}
/// @}

/** @name Serialization */ /// @{
	/**
		Serialize.

		@throws SerializerError{..}
		If a serialization operation failed.
	*/
	template<class Ser>
	ser_result_type
	serialize(
		ser_tag_serialize,
		Ser& ser
	) {
		auto& self = const_safe<Ser>(*this);
		ser(self.m_value);
	}
/// @}
};

/** @cond INTERNAL */
namespace {

template<class>
struct type_traits_impl {
	static constexpr Data::Type
	value() { return {Data::ValueType::null}; }
};

#define HORD_DEFINE_TYPE_TO_DATA_TYPE(T, VT, VF, SZ)				\
	template<> struct type_traits_impl<T> {							\
		static constexpr Data::Type									\
		value() {													\
			return {												\
				Data::ValueType:: VT,								\
				Data::ValueFlag:: VF,								\
				Data::Size:: SZ										\
			};														\
		}															\
	} //

HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int8_t , integer, integer_signed, b8);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int16_t, integer, integer_signed, b16);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int32_t, integer, integer_signed, b32);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::int64_t, integer, integer_signed, b64);

HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint8_t , integer, none, b8);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint16_t, integer, none, b16);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint32_t, integer, none, b32);
HORD_DEFINE_TYPE_TO_DATA_TYPE(std::uint64_t, integer, none, b64);

HORD_DEFINE_TYPE_TO_DATA_TYPE(float , decimal, none, b32);
HORD_DEFINE_TYPE_TO_DATA_TYPE(double, decimal, none, b64);

#undef HORD_DEFINE_TYPE_TO_DATA_TYPE

template<Object::BaseType const B>
struct type_traits_impl<Object::GenID<B>> {
	static constexpr Data::Type const
	value() { return {Data::ValueType::object_id}; }
};

} // anonymous namespace
/** @endcond */ // INTERNAL

/**
	Get data type for type.

	@note @c value will be Data::Type::null if the type does not have
	a conversion to Data::Type.
*/
template<class T>
struct type_traits {
	static constexpr Data::Type
	value() {
		return {Data::type_traits_impl<typename std::remove_const<T>::type>::value()};
	}
};

/** @} */ // end of doc-group data

} // namespace Data
} // namespace Hord
<|endoftext|>