<commit_before>// -*- C++ -*-

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);

  // Takes a pointer and returns how much space it holds.
  size_t xxmalloc_usable_size (void *);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

// From GNU libc 2.14 this macro is defined, to declare
// hook variables as volatile. Define it as empty for
// older glibc versions
#ifndef __MALLOC_HOOK_VOLATILE
 #define __MALLOC_HOOK_VOLATILE
#endif

  void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    // Store the old hooks.
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    old_realloc_hook = __realloc_hook;
    old_memalign_hook = __memalign_hook;

    // Point the hooks to the replacement functions.
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
    __realloc_hook = my_realloc_hook;
    __memalign_hook = my_memalign_hook;

    initialized = true;
  }

  static void * my_malloc_hook (size_t size, const void *) {
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size) throw()
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  size_t malloc_usable_size (void * ptr) throw() {
    return xxmalloc_usable_size (ptr);
  }

}

<commit_msg>Added checks to make sure we are initialized. Added new interception.<commit_after>// -*- C++ -*-

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <new>

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);

  // Takes a pointer and returns how much space it holds.
  size_t xxmalloc_usable_size (void *);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

// From GNU libc 2.14 this macro is defined, to declare
// hook variables as volatile. Define it as empty for
// older glibc versions
#ifndef __MALLOC_HOOK_VOLATILE
 #define __MALLOC_HOOK_VOLATILE
#endif

  void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    // Store the old hooks.
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    old_realloc_hook = __realloc_hook;
    old_memalign_hook = __memalign_hook;

    // Point the hooks to the replacement functions.
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
    __realloc_hook = my_realloc_hook;
    __memalign_hook = my_memalign_hook;

    initialized = true;
  }

  static void * my_malloc_hook (size_t size, const void *) {
    if (!initialized) {
      my_init_hook();
    }
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    if (!initialized) {
      my_init_hook();
    }
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    if (!initialized) {
      my_init_hook();
    }
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size) throw()
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  size_t malloc_usable_size (void * ptr) throw() {
    if (!initialized) {
      my_init_hook();
    }
    return xxmalloc_usable_size (ptr);
  }

  int mallopt (int param, int value) throw() {
    // NOP.
    return 1; // success.
  }

  int malloc_trim (size_t pad) throw() {
    // NOP.
    return 0; // no memory returned to OS.
  }

  void malloc_stats (void) throw() {
    // NOP.
  }

  void * malloc_get_state (void) throw() {
    return NULL; // always returns "error".
  }

  int malloc_set_state (void * ptr) throw() {
    return 0; // success.
  }

  struct mallinfo mallinfo(void) throw() {
    // For now, we return useless stats.
    struct mallinfo m;
    m.arena = 0;
    m.ordblks = 0;
    m.smblks = 0;
    m.hblks = 0;
    m.hblkhd = 0;
    m.usmblks = 0;
    m.fsmblks = 0;
    m.uordblks = 0;
    m.fordblks = 0;
    m.keepcost = 0;
    return m;
  }

}

void * operator new (size_t sz) throw (std::bad_alloc)
{
  void * ptr = xxmalloc (sz);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void operator delete (void * ptr)
  throw ()
{
  xxfree (ptr);
}

void * operator new (size_t sz, const std::nothrow_t&) throw() {
  return xxmalloc(sz);
}

void * operator new[] (size_t size)
  throw (std::bad_alloc)
{
  void * ptr = xxmalloc(size);
  if (ptr == NULL) {
    throw std::bad_alloc();
  } else {
    return ptr;
  }
}

void * operator new[] (size_t sz, const std::nothrow_t&)
  throw()
 {
  return xxmalloc(sz);
}

void operator delete[] (void * ptr)
  throw ()
{
  xxfree (ptr);
}
<|endoftext|>


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

// exploitability_win.cc: Windows specific exploitability engine.
//
// Provides a guess at the exploitability of the crash for the Windows
// platform given a minidump and process_state.
//
// Author: Cris Neckar

#include <vector>

#include "processor/exploitability_win.h"

#include "common/scoped_ptr.h"
#include "google_breakpad/common/minidump_exception_win32.h"
#include "google_breakpad/processor/minidump.h"
#include "processor/disassembler_x86.h"
#include "processor/logging.h"

#include "third_party/libdisasm/libdis.h"

namespace google_breakpad {

// The cutoff that we use to judge if and address is likely an offset
// from various interesting addresses.
static const uint64_t kProbableNullOffset = 4096;
static const uint64_t kProbableStackOffset = 8192;

// The various cutoffs for the different ratings.
static const size_t kHighCutoff        = 100;
static const size_t kMediumCutoff      = 80;
static const size_t kLowCutoff         = 50;
static const size_t kInterestingCutoff = 25;

// Predefined incremental values for conditional weighting.
static const size_t kTinyBump          = 5;
static const size_t kSmallBump         = 20;
static const size_t kMediumBump        = 50;
static const size_t kLargeBump         = 70;
static const size_t kHugeBump          = 90;

// The maximum number of bytes to disassemble past the program counter.
static const size_t kDisassembleBytesBeyondPC = 2048;

ExploitabilityWin::ExploitabilityWin(Minidump *dump,
                                     ProcessState *process_state)
    : Exploitability(dump, process_state) { }

ExploitabilityRating ExploitabilityWin::CheckPlatformExploitability() {
  MinidumpException *exception = dump_->GetException();
  if (!exception) {
    BPLOG(INFO) << "Minidump does not have exception record.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  const MDRawExceptionStream *raw_exception = exception->exception();
  if (!raw_exception) {
    BPLOG(INFO) << "Could not obtain raw exception info.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  const MinidumpContext *context = exception->GetContext();
  if (!context) {
    BPLOG(INFO) << "Could not obtain exception context.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  MinidumpMemoryList *memory_list = dump_->GetMemoryList();
  bool memory_available = true;
  if (!memory_list) {
    BPLOG(INFO) << "Minidump memory segments not available.";
    memory_available = false;
  }
  uint64_t address = process_state_->crash_address();
  uint32_t exception_code = raw_exception->exception_record.exception_code;

  uint32_t exploitability_weight = 0;

  uint64_t stack_ptr = 0;
  uint64_t instruction_ptr = 0;
  uint64_t this_ptr = 0;

  switch (context->GetContextCPU()) {
    case MD_CONTEXT_X86:
      stack_ptr = context->GetContextX86()->esp;
      instruction_ptr = context->GetContextX86()->eip;
      this_ptr = context->GetContextX86()->ecx;
      break;
    case MD_CONTEXT_AMD64:
      stack_ptr = context->GetContextAMD64()->rsp;
      instruction_ptr = context->GetContextAMD64()->rip;
      this_ptr = context->GetContextAMD64()->rcx;
      break;
    default:
      BPLOG(INFO) << "Unsupported architecture.";
      return EXPLOITABILITY_ERR_PROCESSING;
  }

  // Check if we are executing on the stack.
  if (instruction_ptr <= (stack_ptr + kProbableStackOffset) &&
      instruction_ptr >= (stack_ptr - kProbableStackOffset))
    exploitability_weight += kHugeBump;

  switch (exception_code) {
    // This is almost certainly recursion.
    case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
      exploitability_weight += kTinyBump;
      break;

    // These exceptions tend to be benign and we can generally ignore them.
    case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
    case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
    case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
    case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
    case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
    case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
    case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
      exploitability_weight += kTinyBump;
      break;

    // These exceptions will typically mean that we have jumped where we
    // shouldn't.
    case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
    case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
    case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
      exploitability_weight += kLargeBump;
      break;

    // These represent bugs in exception handlers.
    case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
    case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
      exploitability_weight += kSmallBump;
      break;

    case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
    case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
      exploitability_weight += kHugeBump;
      break;

    case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
      exploitability_weight += kLargeBump;
      break;

    case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
      bool near_null = (address <= kProbableNullOffset);
      bool bad_read = false;
      bool bad_write = false;
      if (raw_exception->exception_record.number_parameters >= 1) {
        MDAccessViolationTypeWin av_type =
            static_cast<MDAccessViolationTypeWin>
            (raw_exception->exception_record.exception_information[0]);
        switch (av_type) {
          case MD_ACCESS_VIOLATION_WIN_READ:
            bad_read = true;
            if (near_null)
              exploitability_weight += kSmallBump;
            else
              exploitability_weight += kMediumBump;
            break;
          case MD_ACCESS_VIOLATION_WIN_WRITE:
            bad_write = true;
            if (near_null)
              exploitability_weight += kSmallBump;
            else
              exploitability_weight += kHugeBump;
            break;
          case MD_ACCESS_VIOLATION_WIN_EXEC:
            if (near_null)
              exploitability_weight += kSmallBump;
            else
              exploitability_weight += kHugeBump;
            break;
          default:
            BPLOG(INFO) << "Unrecognized access violation type.";
            return EXPLOITABILITY_ERR_PROCESSING;
            break;
        }
        MinidumpMemoryRegion *instruction_region = 0;
        if (memory_available) {
          instruction_region =
              memory_list->GetMemoryRegionForAddress(instruction_ptr);
        }
        if (!near_null && instruction_region &&
            context->GetContextCPU() == MD_CONTEXT_X86 &&
            (bad_read || bad_write)) {
          // Perform checks related to memory around instruction pointer.
          uint32_t memory_offset =
              instruction_ptr - instruction_region->GetBase();
          uint32_t available_memory =
              instruction_region->GetSize() - memory_offset;
          available_memory = available_memory > kDisassembleBytesBeyondPC ?
              kDisassembleBytesBeyondPC : available_memory;
          if (available_memory) {
            const uint8_t *raw_memory =
                instruction_region->GetMemory() + memory_offset;
            DisassemblerX86 disassembler(raw_memory,
                                         available_memory,
                                         instruction_ptr);
            disassembler.NextInstruction();
            if (bad_read)
              disassembler.setBadRead();
            else
              disassembler.setBadWrite();
            if (disassembler.currentInstructionValid()) {
              // Check if the faulting instruction falls into one of
              // several interesting groups.
              switch (disassembler.currentInstructionGroup()) {
                case libdis::insn_controlflow:
                  exploitability_weight += kLargeBump;
                  break;
                case libdis::insn_string:
                  exploitability_weight += kHugeBump;
                  break;
                default:
                  break;
              }
              // Loop the disassembler through the code and check if it
              // IDed any interesting conditions in the near future.
              // Multiple flags may be set so treat each equally.
              while (disassembler.NextInstruction() &&
                     disassembler.currentInstructionValid() &&
                     !disassembler.endOfBlock())
                continue;
              if (disassembler.flags() & DISX86_BAD_BRANCH_TARGET)
                exploitability_weight += kLargeBump;
              if (disassembler.flags() & DISX86_BAD_ARGUMENT_PASSED)
                exploitability_weight += kTinyBump;
              if (disassembler.flags() & DISX86_BAD_WRITE)
                exploitability_weight += kMediumBump;
              if (disassembler.flags() & DISX86_BAD_BLOCK_WRITE)
                exploitability_weight += kMediumBump;
              if (disassembler.flags() & DISX86_BAD_READ)
                exploitability_weight += kTinyBump;
              if (disassembler.flags() & DISX86_BAD_BLOCK_READ)
                exploitability_weight += kTinyBump;
              if (disassembler.flags() & DISX86_BAD_COMPARISON)
                exploitability_weight += kTinyBump;
            }
          }
        }
        if (!near_null && AddressIsAscii(address))
          exploitability_weight += kMediumBump;
      } else {
        BPLOG(INFO) << "Access violation type parameter missing.";
        return EXPLOITABILITY_ERR_PROCESSING;
      }
  }

  // Based on the calculated weight we return a simplified classification.
  BPLOG(INFO) << "Calculated exploitability weight: " << exploitability_weight;
  if (exploitability_weight >= kHighCutoff)
    return EXPLOITABILITY_HIGH;
  if (exploitability_weight >= kMediumCutoff)
    return EXPLOITABLITY_MEDIUM;
  if (exploitability_weight >= kLowCutoff)
    return EXPLOITABILITY_LOW;
  if (exploitability_weight >= kInterestingCutoff)
    return EXPLOITABILITY_INTERESTING;

  return EXPLOITABILITY_NONE;
}

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

// exploitability_win.cc: Windows specific exploitability engine.
//
// Provides a guess at the exploitability of the crash for the Windows
// platform given a minidump and process_state.
//
// Author: Cris Neckar

#include <vector>

#include "processor/exploitability_win.h"

#include "common/scoped_ptr.h"
#include "google_breakpad/common/minidump_exception_win32.h"
#include "google_breakpad/processor/minidump.h"
#include "processor/disassembler_x86.h"
#include "processor/logging.h"

#include "third_party/libdisasm/libdis.h"

namespace google_breakpad {

// The cutoff that we use to judge if and address is likely an offset
// from various interesting addresses.
static const uint64_t kProbableNullOffset = 4096;
static const uint64_t kProbableStackOffset = 8192;

// The various cutoffs for the different ratings.
static const size_t kHighCutoff        = 100;
static const size_t kMediumCutoff      = 80;
static const size_t kLowCutoff         = 50;
static const size_t kInterestingCutoff = 25;

// Predefined incremental values for conditional weighting.
static const size_t kTinyBump          = 5;
static const size_t kSmallBump         = 20;
static const size_t kMediumBump        = 50;
static const size_t kLargeBump         = 70;
static const size_t kHugeBump          = 90;

// The maximum number of bytes to disassemble past the program counter.
static const size_t kDisassembleBytesBeyondPC = 2048;

ExploitabilityWin::ExploitabilityWin(Minidump *dump,
                                     ProcessState *process_state)
    : Exploitability(dump, process_state) { }

ExploitabilityRating ExploitabilityWin::CheckPlatformExploitability() {
  MinidumpException *exception = dump_->GetException();
  if (!exception) {
    BPLOG(INFO) << "Minidump does not have exception record.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  const MDRawExceptionStream *raw_exception = exception->exception();
  if (!raw_exception) {
    BPLOG(INFO) << "Could not obtain raw exception info.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  const MinidumpContext *context = exception->GetContext();
  if (!context) {
    BPLOG(INFO) << "Could not obtain exception context.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  MinidumpMemoryList *memory_list = dump_->GetMemoryList();
  bool memory_available = true;
  if (!memory_list) {
    BPLOG(INFO) << "Minidump memory segments not available.";
    memory_available = false;
  }
  uint64_t address = process_state_->crash_address();
  uint32_t exception_code = raw_exception->exception_record.exception_code;

  uint32_t exploitability_weight = 0;

  uint64_t stack_ptr = 0;
  uint64_t instruction_ptr = 0;

  switch (context->GetContextCPU()) {
    case MD_CONTEXT_X86:
      stack_ptr = context->GetContextX86()->esp;
      instruction_ptr = context->GetContextX86()->eip;
      break;
    case MD_CONTEXT_AMD64:
      stack_ptr = context->GetContextAMD64()->rsp;
      instruction_ptr = context->GetContextAMD64()->rip;
      break;
    default:
      BPLOG(INFO) << "Unsupported architecture.";
      return EXPLOITABILITY_ERR_PROCESSING;
  }

  // Check if we are executing on the stack.
  if (instruction_ptr <= (stack_ptr + kProbableStackOffset) &&
      instruction_ptr >= (stack_ptr - kProbableStackOffset))
    exploitability_weight += kHugeBump;

  switch (exception_code) {
    // This is almost certainly recursion.
    case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
      exploitability_weight += kTinyBump;
      break;

    // These exceptions tend to be benign and we can generally ignore them.
    case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
    case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
    case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
    case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
    case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
    case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
    case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
      exploitability_weight += kTinyBump;
      break;

    // These exceptions will typically mean that we have jumped where we
    // shouldn't.
    case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
    case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
    case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
      exploitability_weight += kLargeBump;
      break;

    // These represent bugs in exception handlers.
    case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
    case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
      exploitability_weight += kSmallBump;
      break;

    case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
    case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
      exploitability_weight += kHugeBump;
      break;

    case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
      exploitability_weight += kLargeBump;
      break;

    case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
      bool near_null = (address <= kProbableNullOffset);
      bool bad_read = false;
      bool bad_write = false;
      if (raw_exception->exception_record.number_parameters >= 1) {
        MDAccessViolationTypeWin av_type =
            static_cast<MDAccessViolationTypeWin>
            (raw_exception->exception_record.exception_information[0]);
        switch (av_type) {
          case MD_ACCESS_VIOLATION_WIN_READ:
            bad_read = true;
            if (near_null)
              exploitability_weight += kSmallBump;
            else
              exploitability_weight += kMediumBump;
            break;
          case MD_ACCESS_VIOLATION_WIN_WRITE:
            bad_write = true;
            if (near_null)
              exploitability_weight += kSmallBump;
            else
              exploitability_weight += kHugeBump;
            break;
          case MD_ACCESS_VIOLATION_WIN_EXEC:
            if (near_null)
              exploitability_weight += kSmallBump;
            else
              exploitability_weight += kHugeBump;
            break;
          default:
            BPLOG(INFO) << "Unrecognized access violation type.";
            return EXPLOITABILITY_ERR_PROCESSING;
            break;
        }
        MinidumpMemoryRegion *instruction_region = 0;
        if (memory_available) {
          instruction_region =
              memory_list->GetMemoryRegionForAddress(instruction_ptr);
        }
        if (!near_null && instruction_region &&
            context->GetContextCPU() == MD_CONTEXT_X86 &&
            (bad_read || bad_write)) {
          // Perform checks related to memory around instruction pointer.
          uint32_t memory_offset =
              instruction_ptr - instruction_region->GetBase();
          uint32_t available_memory =
              instruction_region->GetSize() - memory_offset;
          available_memory = available_memory > kDisassembleBytesBeyondPC ?
              kDisassembleBytesBeyondPC : available_memory;
          if (available_memory) {
            const uint8_t *raw_memory =
                instruction_region->GetMemory() + memory_offset;
            DisassemblerX86 disassembler(raw_memory,
                                         available_memory,
                                         instruction_ptr);
            disassembler.NextInstruction();
            if (bad_read)
              disassembler.setBadRead();
            else
              disassembler.setBadWrite();
            if (disassembler.currentInstructionValid()) {
              // Check if the faulting instruction falls into one of
              // several interesting groups.
              switch (disassembler.currentInstructionGroup()) {
                case libdis::insn_controlflow:
                  exploitability_weight += kLargeBump;
                  break;
                case libdis::insn_string:
                  exploitability_weight += kHugeBump;
                  break;
                default:
                  break;
              }
              // Loop the disassembler through the code and check if it
              // IDed any interesting conditions in the near future.
              // Multiple flags may be set so treat each equally.
              while (disassembler.NextInstruction() &&
                     disassembler.currentInstructionValid() &&
                     !disassembler.endOfBlock())
                continue;
              if (disassembler.flags() & DISX86_BAD_BRANCH_TARGET)
                exploitability_weight += kLargeBump;
              if (disassembler.flags() & DISX86_BAD_ARGUMENT_PASSED)
                exploitability_weight += kTinyBump;
              if (disassembler.flags() & DISX86_BAD_WRITE)
                exploitability_weight += kMediumBump;
              if (disassembler.flags() & DISX86_BAD_BLOCK_WRITE)
                exploitability_weight += kMediumBump;
              if (disassembler.flags() & DISX86_BAD_READ)
                exploitability_weight += kTinyBump;
              if (disassembler.flags() & DISX86_BAD_BLOCK_READ)
                exploitability_weight += kTinyBump;
              if (disassembler.flags() & DISX86_BAD_COMPARISON)
                exploitability_weight += kTinyBump;
            }
          }
        }
        if (!near_null && AddressIsAscii(address))
          exploitability_weight += kMediumBump;
      } else {
        BPLOG(INFO) << "Access violation type parameter missing.";
        return EXPLOITABILITY_ERR_PROCESSING;
      }
  }

  // Based on the calculated weight we return a simplified classification.
  BPLOG(INFO) << "Calculated exploitability weight: " << exploitability_weight;
  if (exploitability_weight >= kHighCutoff)
    return EXPLOITABILITY_HIGH;
  if (exploitability_weight >= kMediumCutoff)
    return EXPLOITABLITY_MEDIUM;
  if (exploitability_weight >= kLowCutoff)
    return EXPLOITABILITY_LOW;
  if (exploitability_weight >= kInterestingCutoff)
    return EXPLOITABILITY_INTERESTING;

  return EXPLOITABILITY_NONE;
}

}  // namespace google_breakpad
<|endoftext|>


<commit_before>#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

using namespace boost::interprocess;

//Typedefs of allocators and containers
typedef managed_shared_memory::segment_manager                       segment_manager_t;
typedef allocator<void, segment_manager_t>                           void_allocator;
typedef allocator<int, segment_manager_t>                            int_allocator;
typedef vector<int, int_allocator>                                   int_vector;
typedef allocator<char, segment_manager_t>                           char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator>   char_string;

class complex_data {
public:
    int               id_;
    char_string       char_string_;
    int_vector int_vector_;

    //Since void_allocator is convertible to any other allocator<T>, we can simplify
    //the initialization taking just one allocator for all inner containers.
    complex_data ( const void_allocator &void_alloc )
        : id_ ( -1 ), char_string_ ( void_alloc ), int_vector_ ( void_alloc )
    {}
    // copy constructor
    complex_data ( const complex_data &o )
        : id_ ( o.id_ ), char_string_ ( o.char_string_, o.char_string_.get_allocator() ), int_vector_ ( o.int_vector_, o.int_vector_.get_allocator() )
    {}
    // copy assignment operator
    complex_data& operator= ( const complex_data& o ) {
        id_ = o.id_;
        char_string_ = o.char_string_;
        int_vector_ = o.int_vector_;
        return *this;
    }
    friend std::ostream &operator << ( std::ostream &os, const complex_data &o ) {
        os << "[" << o.id_ <<  ", " << o.char_string_ << ", ";
        for ( size_t i = 0; i < o.int_vector_.size(); i++ ) {
            os << ( i==0?"[ ": ", " ) << o.int_vector_[i] << ( i==o.int_vector_.size()-1?"]":"" );
        }
        return os;
    };
};

typedef allocator<complex_data, segment_manager_t>     complex_data_allocator;
typedef vector<complex_data, complex_data_allocator>   complex_data_vector;

template<class ForwardIt>
ForwardIt next(ForwardIt it, typename std::iterator_traits<ForwardIt>::difference_type n = 1)
{
    std::advance(it, n);
    return it;
}

template <typename V, typename Element /*= typename V::value_type*/>
static inline void resize ( V& vect, size_t newsize, Element const& element ) {
    if ( vect.size() < newsize ) {
        vect.insert (
            vect.end(),
            newsize - vect.size(),
            element
        );
    } else {
        vect.erase (
            next ( vect.begin(), newsize ),
            vect.end()
        );
    }
}

template <typename V>
static inline void resize ( V& vect, size_t newsize, typename V::allocator_type const& alloc_inst ) {
    resize ( vect, newsize, typename V::value_type ( alloc_inst ) );
}

template <typename V>
static inline void resize ( V& vect, size_t newsize ) {
    resize ( vect, newsize, typename V::value_type ( vect.get_allocator() ) );
}

int main () {
    //Remove shared memory on construction and destruction

    struct shm_remove {
        shm_remove() {
            shared_memory_object::remove ( "MySharedMemory" );
        }
        ~shm_remove() {
            shared_memory_object::remove ( "MySharedMemory" );
        }
    } remover;

    //Create shared memory
    managed_shared_memory segment;
    //A managed shared memory where we can construct objects
    //associated with a c-string
    try {
        segment =  managed_shared_memory ( create_only, "MySharedMemory", 65536 );
    } catch ( ... ) {
        segment = managed_shared_memory ( open_only, "MySharedMemory" );
    }

    //An allocator convertible to any allocator<T, segment_manager_t> type
    void_allocator alloc_inst ( segment.get_segment_manager() );

    //Construct the shared memory map and fill it
    complex_data *complex_data0_ = segment.find_or_construct<complex_data> ( "MyCompexData" ) ( alloc_inst );

    complex_data0_->char_string_ = "Hello World";
    complex_data0_->int_vector_.push_back ( 3 );

    complex_data *complex_data1_ = segment.find_or_construct<complex_data> ( "MyCompexData" ) ( alloc_inst );
    complex_data1_->int_vector_.push_back ( 6 );

    std::cout << *complex_data1_ << std::endl;

    complex_data_vector *complex_data_vector0 = segment.find_or_construct<complex_data_vector> ( "MyCompexDataVector" ) ( alloc_inst );
    complex_data_vector *complex_data_vector1 = segment.find_or_construct<complex_data_vector> ( "MyCompexDataVector" ) ( alloc_inst );

    /**
     * Problem
     * How to I resize or add new elements?
     **/
    //complex_data_vector0->resize(3); // --> still not working
    complex_data_vector0->clear();
    complex_data_vector0->insert ( complex_data_vector0->end(), 3, complex_data ( alloc_inst ) );
    complex_data_vector0->at ( 0 ) = *complex_data0_;
    for ( size_t i = 0; i < complex_data_vector0->size(); i++ ) {
        std::cout << complex_data_vector0->at ( i )  << std::endl;
    }
    std::cout << "--------------"  << std::endl;
    resize(*complex_data_vector1, 5, complex_data(alloc_inst));
    complex_data_vector0->at ( 4 ).id_ = 4;
    for ( size_t i = 0; i < complex_data_vector1->size(); i++ ) {
        std::cout << complex_data_vector1->at ( i )  << std::endl;
    }
    return 0;
}

<commit_msg>iostream include added<commit_after>
#include <iostream>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

using namespace boost::interprocess;

//Typedefs of allocators and containers
typedef managed_shared_memory::segment_manager                       segment_manager_t;
typedef allocator<void, segment_manager_t>                           void_allocator;
typedef allocator<int, segment_manager_t>                            int_allocator;
typedef vector<int, int_allocator>                                   int_vector;
typedef allocator<char, segment_manager_t>                           char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator>   char_string;

class complex_data {
public:
    int               id_;
    char_string       char_string_;
    int_vector int_vector_;

    //Since void_allocator is convertible to any other allocator<T>, we can simplify
    //the initialization taking just one allocator for all inner containers.
    complex_data ( const void_allocator &void_alloc )
        : id_ ( -1 ), char_string_ ( void_alloc ), int_vector_ ( void_alloc )
    {}
    // copy constructor
    complex_data ( const complex_data &o )
        : id_ ( o.id_ ), char_string_ ( o.char_string_, o.char_string_.get_allocator() ), int_vector_ ( o.int_vector_, o.int_vector_.get_allocator() )
    {}
    // copy assignment operator
    complex_data& operator= ( const complex_data& o ) {
        id_ = o.id_;
        char_string_ = o.char_string_;
        int_vector_ = o.int_vector_;
        return *this;
    }
    friend std::ostream &operator << ( std::ostream &os, const complex_data &o ) {
        os << "[" << o.id_ <<  ", " << o.char_string_ << ", ";
        for ( size_t i = 0; i < o.int_vector_.size(); i++ ) {
            os << ( i==0?"[ ": ", " ) << o.int_vector_[i] << ( i==o.int_vector_.size()-1?"]":"" );
        }
        return os;
    };
};

typedef allocator<complex_data, segment_manager_t>     complex_data_allocator;
typedef vector<complex_data, complex_data_allocator>   complex_data_vector;

template<class ForwardIt>
ForwardIt next(ForwardIt it, typename std::iterator_traits<ForwardIt>::difference_type n = 1)
{
    std::advance(it, n);
    return it;
}

template <typename V, typename Element /*= typename V::value_type*/>
static inline void resize ( V& vect, size_t newsize, Element const& element ) {
    if ( vect.size() < newsize ) {
        vect.insert (
            vect.end(),
            newsize - vect.size(),
            element
        );
    } else {
        vect.erase (
            next ( vect.begin(), newsize ),
            vect.end()
        );
    }
}

template <typename V>
static inline void resize ( V& vect, size_t newsize, typename V::allocator_type const& alloc_inst ) {
    resize ( vect, newsize, typename V::value_type ( alloc_inst ) );
}

template <typename V>
static inline void resize ( V& vect, size_t newsize ) {
    resize ( vect, newsize, typename V::value_type ( vect.get_allocator() ) );
}

int main () {
    //Remove shared memory on construction and destruction

    struct shm_remove {
        shm_remove() {
            shared_memory_object::remove ( "MySharedMemory" );
        }
        ~shm_remove() {
            shared_memory_object::remove ( "MySharedMemory" );
        }
    } remover;

    //Create shared memory
    managed_shared_memory segment;
    //A managed shared memory where we can construct objects
    //associated with a c-string
    try {
        segment =  managed_shared_memory ( create_only, "MySharedMemory", 65536 );
    } catch ( ... ) {
        segment = managed_shared_memory ( open_only, "MySharedMemory" );
    }

    //An allocator convertible to any allocator<T, segment_manager_t> type
    void_allocator alloc_inst ( segment.get_segment_manager() );

    //Construct the shared memory map and fill it
    complex_data *complex_data0_ = segment.find_or_construct<complex_data> ( "MyCompexData" ) ( alloc_inst );

    complex_data0_->char_string_ = "Hello World";
    complex_data0_->int_vector_.push_back ( 3 );

    complex_data *complex_data1_ = segment.find_or_construct<complex_data> ( "MyCompexData" ) ( alloc_inst );
    complex_data1_->int_vector_.push_back ( 6 );

    std::cout << *complex_data1_ << std::endl;

    complex_data_vector *complex_data_vector0 = segment.find_or_construct<complex_data_vector> ( "MyCompexDataVector" ) ( alloc_inst );
    complex_data_vector *complex_data_vector1 = segment.find_or_construct<complex_data_vector> ( "MyCompexDataVector" ) ( alloc_inst );

    /**
     * Problem
     * How to I resize or add new elements?
     **/
    //complex_data_vector0->resize(3); // --> still not working
    complex_data_vector0->clear();
    complex_data_vector0->insert ( complex_data_vector0->end(), 3, complex_data ( alloc_inst ) );
    complex_data_vector0->at ( 0 ) = *complex_data0_;
    for ( size_t i = 0; i < complex_data_vector0->size(); i++ ) {
        std::cout << complex_data_vector0->at ( i )  << std::endl;
    }
    std::cout << "--------------"  << std::endl;
    resize(*complex_data_vector1, 5, complex_data(alloc_inst));
    complex_data_vector0->at ( 4 ).id_ = 4;
    for ( size_t i = 0; i < complex_data_vector1->size(); i++ ) {
        std::cout << complex_data_vector1->at ( i )  << std::endl;
    }
    return 0;
}

<|endoftext|>


<commit_before><commit_msg>Related fdo#60338: do not call umask(3) in a MT program<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: npshell.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: mba $ $Date: 2004-09-02 14:01:05 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#define PLUGIN_NAME         "StarOffice Plugin"
#define PLUGIN_DESCRIPTION  "The StarOffice plugin handles all staroffice documents"

#ifdef UNIX

#define MOZ_X11

#include <gtk/gtk.h>
#include <X11/Xlib.h>

typedef struct _PluginInstance
{
    uint16 mode;
#ifdef MOZ_X11
    Window window;
    Display *display;
#endif
    uint32 x, y;
    uint32 width, height;
    NPMIMEType type;
    char *message;

    NPP instance;
    char *pluginsPageUrl;
    char *pluginsFileUrl;
    NPBool pluginsHidden;
#ifdef MOZ_X11
    Visual* visual;
    Colormap colormap;
#endif
    unsigned int depth;
    GtkWidget* dialogBox;

    NPBool exists;  /* Does the widget already exist? */
    int action;     /* What action should we take? (GET or REFRESH) */

} PluginInstance;

typedef struct _MimeTypeElement
{
    PluginInstance *pinst;
    struct _MimeTypeElement *next;
} MimeTypeElement;

#endif  //end of UNIX

#ifdef WNT

#include <windows.h>

typedef struct _PluginInstance
{
    NPWindow*            fWindow;
    uint16                fMode;

    HWND                fhWnd;
    WNDPROC                fDefaultWindowProc;
} PluginInstance;

#endif //end of WNT

/* Extern functions */
extern "C" NPMIMEType dupMimeType(NPMIMEType type);
<commit_msg>INTEGRATION: CWS nsplugin3 (1.3.24); FILE MERGED 2004/10/12 03:10:22 jmeng 1.3.24.1: add dynamic OpenOffice.org / StarOffice support<commit_after>/*************************************************************************
 *
 *  $RCSfile: npshell.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2004-11-26 16:00:51 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef UNIX

#define MOZ_X11

#include <gtk/gtk.h>
#include <X11/Xlib.h>

typedef struct _PluginInstance
{
    uint16 mode;
#ifdef MOZ_X11
    Window window;
    Display *display;
#endif
    uint32 x, y;
    uint32 width, height;
    NPMIMEType type;
    char *message;

    NPP instance;
    char *pluginsPageUrl;
    char *pluginsFileUrl;
    NPBool pluginsHidden;
#ifdef MOZ_X11
    Visual* visual;
    Colormap colormap;
#endif
    unsigned int depth;
    GtkWidget* dialogBox;

    NPBool exists;  /* Does the widget already exist? */
    int action;     /* What action should we take? (GET or REFRESH) */

} PluginInstance;

typedef struct _MimeTypeElement
{
    PluginInstance *pinst;
    struct _MimeTypeElement *next;
} MimeTypeElement;

#endif  //end of UNIX

#ifdef WNT

#include <windows.h>

typedef struct _PluginInstance
{
    NPWindow*            fWindow;
    uint16                fMode;

    HWND                fhWnd;
    WNDPROC                fDefaultWindowProc;
} PluginInstance;

#endif //end of WNT

/* Extern functions */
extern "C" NPMIMEType dupMimeType(NPMIMEType type);
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for json.c
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "BasicsC/json.h"
#include "BasicsC/string-buffer.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                    private macros
// -----------------------------------------------------------------------------

#define INIT_BUFFER  TRI_string_buffer_t* sb = TRI_CreateStringBuffer(TRI_UNKNOWN_MEM_ZONE);
#define FREE_BUFFER  TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, sb);
#define STRINGIFY    TRI_StringifyJson(sb, json);
#define STRING_VALUE sb->_buffer
#define FREE_JSON    TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CJsonSetup {
  CJsonSetup () {
    BOOST_TEST_MESSAGE("setup json");
  }

  ~CJsonSetup () {
    BOOST_TEST_MESSAGE("tear-down json");
  }
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CJsonTest, CJsonSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test null value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_null) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE);

  STRINGIFY
  BOOST_CHECK_EQUAL("null", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test true value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_true) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true);

  STRINGIFY
  BOOST_CHECK_EQUAL("true", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test false value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_false) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, false);

  STRINGIFY
  BOOST_CHECK_EQUAL("false", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value 0
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number0) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 0.0);

  STRINGIFY
  BOOST_CHECK_EQUAL("0", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (positive)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_positive1) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 1.0);

  STRINGIFY
  BOOST_CHECK_EQUAL("1", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (positive)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_positive2) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 46281);

  STRINGIFY
  BOOST_CHECK_EQUAL("46281", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (negative)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_negative1) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, -1.0);

  STRINGIFY
  BOOST_CHECK_EQUAL("-1", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (negative)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_negative2) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, -2342);

  STRINGIFY
  BOOST_CHECK_EQUAL("-2342", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value (empty)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string_empty) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string1) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "the quick brown fox");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"the quick brown fox\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string2) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "The Quick Brown Fox");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"The Quick Brown Fox\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value (escaped)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string_escaped) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "\"the quick \"fox\" jumped over the \\brown\\ dog '\n\\\" \\' \\\\ lazy");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"\\\"the quick \\\"fox\\\" jumped over the \\\\brown\\\\ dog '\\n\\\\\\\" \\\\' \\\\\\\\ lazy\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test empty json list
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_list_empty) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);

  STRINGIFY
  BOOST_CHECK_EQUAL("[]", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test empty json array
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_array_empty) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);

  STRINGIFY
  BOOST_CHECK_EQUAL("{}", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<commit_msg>some more tests<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for json.c
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "BasicsC/json.h"
#include "BasicsC/string-buffer.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                    private macros
// -----------------------------------------------------------------------------

#define INIT_BUFFER  TRI_string_buffer_t* sb = TRI_CreateStringBuffer(TRI_UNKNOWN_MEM_ZONE);
#define FREE_BUFFER  TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, sb);
#define STRINGIFY    TRI_StringifyJson(sb, json);
#define STRING_VALUE sb->_buffer
#define FREE_JSON    TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CJsonSetup {
  CJsonSetup () {
    BOOST_TEST_MESSAGE("setup json");
  }

  ~CJsonSetup () {
    BOOST_TEST_MESSAGE("tear-down json");
  }
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CJsonTest, CJsonSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test null value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_null) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE);

  STRINGIFY
  BOOST_CHECK_EQUAL("null", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test true value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_true) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true);

  STRINGIFY
  BOOST_CHECK_EQUAL("true", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test false value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_false) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, false);

  STRINGIFY
  BOOST_CHECK_EQUAL("false", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value 0
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number0) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 0.0);

  STRINGIFY
  BOOST_CHECK_EQUAL("0", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (positive)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_positive1) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 1.0);

  STRINGIFY
  BOOST_CHECK_EQUAL("1", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (positive)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_positive2) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 46281);

  STRINGIFY
  BOOST_CHECK_EQUAL("46281", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (negative)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_negative1) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, -1.0);

  STRINGIFY
  BOOST_CHECK_EQUAL("-1", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test number value (negative)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_number_negative2) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, -2342);

  STRINGIFY
  BOOST_CHECK_EQUAL("-2342", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value (empty)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string_empty) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string1) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "the quick brown fox");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"the quick brown fox\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string2) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "The Quick Brown Fox");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"The Quick Brown Fox\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value (escaped)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string_escaped) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "\"the quick \"fox\" jumped over the \\brown\\ dog '\n\\\" \\' \\\\ lazy");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"\\\"the quick \\\"fox\\\" jumped over the \\\\brown\\\\ dog '\\n\\\\\\\" \\\\' \\\\\\\\ lazy\"", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value (special chars)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string_utf8_1) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "코리아닷컴 메일알리미 서비스 중단안내 [안내] 개인정보취급방침 변경 안내 회사소개 | 광고안내 | 제휴안내 | 개인정보취급방침 | 청소년보호정책 | 스팸방지정책 | 사이버고객센터 | 약관안내 | 이메일 무단수집거부 | 서비스 전체보기");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"\\uCF54\\uB9AC\\uC544\\uB2F7\\uCEF4 \\uBA54\\uC77C\\uC54C\\uB9AC\\uBBF8 \\uC11C\\uBE44\\uC2A4 \\uC911\\uB2E8\\uC548\\uB0B4 [\\uC548\\uB0B4] \\uAC1C\\uC778\\uC815\\uBCF4\\uCDE8\\uAE09\\uBC29\\uCE68 \\uBCC0\\uACBD \\uC548\\uB0B4 \\uD68C\\uC0AC\\uC18C\\uAC1C | \\uAD11\\uACE0\\uC548\\uB0B4 | \\uC81C\\uD734\\uC548\\uB0B4 | \\uAC1C\\uC778\\uC815\\uBCF4\\uCDE8\\uAE09\\uBC29\\uCE68 | \\uCCAD\\uC18C\\uB144\\uBCF4\\uD638\\uC815\\uCC45 | \\uC2A4\\uD338\\uBC29\\uC9C0\\uC815\\uCC45 | \\uC0AC\\uC774\\uBC84\\uACE0\\uAC1D\\uC13C\\uD130 | \\uC57D\\uAD00\\uC548\\uB0B4 | \\uC774\\uBA54\\uC77C \\uBB34\\uB2E8\\uC218\\uC9D1\\uAC70\\uBD80 | \\uC11C\\uBE44\\uC2A4 \\uC804\\uCCB4\\uBCF4\\uAE30\"", STRING_VALUE);

  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test string value (special chars)
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_string_utf8_2) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "äöüßÄÖÜ€µ");

  STRINGIFY
  BOOST_CHECK_EQUAL("\"\\u00E4\\u00F6\\u00FC\\u00DF\\u00C4\\u00D6\\u00DC\\u20AC\\u00B5\"", STRING_VALUE);

  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test empty json list
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_list_empty) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);

  STRINGIFY
  BOOST_CHECK_EQUAL("[]", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test empty json list mixed
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_list_mixed) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);
  TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE));
  TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true));
  TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, false));
  TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, -8093));
  TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, 1.5));
  TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, json, TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, (char*) "the quick brown fox"));

  STRINGIFY
  BOOST_CHECK_EQUAL("[null,true,false,-8093,1.5,\"the quick brown fox\"]", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test empty json array
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_json_array_empty) {
  INIT_BUFFER

  TRI_json_t* json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);

  STRINGIFY
  BOOST_CHECK_EQUAL("{}", STRING_VALUE);
  FREE_JSON
  FREE_BUFFER
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <iostream>
#include "OmahaHighHandEvaluator.h"

using namespace pokerstove;
using namespace std;

TEST(OmahaHighHandEvaluator, Construct) {
  OmahaHighHandEvaluator eval;
  EXPECT_EQ(true, eval.usesSuits());
  EXPECT_EQ(5, eval.boardSize());
}

TEST(OmahaHighHandEvaluator, RankEval) {
  OmahaHighHandEvaluator oeval;
  CardSet hand("2c3c");
  CardSet board("2c3c4c");
  PokerEvaluation eval = oeval.evaluateRanks(hand, board);
  EXPECT_EQ(TWO_PAIR, eval.type());
  EXPECT_EQ(Rank("3"), eval.majorRank());
  EXPECT_EQ(Rank("2"), eval.minorRank());
}
<commit_msg>use omaha hand for omaha test<commit_after>#include <gtest/gtest.h>
#include <iostream>
#include "OmahaHighHandEvaluator.h"

using namespace pokerstove;
using namespace std;

TEST(OmahaHighHandEvaluator, Construct) {
  OmahaHighHandEvaluator eval;
  EXPECT_EQ(true, eval.usesSuits());
  EXPECT_EQ(5, eval.boardSize());
}

TEST(OmahaHighHandEvaluator, RankEval) {
  OmahaHighHandEvaluator oeval;
  CardSet hand("2c3cKhQd");
  CardSet board("2c3c4c");
  PokerEvaluation eval = oeval.evaluateRanks(hand, board);
  EXPECT_EQ(TWO_PAIR, eval.type());
  EXPECT_EQ(Rank("3"), eval.majorRank());
  EXPECT_EQ(Rank("2"), eval.minorRank());
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Chiyuan Zhang
 * Copyright (C) 2012 Chiyuan Zhang
 */

#include <algorithm>

#include <shogun/lib/Time.h>
#include <shogun/mathematics/Math.h>
#include <shogun/multiclass/ShareBoost.h>
#include <shogun/multiclass/ShareBoostOptimizer.h>
#include <shogun/features/DenseSubsetFeatures.h>
#include <shogun/labels/RegressionLabels.h>

using namespace shogun;

CShareBoost::CShareBoost()
	:CLinearMulticlassMachine(), m_nonzero_feas(0)
{
	init_sb_params();
}

CShareBoost::CShareBoost(CDenseFeatures<float64_t> *features, CMulticlassLabels *labs, int32_t num_nonzero_feas)
	:CLinearMulticlassMachine(new CMulticlassOneVsRestStrategy(), features, NULL, labs), m_nonzero_feas(num_nonzero_feas)
{
	init_sb_params();
}

void CShareBoost::init_sb_params()
{
	SG_ADD(&m_nonzero_feas, "m_nonzero_feas", "Number of non-zero features", MS_NOT_AVAILABLE);
}

SGVector<int32_t> CShareBoost::get_activeset()
{
	return m_activeset.clone();
}

bool CShareBoost::train_machine(CFeatures* data)
{
	if (data)
		set_features(data);

	if (m_features == NULL)
		SG_ERROR("No features given for training\n")
	if (m_labels == NULL)
		SG_ERROR("No labels given for training\n")

	if (m_nonzero_feas <= 0)
		SG_ERROR("Set a valid (> 0) number of non-zero features to seek before training\n")
	if (m_nonzero_feas >= dynamic_cast<CDenseFeatures<float64_t>*>(m_features)->get_num_features())
		SG_ERROR("It doesn't make sense to use ShareBoost with num non-zero features >= num features in the data\n")

	m_fea = dynamic_cast<CDenseFeatures<float64_t> *>(m_features)->get_feature_matrix();
	m_rho = SGMatrix<float64_t>(m_multiclass_strategy->get_num_classes(), m_fea.num_cols);
	m_rho_norm = SGVector<float64_t>(m_fea.num_cols);
	m_pred = SGMatrix<float64_t>(m_fea.num_cols, m_multiclass_strategy->get_num_classes());
	m_pred.zero();

	m_activeset = SGVector<int32_t>(m_fea.num_rows);
	m_activeset.vlen = 0;

	m_machines->reset_array();
	for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
		m_machines->push_back(new CLinearMachine());

	CTime *timer = new CTime();

	float64_t t_compute_pred = 0; // t of 1st round is 0, since no pred to compute
	for (int32_t t=0; t < m_nonzero_feas; ++t)
	{
		timer->start();
		compute_rho();
		int32_t i_fea = choose_feature();
		m_activeset.vector[m_activeset.vlen] = i_fea;
		m_activeset.vlen += 1;
		float64_t t_choose_feature = timer->cur_time_diff();
		timer->start();
		optimize_coefficients();
		float64_t t_optimize = timer->cur_time_diff();

		SG_SPRINT(" SB[round %03d]: (%8.4f + %8.4f) sec.\n", t,
				t_compute_pred + t_choose_feature, t_optimize);

		timer->start();
		compute_pred();
		t_compute_pred = timer->cur_time_diff();
	}

	SG_UNREF(timer);

	// release memory
	m_fea = SGMatrix<float64_t>();
	m_rho = SGMatrix<float64_t>();
	m_rho_norm = SGVector<float64_t>();
	m_pred = SGMatrix<float64_t>();

	return true;
}

void CShareBoost::compute_pred()
{
	CDenseFeatures<float64_t> *fea = dynamic_cast<CDenseFeatures<float64_t> *>(m_features);
	CDenseSubsetFeatures<float64_t> *subset_fea = new CDenseSubsetFeatures<float64_t>(fea, m_activeset);
	SG_REF(subset_fea);
	for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
	{
		CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
		CRegressionLabels *lab = machine->apply_regression(subset_fea);
		SGVector<float64_t> lab_raw = lab->get_labels();
		std::copy(lab_raw.vector, lab_raw.vector + lab_raw.vlen, m_pred.get_column_vector(i));
		SG_UNREF(machine);
		SG_UNREF(lab);
	}
	SG_UNREF(subset_fea);
}

void CShareBoost::compute_pred(const float64_t *W)
{
	int32_t w_len = m_activeset.vlen;

	for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
	{
		CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
		SGVector<float64_t> w(w_len);
		std::copy(W + i*w_len, W + (i+1)*w_len, w.vector);
		machine->set_w(w);
		SG_UNREF(machine);
	}
	compute_pred();
}

void CShareBoost::compute_rho()
{
	CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
	for (int32_t i=0; i < m_rho.num_rows; ++i)
	{ // i loop classes
		for (int32_t j=0; j < m_rho.num_cols; ++j)
		{ // j loop samples
			int32_t label = lab->get_int_label(j);

			m_rho(i,j) = CMath::exp((label == i) - m_pred(j, label) + m_pred(j, i));
		}
	}

	// normalize
	for (int32_t j=0; j < m_rho.num_cols; ++j)
	{
		m_rho_norm[j] = 0;
		for (int32_t i=0; i < m_rho.num_rows; ++i)
			m_rho_norm[j] += m_rho(i,j);
	}
}

int32_t CShareBoost::choose_feature()
{
	SGVector<float64_t> l1norm(m_fea.num_rows);
	for (int32_t j=0; j < m_fea.num_rows; ++j)
	{
		if (std::find(&m_activeset[0], &m_activeset[m_activeset.vlen], j) !=
				&m_activeset[m_activeset.vlen])
		{
			l1norm[j] = 0;
		}
		else
		{
			l1norm[j] = 0;
			CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
			for (int32_t k=0; k < m_multiclass_strategy->get_num_classes(); ++k)
			{
				float64_t abssum = 0;
				for (int32_t ii=0; ii < m_fea.num_cols; ++ii)
				{
					abssum += m_fea(j, ii)*(m_rho(k, ii)/m_rho_norm[ii] -
							(j == lab->get_int_label(ii)));
				}
				l1norm[j] += CMath::abs(abssum);
			}
			l1norm[j] /= m_fea.num_cols;
		}
	}

	return SGVector<float64_t>::arg_max(l1norm.vector, 1, l1norm.vlen);
}

void CShareBoost::optimize_coefficients()
{
	ShareBoostOptimizer optimizer(this, false);
	optimizer.optimize();
}

void CShareBoost::set_features(CFeatures *f)
{
	CDenseFeatures<float64_t> *fea = dynamic_cast<CDenseFeatures<float64_t> *>(f);
	if (fea == NULL)
		SG_ERROR("Require DenseFeatures<float64_t>\n")
	CLinearMulticlassMachine::set_features(fea);
}
<commit_msg>shareboost: don't print progress if not in debug mode<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Chiyuan Zhang
 * Copyright (C) 2012 Chiyuan Zhang
 */

#include <algorithm>

#include <shogun/lib/Time.h>
#include <shogun/mathematics/Math.h>
#include <shogun/multiclass/ShareBoost.h>
#include <shogun/multiclass/ShareBoostOptimizer.h>
#include <shogun/features/DenseSubsetFeatures.h>
#include <shogun/labels/RegressionLabels.h>

using namespace shogun;

CShareBoost::CShareBoost()
	:CLinearMulticlassMachine(), m_nonzero_feas(0)
{
	init_sb_params();
}

CShareBoost::CShareBoost(CDenseFeatures<float64_t> *features, CMulticlassLabels *labs, int32_t num_nonzero_feas)
	:CLinearMulticlassMachine(new CMulticlassOneVsRestStrategy(), features, NULL, labs), m_nonzero_feas(num_nonzero_feas)
{
	init_sb_params();
}

void CShareBoost::init_sb_params()
{
	SG_ADD(&m_nonzero_feas, "m_nonzero_feas", "Number of non-zero features", MS_NOT_AVAILABLE);
}

SGVector<int32_t> CShareBoost::get_activeset()
{
	return m_activeset.clone();
}

bool CShareBoost::train_machine(CFeatures* data)
{
	if (data)
		set_features(data);

	if (m_features == NULL)
		SG_ERROR("No features given for training\n")
	if (m_labels == NULL)
		SG_ERROR("No labels given for training\n")

	if (m_nonzero_feas <= 0)
		SG_ERROR("Set a valid (> 0) number of non-zero features to seek before training\n")
	if (m_nonzero_feas >= dynamic_cast<CDenseFeatures<float64_t>*>(m_features)->get_num_features())
		SG_ERROR("It doesn't make sense to use ShareBoost with num non-zero features >= num features in the data\n")

	m_fea = dynamic_cast<CDenseFeatures<float64_t> *>(m_features)->get_feature_matrix();
	m_rho = SGMatrix<float64_t>(m_multiclass_strategy->get_num_classes(), m_fea.num_cols);
	m_rho_norm = SGVector<float64_t>(m_fea.num_cols);
	m_pred = SGMatrix<float64_t>(m_fea.num_cols, m_multiclass_strategy->get_num_classes());
	m_pred.zero();

	m_activeset = SGVector<int32_t>(m_fea.num_rows);
	m_activeset.vlen = 0;

	m_machines->reset_array();
	for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
		m_machines->push_back(new CLinearMachine());

	CTime *timer = new CTime();

	float64_t t_compute_pred = 0; // t of 1st round is 0, since no pred to compute
	for (int32_t t=0; t < m_nonzero_feas; ++t)
	{
		timer->start();
		compute_rho();
		int32_t i_fea = choose_feature();
		m_activeset.vector[m_activeset.vlen] = i_fea;
		m_activeset.vlen += 1;
		float64_t t_choose_feature = timer->cur_time_diff();
		timer->start();
		optimize_coefficients();
		float64_t t_optimize = timer->cur_time_diff();

		SG_SDEBUG(" SB[round %03d]: (%8.4f + %8.4f) sec.\n", t,
				t_compute_pred + t_choose_feature, t_optimize);

		timer->start();
		compute_pred();
		t_compute_pred = timer->cur_time_diff();
	}

	SG_UNREF(timer);

	// release memory
	m_fea = SGMatrix<float64_t>();
	m_rho = SGMatrix<float64_t>();
	m_rho_norm = SGVector<float64_t>();
	m_pred = SGMatrix<float64_t>();

	return true;
}

void CShareBoost::compute_pred()
{
	CDenseFeatures<float64_t> *fea = dynamic_cast<CDenseFeatures<float64_t> *>(m_features);
	CDenseSubsetFeatures<float64_t> *subset_fea = new CDenseSubsetFeatures<float64_t>(fea, m_activeset);
	SG_REF(subset_fea);
	for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
	{
		CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
		CRegressionLabels *lab = machine->apply_regression(subset_fea);
		SGVector<float64_t> lab_raw = lab->get_labels();
		std::copy(lab_raw.vector, lab_raw.vector + lab_raw.vlen, m_pred.get_column_vector(i));
		SG_UNREF(machine);
		SG_UNREF(lab);
	}
	SG_UNREF(subset_fea);
}

void CShareBoost::compute_pred(const float64_t *W)
{
	int32_t w_len = m_activeset.vlen;

	for (int32_t i=0; i < m_multiclass_strategy->get_num_classes(); ++i)
	{
		CLinearMachine *machine = dynamic_cast<CLinearMachine *>(m_machines->get_element(i));
		SGVector<float64_t> w(w_len);
		std::copy(W + i*w_len, W + (i+1)*w_len, w.vector);
		machine->set_w(w);
		SG_UNREF(machine);
	}
	compute_pred();
}

void CShareBoost::compute_rho()
{
	CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
	for (int32_t i=0; i < m_rho.num_rows; ++i)
	{ // i loop classes
		for (int32_t j=0; j < m_rho.num_cols; ++j)
		{ // j loop samples
			int32_t label = lab->get_int_label(j);

			m_rho(i,j) = CMath::exp((label == i) - m_pred(j, label) + m_pred(j, i));
		}
	}

	// normalize
	for (int32_t j=0; j < m_rho.num_cols; ++j)
	{
		m_rho_norm[j] = 0;
		for (int32_t i=0; i < m_rho.num_rows; ++i)
			m_rho_norm[j] += m_rho(i,j);
	}
}

int32_t CShareBoost::choose_feature()
{
	SGVector<float64_t> l1norm(m_fea.num_rows);
	for (int32_t j=0; j < m_fea.num_rows; ++j)
	{
		if (std::find(&m_activeset[0], &m_activeset[m_activeset.vlen], j) !=
				&m_activeset[m_activeset.vlen])
		{
			l1norm[j] = 0;
		}
		else
		{
			l1norm[j] = 0;
			CMulticlassLabels *lab = dynamic_cast<CMulticlassLabels *>(m_labels);
			for (int32_t k=0; k < m_multiclass_strategy->get_num_classes(); ++k)
			{
				float64_t abssum = 0;
				for (int32_t ii=0; ii < m_fea.num_cols; ++ii)
				{
					abssum += m_fea(j, ii)*(m_rho(k, ii)/m_rho_norm[ii] -
							(j == lab->get_int_label(ii)));
				}
				l1norm[j] += CMath::abs(abssum);
			}
			l1norm[j] /= m_fea.num_cols;
		}
	}

	return SGVector<float64_t>::arg_max(l1norm.vector, 1, l1norm.vlen);
}

void CShareBoost::optimize_coefficients()
{
	ShareBoostOptimizer optimizer(this, false);
	optimizer.optimize();
}

void CShareBoost::set_features(CFeatures *f)
{
	CDenseFeatures<float64_t> *fea = dynamic_cast<CDenseFeatures<float64_t> *>(f);
	if (fea == NULL)
		SG_ERROR("Require DenseFeatures<float64_t>\n")
	CLinearMulticlassMachine::set_features(fea);
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "core/Scaled.h"

TEST(ScaledTest, CanRetrieveInteger)
{
	Scaled s1(5);

	EXPECT_EQ(5, (int)s1);
}

TEST(ScaledTest, FloatCast)
{
	Scaled s1(1.5);

	EXPECT_FLOAT_EQ(1.5, (float)s1);
	EXPECT_FLOAT_EQ(1.5, (double)s1);
}

TEST(ScaledTest, ComparisonOperators)
{
	Scaled s1(5);
	Scaled s2(5);
	Scaled s3(3);
	Scaled s4(8);
	Scaled s5(0);

	EXPECT_TRUE(s1 == s2);
	EXPECT_FALSE(s1 == s3);

	EXPECT_FALSE(s1 != s2);
	EXPECT_TRUE(s1 != s4);

	EXPECT_FALSE(s1 < s2);
	EXPECT_FALSE(s1 < s3);
	EXPECT_TRUE(s1 < s4);

	EXPECT_FALSE(s1 > s2);
	EXPECT_TRUE(s1 > s3);
	EXPECT_FALSE(s1 > s4);

	EXPECT_TRUE(s1 <= s2);
	EXPECT_FALSE(s1 <= s3);
	EXPECT_TRUE(s1 <= s4);

	EXPECT_TRUE(s1 >= s2);
	EXPECT_TRUE(s1 >= s3);
	EXPECT_FALSE(s1 >= s4);

	EXPECT_FALSE(!s1);
	EXPECT_TRUE(!s5);
}

TEST(ScaledTest, BasicAddition)
{
	Scaled s1(2);
	Scaled s2(4);

	Scaled s3 = s1 + s2;

	EXPECT_EQ(6, (int)s3);
}

TEST(ScaledTest, BasicSubtraction)
{
	Scaled s1(6);
	Scaled s2(4);

	Scaled s3 = s1 - s2;

	EXPECT_EQ(2, (int)s3);
}

TEST(ScaledTest, AddInt)
{
	Scaled s1(2);

	Scaled s2 = s1 + 4;

	EXPECT_EQ(6, (int)s2);
}

TEST(ScaledTest, SubtractInt)
{
	Scaled s1(6);

	Scaled s2 = s1 - 4;

	EXPECT_EQ(2, (int)s2);
}

TEST(ScaledTest, BasicMultiplication)
{
	Scaled s1(2);
	Scaled s2(4);

	Scaled s3 = s1 * s2;

	EXPECT_EQ(8, (int)s3);
}

TEST(ScaledTest, BasicDivision)
{
	Scaled s1(6);
	Scaled s2(3);

	Scaled s3 = s1 / s2;

	EXPECT_EQ(2, (int)s3);
}

TEST(ScaledTest, MultiplyInt)
{
	Scaled s1(2);

	Scaled s2 = s1 * 4;

	EXPECT_EQ(8, (int)s2);
}

TEST(ScaledTest, DivideInt)
{
	Scaled s1(6);

	Scaled s2 = s1 / 3;

	EXPECT_EQ(2, (int)s2);
}

<commit_msg>Tests for int and double/float comparisons<commit_after>#include "gtest/gtest.h"
#include "core/Scaled.h"

TEST(ScaledTest, IntCast)
{
	Scaled s1(5);

	EXPECT_EQ(5, (int)s1);
}

TEST(ScaledTest, FloatCast)
{
	Scaled s1(1.5);

	EXPECT_FLOAT_EQ(1.5, (float)s1);
	EXPECT_FLOAT_EQ(1.5, (double)s1);
}

TEST(ScaledTest, ScaledComparisons)
{
	Scaled s1(5);
	Scaled s2(5);
	Scaled s3(3);
	Scaled s4(8);
	Scaled s5(0);

	EXPECT_TRUE(s1 == s2);
	EXPECT_FALSE(s1 == s3);

	EXPECT_FALSE(s1 != s2);
	EXPECT_TRUE(s1 != s4);

	EXPECT_FALSE(s1 < s2);
	EXPECT_FALSE(s1 < s3);
	EXPECT_TRUE(s1 < s4);

	EXPECT_FALSE(s1 > s2);
	EXPECT_TRUE(s1 > s3);
	EXPECT_FALSE(s1 > s4);

	EXPECT_TRUE(s1 <= s2);
	EXPECT_FALSE(s1 <= s3);
	EXPECT_TRUE(s1 <= s4);

	EXPECT_TRUE(s1 >= s2);
	EXPECT_TRUE(s1 >= s3);
	EXPECT_FALSE(s1 >= s4);

	EXPECT_FALSE(!s1);
	EXPECT_TRUE(!s5);
}

TEST(ScaledTest, IntComparisons)
{
	Scaled s1(5);
	Scaled s2(5);
	Scaled s3(3);
	Scaled s4(8);
	Scaled s5(0);

	EXPECT_TRUE(s1 == 5);
	EXPECT_FALSE(s1 == 4);

	EXPECT_FALSE(s1 != 5);
	EXPECT_TRUE(s1 != 4);

	EXPECT_FALSE(s1 < 5);
	EXPECT_FALSE(s1 < 3);
	EXPECT_TRUE(s1 < 8);

	EXPECT_FALSE(s1 > 5);
	EXPECT_TRUE(s1 > 3);
	EXPECT_FALSE(s1 > 8);

	EXPECT_TRUE(s1 <= 5);
	EXPECT_FALSE(s1 <= 3);
	EXPECT_TRUE(s1 <= 8);

	EXPECT_TRUE(s1 >= 5);
	EXPECT_TRUE(s1 >= 3);
	EXPECT_FALSE(s1 >= 8);
}

TEST(ScaledTest, DoubleComparisons)
{
	Scaled s1(5.6);
	Scaled s2(5.6);
	Scaled s3(3.2);
	Scaled s4(8.78);
	Scaled s5(0.2);

	EXPECT_TRUE(s1 == 5.6);
	EXPECT_FALSE(s1 == 5.5);

	EXPECT_FALSE(s1 != 5.6);
	EXPECT_TRUE(s1 != 5.5);

	EXPECT_FALSE(s1 < 5.6);
	EXPECT_FALSE(s1 < 3.2);
	EXPECT_TRUE(s1 < 8.78);

	EXPECT_FALSE(s1 > 5.6);
	EXPECT_TRUE(s1 > 3.2);
	EXPECT_FALSE(s1 > 8.78);

	EXPECT_TRUE(s1 <= 5.6);
	EXPECT_FALSE(s1 <= 3.2);
	EXPECT_TRUE(s1 <= 8.78);

	EXPECT_TRUE(s1 >= 5.6);
	EXPECT_TRUE(s1 >= 3.2);
	EXPECT_FALSE(s1 >= 8.78);
}

TEST(ScaledTest, BasicAddition)
{
	Scaled s1(2);
	Scaled s2(4);

	Scaled s3 = s1 + s2;

	EXPECT_EQ(6, (int)s3);
}

TEST(ScaledTest, BasicSubtraction)
{
	Scaled s1(6);
	Scaled s2(4);

	Scaled s3 = s1 - s2;

	EXPECT_EQ(2, (int)s3);
}

TEST(ScaledTest, AddInt)
{
	Scaled s1(2);

	Scaled s2 = s1 + 4;

	EXPECT_EQ(6, (int)s2);
}

TEST(ScaledTest, SubtractInt)
{
	Scaled s1(6);

	Scaled s2 = s1 - 4;

	EXPECT_EQ(2, (int)s2);
}

TEST(ScaledTest, BasicMultiplication)
{
	Scaled s1(2);
	Scaled s2(4);

	Scaled s3 = s1 * s2;

	EXPECT_EQ(8, (int)s3);
}

TEST(ScaledTest, BasicDivision)
{
	Scaled s1(6);
	Scaled s2(3);

	Scaled s3 = s1 / s2;

	EXPECT_EQ(2, (int)s3);
}

TEST(ScaledTest, MultiplyInt)
{
	Scaled s1(2);

	Scaled s2 = s1 * 4;

	EXPECT_EQ(8, (int)s2);
}

TEST(ScaledTest, DivideInt)
{
	Scaled s1(6);

	Scaled s2 = s1 / 3;

	EXPECT_EQ(2, (int)s2);
}

<|endoftext|>