//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER
#define BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER

#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <vector>
#include <iostream>
#include <cstdio>
#include <new>
#include <utility>
#include <iterator>
#include <set>
#include <string>
#include "get_process_id_name.hpp"

namespace boost { namespace interprocess { namespace test {

namespace {
   const wchar_t *get_prefix(wchar_t)
   {  return L"prefix_name_"; }

   const char *get_prefix(char)
   {  return "prefix_name_"; }
}

//This test allocates until there is no more memory
//and after that deallocates all in the same order
template<class ManagedMemory>
bool test_names_and_types(ManagedMemory &m)
{
   typedef typename ManagedMemory::char_type char_type;
   typedef std::char_traits<char_type> char_traits_type;
   std::vector<char*> buffers;
   const int BufferLen = 100;
   char_type name[BufferLen];

   basic_bufferstream<char_type> formatter(name, BufferLen);

   for(int i = 0; true; ++i){
      formatter.seekp(0);
      formatter << get_prefix(char_type()) << i << std::ends;

      char *ptr = m.template construct<char>(name, std::nothrow)(i);

      if(!ptr)
         break;

      std::size_t namelen = char_traits_type::length(m.get_instance_name(ptr));
      if(namelen != char_traits_type::length(name)){
         return 1;
      }

      if(char_traits_type::compare(m.get_instance_name(ptr), name, namelen) != 0){
         return 1;
      }

      if(m.template find<char>(name).first == 0)
         return false;

      if(m.get_instance_type(ptr) != named_type)
         return false;

      buffers.push_back(ptr);
   }

   if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
      return false;

   for(int j = 0, max = (int)buffers.size()
      ;j < max
      ;++j){
      m.destroy_ptr(buffers[j]);
   }

   if(m.get_num_named_objects() != 0 || !m.check_sanity())
      return false;
   m.shrink_to_fit_indexes();
   if(!m.all_memory_deallocated())
      return false;
   return true;
}


//This test allocates until there is no more memory
//and after that deallocates all in the same order
template<class ManagedMemory>
bool test_named_iterators(ManagedMemory &m)
{
   typedef typename ManagedMemory::char_type char_type;
   typedef std::char_traits<char_type> char_traits_type;
   std::vector<char*> buffers;
   const int BufferLen = 100;
   char_type name[BufferLen];
   typedef std::basic_string<char_type> string_type;
   std::set<string_type> names;

   basic_bufferstream<char_type> formatter(name, BufferLen);

   string_type aux_str;

   for(int i = 0; true; ++i){
      formatter.seekp(0);
      formatter << get_prefix(char_type()) << i << std::ends;
      char *ptr = m.template construct<char>(name, std::nothrow)(i);
      if(!ptr)
         break;
      aux_str = name;
      names.insert(aux_str);
      buffers.push_back(ptr);
   }

   if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
      return false;

   typedef typename ManagedMemory::const_named_iterator const_named_iterator;
   const_named_iterator named_beg = m.named_begin();
   const_named_iterator named_end = m.named_end();

   if(std::distance(named_beg, named_end) != (int)buffers.size()){
      return 1;
   }

   for(; named_beg != named_end; ++named_beg){
      const char_type *name = named_beg->name();
      aux_str = name;
      if(names.find(aux_str) == names.end()){
         return 1;
      }

      if(aux_str.size() != named_beg->name_length()){
         return 1;
      }

      const void *found_value = m.template find<char>(name).first;

      if(found_value == 0)
         return false;
      if(found_value != named_beg->value())
         return false;
   }

   for(int j = 0, max = (int)buffers.size()
      ;j < max
      ;++j){
      m.destroy_ptr(buffers[j]);
   }

   if(m.get_num_named_objects() != 0 || !m.check_sanity())
      return false;
   m.shrink_to_fit_indexes();
   if(!m.all_memory_deallocated())
      return false;
   return true;
}

//This test allocates until there is no more memory
//and after that deallocates all in the same order
template<class ManagedMemory>
bool test_shrink_to_fit(ManagedMemory &m)
{
   typedef typename ManagedMemory::char_type char_type;
   typedef std::char_traits<char_type> char_traits_type;
   std::vector<char*> buffers;
   const int BufferLen = 100;
   char_type name[BufferLen];

   basic_bufferstream<char_type> formatter(name, BufferLen);

   std::size_t free_memory_before = m.get_free_memory();

   for(int i = 0; true; ++i){
      formatter.seekp(0);
      formatter << get_prefix(char_type()) << i << std::ends;

      char *ptr = m.template construct<char>(name, std::nothrow)(i);

      if(!ptr)
         break;
      buffers.push_back(ptr);
   }

   for(int j = 0, max = (int)buffers.size()
      ;j < max
      ;++j){
      m.destroy_ptr(buffers[j]);
   }

   std::size_t free_memory_after = m.get_free_memory();

   if(free_memory_before != free_memory_after){
      m.shrink_to_fit_indexes();
      if(free_memory_before != free_memory_after)
         return false;
   }
   return true;
}

//This test allocates until there is no more memory
//and after that deallocates all in the same order
template<class ManagedMemory>
bool test_direct_named_allocation_destruction(ManagedMemory &m)
{
   typedef typename ManagedMemory::char_type char_type;
   typedef std::char_traits<char_type> char_traits_type;
   std::vector<char*> buffers;
   const int BufferLen = 100;
   char_type name[BufferLen];

   basic_bufferstream<char_type> formatter(name, BufferLen);

   for(int i = 0; true; ++i){
      formatter.seekp(0);
      formatter << get_prefix(char_type()) << i << std::ends;
      char *ptr = m.template construct<char>(name, std::nothrow)(i);
      if(!ptr)
         break;
      if(m.template find<char>(name).first == 0)
         return false;
      buffers.push_back(ptr);
   }

   if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
      return false;

   for(int j = 0, max = (int)buffers.size()
      ;j < max
      ;++j){
      m.destroy_ptr(buffers[j]);
   }

   if(m.get_num_named_objects() != 0 || !m.check_sanity())
      return false;
   m.shrink_to_fit_indexes();
   if(!m.all_memory_deallocated())
      return false;
   return true;
}

//This test allocates until there is no more memory
//and after that deallocates all in the inverse order
template<class ManagedMemory>
bool test_named_allocation_inverse_destruction(ManagedMemory &m)
{
   typedef typename ManagedMemory::char_type char_type;
   typedef std::char_traits<char_type> char_traits_type;

   std::vector<char*> buffers;
   const int BufferLen = 100;
   char_type name[BufferLen];

   basic_bufferstream<char_type> formatter(name, BufferLen);

   for(int i = 0; true; ++i){
      formatter.seekp(0);
      formatter << get_prefix(char_type()) << i << std::ends;
      char *ptr = m.template construct<char>(name, std::nothrow)(i);
      if(!ptr)
         break;
      buffers.push_back(ptr);
   }

   if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
      return false;

   for(int j = (int)buffers.size()
      ;j--
      ;){
      m.destroy_ptr(buffers[j]);
   }

   if(m.get_num_named_objects() != 0 || !m.check_sanity())
      return false;
   m.shrink_to_fit_indexes();
   if(!m.all_memory_deallocated())
      return false;
   return true;
}

//This test allocates until there is no more memory
//and after that deallocates all following a pattern
template<class ManagedMemory>
bool test_named_allocation_mixed_destruction(ManagedMemory &m)
{
   typedef typename ManagedMemory::char_type char_type;
   typedef std::char_traits<char_type> char_traits_type;

   std::vector<char*> buffers;
   const int BufferLen = 100;
   char_type name[BufferLen];

   basic_bufferstream<char_type> formatter(name, BufferLen);

   for(int i = 0; true; ++i){
      formatter.seekp(0);
      formatter << get_prefix(char_type()) << i << std::ends;
      char *ptr = m.template construct<char>(name, std::nothrow)(i);
      if(!ptr)
         break;
      buffers.push_back(ptr);
   }

   if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
      return false;

   for(int j = 0, max = (int)buffers.size()
      ;j < max
      ;++j){
      int pos = (j%4)*((int)buffers.size())/4;
      m.destroy_ptr(buffers[pos]);
      buffers.erase(buffers.begin()+pos);
   }

   if(m.get_num_named_objects() != 0 || !m.check_sanity())
      return false;
   m.shrink_to_fit_indexes();
   if(!m.all_memory_deallocated())
      return false;
   return true;
}

//This test allocates until there is no more memory
//and after that deallocates all in the same order
template<class ManagedMemory>
bool test_inverse_named_allocation_destruction(ManagedMemory &m)
{
   typedef typename ManagedMemory::char_type char_type;
   typedef std::char_traits<char_type> char_traits_type;

   std::vector<char*> buffers;
   const int BufferLen = 100;
   char_type name[BufferLen];

   basic_bufferstream<char_type> formatter(name, BufferLen);

   for(unsigned int i = 0; true; ++i){
      formatter.seekp(0);
      formatter << get_prefix(char_type()) << i << std::ends;
      char *ptr = m.template construct<char>(name, std::nothrow)(i);
      if(!ptr)
         break;
      buffers.push_back(ptr);
   }

   if(m.get_num_named_objects() != buffers.size() || !m.check_sanity())
      return false;

   for(unsigned int j = 0, max = (unsigned int)buffers.size()
      ;j < max
      ;++j){
      m.destroy_ptr(buffers[j]);
   }

   if(m.get_num_named_objects() != 0 || !m.check_sanity())
      return false;
   m.shrink_to_fit_indexes();
   if(!m.all_memory_deallocated())
      return false;
   return true;
}

///This function calls all tests
template<class ManagedMemory>
bool test_all_named_allocation(ManagedMemory &m)
{
   std::cout << "Starting test_names_and_types. Class: "
             << typeid(m).name() << std::endl;

   if(!test_names_and_types(m)){
      std::cout << "test_names_and_types failed. Class: "
                << typeid(m).name() << std::endl;
      return false;
   }

   std::cout << "Starting test_direct_named_allocation_destruction. Class: "
             << typeid(m).name() << std::endl;

   if(!test_direct_named_allocation_destruction(m)){
      std::cout << "test_direct_named_allocation_destruction failed. Class: "
                << typeid(m).name() << std::endl;
      return false;
   }

   std::cout << "Starting test_named_allocation_inverse_destruction. Class: "
             << typeid(m).name() << std::endl;

   if(!test_named_allocation_inverse_destruction(m)){
      std::cout << "test_named_allocation_inverse_destruction failed. Class: "
                << typeid(m).name() << std::endl;
      return false;
   }

   std::cout << "Starting test_named_allocation_mixed_destruction. Class: "
             << typeid(m).name() << std::endl;

   if(!test_named_allocation_mixed_destruction(m)){
      std::cout << "test_named_allocation_mixed_destruction failed. Class: "
                << typeid(m).name() << std::endl;
      return false;
   }

   std::cout << "Starting test_inverse_named_allocation_destruction. Class: "
             << typeid(m).name() << std::endl;

   if(!test_inverse_named_allocation_destruction(m)){
      std::cout << "test_inverse_named_allocation_destruction failed. Class: "
                << typeid(m).name() << std::endl;
      return false;
   }

   if(!test_named_iterators(m)){
      std::cout << "test_named_iterators failed. Class: "
                << typeid(m).name() << std::endl;
      return false;
   }

   return true;
}

//This function calls all tests
template<template <class IndexConfig> class Index>
bool test_named_allocation()
{
   using namespace boost::interprocess;

   const int memsize = 163840;
   const char *const shMemName = test::get_process_id_name();
   try
   {
      //A shared memory with rbtree best fit algorithm
      typedef basic_managed_shared_memory
         <char
         ,rbtree_best_fit<mutex_family>
         ,Index
         > my_managed_shared_memory;

      //Create shared memory
      shared_memory_object::remove(shMemName);
      my_managed_shared_memory segment(create_only, shMemName, memsize);

      //Now take the segment manager and launch memory test
      if(!test::test_all_named_allocation(*segment.get_segment_manager())){
         return false;
      }
   }
   catch(...){
      shared_memory_object::remove(shMemName);
      throw;
   }
   shared_memory_object::remove(shMemName);

   //Now test it with wchar_t
   try
   {
      //A shared memory with simple sequential fit algorithm
      typedef basic_managed_shared_memory
         <wchar_t
         ,rbtree_best_fit<mutex_family>
         ,Index
         > my_managed_shared_memory;

      //Create shared memory
      shared_memory_object::remove(shMemName);
      my_managed_shared_memory segment(create_only, shMemName, memsize);

      //Now take the segment manager and launch memory test
      if(!test::test_all_named_allocation(*segment.get_segment_manager())){
         return false;
      }
   }
   catch(...){
      shared_memory_object::remove(shMemName);
      throw;
   }
   shared_memory_object::remove(shMemName);

   return true;
}

}}}   //namespace boost { namespace interprocess { namespace test {

#include <boost/interprocess/detail/config_end.hpp>

#endif   //BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER

