text: // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
  
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the "Software"),
  // to deal in the Software without restriction, including without limitation
  // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  // and/or sell copies of the Software, and to permit persons to whom the
  // Software is furnished to do so, subject to the following conditions:
  
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
  // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  // OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  #include "test.hpp"
  #include <luabind/luabind.hpp>
  #include <luabind/detail/debug.hpp>
  #include <luabind/operator.hpp>
  
  #include <utility>
  
  using namespace luabind;
  
  
  struct test_param : counted_type<test_param>, wrap_base
  {
    luabind::object obj;
    luabind::object obj2;
  
    bool operator==(test_param const& rhs) const
    { return obj == rhs.obj && obj2 == rhs.obj2; }
  };
  
  COUNTER_GUARD(test_param);
  
  static test_param * s_ptr = NULL;
  
  void store_ptr(test_param * ptr) {
    s_ptr = ptr;
  }
  
  test_param * get_ptr() {
    return s_ptr;
  }
  
  void test_main(lua_State* L)
  {
    assert(boost::is_polymorphic<test_param>());
      
    using namespace luabind;
  
    module(L)
    [
      class_<test_param>("test_param")
        .def(constructor<>())
        .def_readwrite("obj", &test_param::obj)
        .def_readonly("obj2", &test_param::obj2)
        .def(const_self == const_self)
      ,    
      def("store_ptr", &store_ptr),
      def("get_ptr", &get_ptr)
    ];
  
    test_param temp_object;
    
    // This tests copies temp_object using assignment by-value
    //   this does NOT! preserve raw-equality and that is why indexing
    //   should fail
    globals(L)["temp"] = temp_object;
    {
      object tab = newtable(L);
      tab[temp_object] = 1;
      TEST_CHECK( tab[temp_object] != 1 );
      TEST_CHECK( tab[globals(L)["temp"]] != 1 );
    }
    
    // Assignment by pointer causes the original object to be used, this is
    //   why raw equlity works in this case!
    globals(L)["temp"] = &temp_object;
    {
      object tab = newtable(L);
      tab[&temp_object] = 1;
      TEST_CHECK( tab[&temp_object] == 1 );
      TEST_CHECK( tab[globals(L)["temp"]] == 1 );
    }
  
    // Re-check of re-assignment
    //   Internally, the earlier tests sets a backref for temp_object. 
    //   This backref must be cleared when copying the object
    globals(L)["temp"] = temp_object;
    {
      object tab = newtable(L);
      tab[temp_object] = 1;
      TEST_CHECK( tab[temp_object] != 1 );
      TEST_CHECK( tab[globals(L)["temp"]] != 1 );
    }
  
    // Test lua-based value copying
    DOSTRING(L,
      "a = test_param()\n");
    DOSTRING(L, "assert(a == a)\n");
    DOSTRING(L, 
      "store_ptr(a)\n"
       "b = get_ptr()\n");
    DOSTRING(L, "assert(a == b)\n");
    
    // Test luabind object copying
    luabind::object o = luabind::globals(L)["a"];
    luabind::globals(L)["b"] = o;
    TEST_CHECK(luabind::globals(L)["b"] == luabind::globals(L)["a"]);
    DOSTRING(L, "assert(a == b)\n");
    DOSTRING(L, "assert(rawequal(a, b))\n");
  
    // Test luabind conversion and rewrapping-based copying
    test_param* tp_ptr = luabind::object_cast<test_param*>(luabind::globals(L)["a"]);
    luabind::globals(L)["b"] = tp_ptr;
    TEST_CHECK(luabind::globals(L)["b"] == luabind::globals(L)["a"]);
    DOSTRING(L, "assert(a == b)\n");
  
    DOSTRING(L,
      "tab = {}\n"
      "tab[temp] = 1\n");
    DOSTRING(L, "assert(rawequal(temp, temp))\n");
    DOSTRING(L, "assert(tab[temp] == 1)");
    
    DOSTRING(L,
      "t = test_param()\n"
      "tab = {}\n"
      "tab[t] = 1\n"
      "store_ptr(t)\n"
      "tc = get_ptr()\n");
      
     DOSTRING(L, "assert(rawequal(t, tc))\n");
     DOSTRING(L, "assert(tab[t] == 1)\n");
     DOSTRING(L, "assert(tab[tc] == 1)");
  }
  
  