You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2015/09/03 11:28:37 UTC

[09/14] ignite git commit: IGNITE-1364: WIP.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core-test/src/portable_reader_writer_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core-test/src/portable_reader_writer_test.cpp b/modules/platform/src/main/cpp/core-test/src/portable_reader_writer_test.cpp
new file mode 100644
index 0000000..5caf4d5
--- /dev/null
+++ b/modules/platform/src/main/cpp/core-test/src/portable_reader_writer_test.cpp
@@ -0,0 +1,1943 @@
+/*
+ *  Copyright (C) GridGain Systems. All Rights Reserved.
+ *  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+#ifndef _MSC_VER
+    #define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include "gridgain/impl/interop/interop.h"
+#include "gridgain/portable/portable.h"
+
+#include "gridgain/portable_test_defs.h"
+#include "gridgain/portable_test_utils.h"
+
+using namespace gridgain;
+using namespace gridgain::impl::interop;
+using namespace gridgain::impl::portable;
+using namespace gridgain::portable;
+using namespace gridgain_test::core::portable;
+
+template<typename T>
+void CheckPrimitive(T val)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    out.Position(18);
+
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    try
+    {
+        Write<T>(writer, NULL, val);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    Write<T>(writer, "test", val);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+
+    in.Position(18);
+
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100);
+    PortableReader reader(&readerImpl);
+
+    try
+    {
+        Read<T>(reader, NULL);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    T readVal = Read<T>(reader, "test");
+    
+    BOOST_REQUIRE(readVal == val);
+}
+
+template<typename T>
+void CheckPrimitiveArray(T dflt, T val1, T val2)
+{
+    const char* fieldName = "test";
+
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+    
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100);
+    PortableReader reader(&readerImpl);
+
+    out.Position(18);
+
+    try
+    {
+        T nullFieldArr[2];
+
+        nullFieldArr[0] = val1;
+        nullFieldArr[1] = val2;
+
+        WriteArray<T>(writer, NULL, nullFieldArr, 2);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+    
+    // 1. Write NULL and see what happens.
+    WriteArray<T>(writer, fieldName, NULL, 0);
+
+    out.Synchronize();
+    in.Synchronize();
+    
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 0) == -1);
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 2) == -1);
+
+    T arr1[2];
+    arr1[0] = dflt;
+    arr1[1] = dflt;
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 1) == -1);
+
+    BOOST_REQUIRE(arr1[0] == dflt);
+    BOOST_REQUIRE(arr1[1] == dflt);
+
+    // 2. Write empty array.
+    T arr2[2];
+    arr2[0] = val1;
+    arr2[1] = val2;
+
+    out.Position(18);
+    
+    WriteArray<T>(writer, fieldName, arr2, 0);
+
+    out.Synchronize();
+    in.Synchronize();
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 0) == 0);
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 2) == 0);
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 0) == 0);
+    BOOST_REQUIRE(arr1[0] == dflt);
+    BOOST_REQUIRE(arr1[1] == dflt);
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 2) == 0);
+    BOOST_REQUIRE(arr1[0] == dflt);
+    BOOST_REQUIRE(arr1[1] == dflt);
+
+    // 3. Partial array write.
+    out.Position(18);
+    
+    WriteArray<T>(writer, fieldName, arr2, 1);
+
+    out.Synchronize();
+    in.Synchronize();
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 0) == 1);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 2) == 1);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 0) == 1);
+    BOOST_REQUIRE(arr1[0] == dflt);
+    BOOST_REQUIRE(arr1[1] == dflt);
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 1) == 1);
+    BOOST_REQUIRE(arr1[0] == val1);
+    BOOST_REQUIRE(arr1[1] == dflt);
+    arr1[0] = dflt;
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 2) == 1);
+    BOOST_REQUIRE(arr1[0] == val1);
+    BOOST_REQUIRE(arr1[1] == dflt);
+    arr1[0] = dflt;
+
+    // 4. Full array write.
+    out.Position(18);
+    
+    WriteArray<T>(writer, fieldName, arr2, 2);
+
+    out.Synchronize();
+    in.Synchronize();
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 0) == 2);
+
+    in.Position(18);
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, NULL, 2) == 2);
+
+    try
+    {
+        ReadArray<T>(reader, NULL, arr1, 2);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 0) == 2);
+    BOOST_REQUIRE(arr1[0] == dflt);
+    BOOST_REQUIRE(arr1[1] == dflt);
+
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 1) == 2);
+    BOOST_REQUIRE(arr1[0] == dflt);
+    BOOST_REQUIRE(arr1[1] == dflt);
+
+    BOOST_REQUIRE(ReadArray<T>(reader, fieldName, arr1, 2) == 2);
+    BOOST_REQUIRE(arr1[0] == val1);
+    BOOST_REQUIRE(arr1[1] == val2);
+}
+
+void CheckWritesRestricted(PortableWriter& writer)
+{
+    try
+    {
+        writer.WriteInt8("field", 1);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        int8_t arr[1];
+
+        writer.WriteInt8Array("field", arr, 1);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        Guid val(1, 1);
+
+        writer.WriteGuid("field", val);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        writer.WriteString("field", "test");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try 
+    {
+        writer.WriteArray<int8_t>("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try 
+    {
+        writer.WriteCollection<int8_t>("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try 
+    {
+        writer.WriteMap<int8_t, int8_t>("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+}
+
+void CheckReadsRestricted(PortableReader& reader)
+{
+    try
+    {
+        reader.ReadInt8("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        int8_t arr[1];
+
+        reader.ReadInt8Array("field", arr, 1);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        reader.ReadGuid("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        reader.ReadString("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        reader.ReadArray<int8_t>("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        reader.ReadCollection<int8_t>("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        reader.ReadMap<int8_t, int8_t>("field");
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+}
+
+void CheckCollectionEmpty(CollectionType* colType)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableCollectionWriter<PortableInner> colWriter = colType ?
+        writer.WriteCollection<PortableInner>("field1", *colType) : writer.WriteCollection<PortableInner>("field1");
+
+    CheckWritesRestricted(writer);
+
+    colWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        colWriter.Write(1);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        colWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableCollectionReader<PortableInner> colReader = reader.ReadCollection<PortableInner>("field1");
+
+    if (colType)
+        BOOST_REQUIRE(colReader.GetType() == *colType);
+    else
+        BOOST_REQUIRE(colReader.GetType() == GG_COLLECTION_UNDEFINED);
+
+    BOOST_REQUIRE(colReader.GetSize() == 0);
+    BOOST_REQUIRE(!colReader.HasNext());
+    BOOST_REQUIRE(!colReader.IsNull());
+
+    try
+    {
+        colReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+void CheckCollection(CollectionType* colType)
+{
+    PortableInner writeVal1 = PortableInner(1);
+    PortableInner writeVal2 = PortableInner(0);
+    PortableInner writeVal3 = PortableInner(2);
+
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableCollectionWriter<PortableInner> colWriter = colType ?
+        writer.WriteCollection<PortableInner>("field1", *colType) : writer.WriteCollection<PortableInner>("field1");
+
+    colWriter.Write(writeVal1);
+    colWriter.Write(writeVal2);
+    colWriter.Write(writeVal3);
+
+    CheckWritesRestricted(writer);
+
+    colWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        colWriter.Write(1);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        colWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableCollectionReader<PortableInner> colReader = reader.ReadCollection<PortableInner>("field1");
+
+    CheckReadsRestricted(reader);
+
+    if (colType)
+        BOOST_REQUIRE(colReader.GetType() == *colType);
+    else
+        BOOST_REQUIRE(colReader.GetType() == GG_COLLECTION_UNDEFINED);
+
+    BOOST_REQUIRE(colReader.GetSize() == 3);
+    BOOST_REQUIRE(!colReader.IsNull());
+
+    BOOST_REQUIRE(colReader.HasNext());
+    BOOST_REQUIRE(colReader.GetNext().GetValue() == writeVal1.GetValue());
+
+    BOOST_REQUIRE(colReader.HasNext());
+    BOOST_REQUIRE(colReader.GetNext().GetValue() == writeVal2.GetValue());
+
+    BOOST_REQUIRE(colReader.HasNext());
+    BOOST_REQUIRE(colReader.GetNext().GetValue() == writeVal3.GetValue());
+
+    BOOST_REQUIRE(!colReader.HasNext());
+
+    try
+    {
+        colReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+void CheckMapEmpty(MapType* mapType)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableMapWriter<int8_t, PortableInner> mapWriter = mapType ?
+        writer.WriteMap<int8_t, PortableInner>("field1", *mapType) : writer.WriteMap<int8_t, PortableInner>("field1");
+
+    CheckWritesRestricted(writer);
+
+    mapWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        mapWriter.Write(1, PortableInner(1));
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        mapWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableMapReader<int8_t, PortableInner> mapReader = reader.ReadMap<int8_t, PortableInner>("field1");
+
+    if (mapType)
+        BOOST_REQUIRE(mapReader.GetType() == *mapType);
+    else
+        BOOST_REQUIRE(mapReader.GetType() == GG_MAP_UNDEFINED);
+
+    BOOST_REQUIRE(mapReader.GetSize() == 0);
+    BOOST_REQUIRE(!mapReader.HasNext());
+    BOOST_REQUIRE(!mapReader.IsNull());
+
+    try
+    {
+        int8_t key;
+        PortableInner val;
+
+        mapReader.GetNext(&key, &val);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+void CheckMap(MapType* mapType)
+{
+    PortableInner writeVal1 = PortableInner(1);
+    PortableInner writeVal2 = PortableInner(0);
+    PortableInner writeVal3 = PortableInner(2);
+
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableMapWriter<int8_t, PortableInner> mapWriter = mapType ?
+        writer.WriteMap<int8_t, PortableInner>("field1", *mapType) : writer.WriteMap<int8_t, PortableInner>("field1");
+
+    mapWriter.Write(1, writeVal1);
+    mapWriter.Write(2, writeVal2);
+    mapWriter.Write(3, writeVal3);
+
+    CheckWritesRestricted(writer);
+
+    mapWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        mapWriter.Write(4, PortableInner(4));
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        mapWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableMapReader<int8_t, PortableInner> mapReader = reader.ReadMap<int8_t, PortableInner>("field1");
+
+    CheckReadsRestricted(reader);
+
+    if (mapType)
+        BOOST_REQUIRE(mapReader.GetType() == *mapType);
+    else
+        BOOST_REQUIRE(mapReader.GetType() == GG_MAP_UNDEFINED);
+
+    BOOST_REQUIRE(mapReader.GetSize() == 3);
+    BOOST_REQUIRE(!mapReader.IsNull());
+
+    int8_t key;
+    PortableInner val;
+
+    BOOST_REQUIRE(mapReader.HasNext());
+
+    mapReader.GetNext(&key, &val);
+    BOOST_REQUIRE(key == 1);
+    BOOST_REQUIRE(val.GetValue() == writeVal1.GetValue());
+
+    mapReader.GetNext(&key, &val);
+    BOOST_REQUIRE(key == 2);
+    BOOST_REQUIRE(val.GetValue() == writeVal2.GetValue());
+
+    mapReader.GetNext(&key, &val);
+    BOOST_REQUIRE(key == 3);
+    BOOST_REQUIRE(val.GetValue() == writeVal3.GetValue());
+
+    BOOST_REQUIRE(!mapReader.HasNext());
+
+    try
+    {
+        mapReader.GetNext(&key, &val);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_SUITE(PortableReaderWriterTestSuite)
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveInt8)
+{
+    CheckPrimitive<int8_t>(1);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveBool)
+{
+    CheckPrimitive<bool>(true);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveInt16)
+{
+    CheckPrimitive<int16_t>(1);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveUInt16)
+{
+    CheckPrimitive<uint16_t>(1);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveInt32)
+{
+    CheckPrimitive<int32_t>(1);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveInt64)
+{
+    CheckPrimitive<int64_t>(1);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveFloat)
+{
+    CheckPrimitive<float>(1.1f);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveDouble)
+{
+    CheckPrimitive<double>(1.1);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveGuid)
+{
+    Guid val(1, 2);
+
+    CheckPrimitive<Guid>(val);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayInt8)
+{
+    CheckPrimitiveArray<int8_t>(1, 2, 3);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayBool)
+{
+    CheckPrimitiveArray<bool>(false, true, false);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayInt16)
+{
+    CheckPrimitiveArray<int16_t>(1, 2, 3);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayUInt16)
+{
+    CheckPrimitiveArray<uint16_t>(1, 2, 3);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayInt32)
+{
+    CheckPrimitiveArray<int32_t>(1, 2, 3);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayInt64)
+{
+    CheckPrimitiveArray<int64_t>(1, 2, 3);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayFloat)
+{
+    CheckPrimitiveArray<float>(1.1f, 2.2f, 3.3f);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayDouble)
+{
+    CheckPrimitiveArray<double>(1.1, 2.2, 3.3);
+}
+
+BOOST_AUTO_TEST_CASE(TestPrimitiveArrayGuid)
+{
+    Guid dflt(1, 2);
+    Guid val1(3, 4);
+    Guid val2(5, 6);
+
+    CheckPrimitiveArray<Guid>(dflt, val1, val2);
+}
+
+BOOST_AUTO_TEST_CASE(TestGuidNull)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    try
+    {
+        writer.WriteNull(NULL);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    writer.WriteNull("test");
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 100, 100);
+    PortableReader reader(&readerImpl);
+    
+    in.Position(18);
+
+    try
+    {
+        reader.ReadGuid(NULL);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    Guid expVal;
+    Guid actualVal = reader.ReadGuid("test");
+
+    BOOST_REQUIRE(actualVal == expVal);
+}
+
+BOOST_AUTO_TEST_CASE(TestString) {
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    const char* writeVal1 = "testtest";
+    const char* writeVal2 = "test";
+    std::string writeVal3 = writeVal1;
+
+    try
+    {
+        writer.WriteString(NULL, writeVal1);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        writer.WriteString(NULL, writeVal1, 4);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        writer.WriteString(NULL, writeVal3);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    writer.WriteString("field1", writeVal1);
+    writer.WriteString("field2", writeVal1, 4);
+    writer.WriteString("field3", writeVal3);
+    writer.WriteString("field4", NULL);
+    writer.WriteString("field5", NULL, 4);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    try
+    {
+        char nullCheckRes[9];
+
+        reader.ReadString(NULL, nullCheckRes, 9);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        reader.ReadString(NULL);
+
+        BOOST_FAIL("Not restricted.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    char readVal1[9];
+    char readVal2[5];
+    
+    BOOST_REQUIRE(reader.ReadString("field1", NULL, 0) == 8);
+    BOOST_REQUIRE(reader.ReadString("field1", NULL, 8) == 8);
+    BOOST_REQUIRE(reader.ReadString("field1", readVal1, 0) == 8);
+    BOOST_REQUIRE(reader.ReadString("field1", readVal1, 4) == 8);
+
+    BOOST_REQUIRE(reader.ReadString("field1", readVal1, 9) == 8);
+    std::string writeVal1Str = writeVal1;
+    std::string readVal1Str = readVal1;
+    BOOST_REQUIRE(readVal1Str.compare(writeVal1Str) == 0);
+
+    BOOST_REQUIRE(reader.ReadString("field2", readVal2, 5) == 4);
+    std::string writeVal2Str = writeVal2;
+    std::string readVal2Str = readVal2;
+    BOOST_REQUIRE(readVal2Str.compare(writeVal2Str) == 0);
+
+    std::string readVal3 = reader.ReadString("field3");
+    BOOST_REQUIRE(readVal3.compare(writeVal3) == 0);
+
+    BOOST_REQUIRE(reader.ReadString("field4", readVal1, 9) == -1);
+    BOOST_REQUIRE(reader.ReadString("field5", readVal1, 9) == -1);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringArrayNull)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    writer.WriteNull("field1");
+    writer.WriteInt8("field2", 1);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableStringArrayReader arrReader = reader.ReadStringArray("field1");
+
+    BOOST_REQUIRE(arrReader.GetSize() == -1);
+    BOOST_REQUIRE(!arrReader.HasNext());
+    BOOST_REQUIRE(arrReader.IsNull());
+
+    try
+    {
+        char res[100];
+
+        arrReader.GetNext(res, 100);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        arrReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringArrayEmpty)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableStringArrayWriter arrWriter = writer.WriteStringArray("field1");
+    
+    CheckWritesRestricted(writer);
+
+    arrWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        const char* val = "test";
+
+        arrWriter.Write(val, 4);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        const char* val = "test";
+
+        arrWriter.Write(val);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        std::string val = "test";
+
+        arrWriter.Write(val);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        arrWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableStringArrayReader arrReader = reader.ReadStringArray("field1");
+
+    BOOST_REQUIRE(arrReader.GetSize() == 0);
+    BOOST_REQUIRE(!arrReader.HasNext());
+    BOOST_REQUIRE(!arrReader.IsNull());
+
+    try
+    {
+        char res[100];
+
+        arrReader.GetNext(res, 100);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        arrReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringArray)
+{
+    const char* writeVal1 = "testtest";
+    const char* writeVal2 = "test";
+    std::string writeVal3 = "test2";
+
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableStringArrayWriter arrWriter = writer.WriteStringArray("field1");
+
+    arrWriter.Write(writeVal1);
+    arrWriter.Write(writeVal1, 4);
+    arrWriter.Write(NULL); // NULL value.
+    arrWriter.Write(NULL, 100); // NULL value again.
+    arrWriter.Write(writeVal3);
+
+    CheckWritesRestricted(writer);
+
+    arrWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        const char* val = "test";
+
+        arrWriter.Write(val, 4);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        const char* val = "test";
+
+        arrWriter.Write(val);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        std::string val = "test";
+
+        arrWriter.Write(val);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        arrWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableStringArrayReader arrReader = reader.ReadStringArray("field1");
+
+    CheckReadsRestricted(reader);
+
+    BOOST_REQUIRE(arrReader.GetSize() == 5);
+    BOOST_REQUIRE(!arrReader.IsNull());
+
+    // 1. Read first value.
+    BOOST_REQUIRE(arrReader.HasNext());
+        
+    char readVal1[9];
+    
+    BOOST_REQUIRE(arrReader.GetNext(NULL, 0) == 8);
+    BOOST_REQUIRE(arrReader.GetNext(NULL, 8) == 8);
+    BOOST_REQUIRE(arrReader.GetNext(readVal1, 0) == 8);
+    BOOST_REQUIRE(arrReader.GetNext(readVal1, 4) == 8);
+
+    BOOST_REQUIRE(arrReader.GetNext(readVal1, 9) == 8);
+    std::string writeVal1Str = writeVal1;
+    std::string readVal1Str = readVal1;
+    BOOST_REQUIRE(readVal1Str.compare(writeVal1Str) == 0);
+
+    // 2. Read second value.
+    BOOST_REQUIRE(arrReader.HasNext());
+
+    char readVal2[5];
+
+    BOOST_REQUIRE(arrReader.GetNext(readVal2, 5) == 4);
+    std::string writeVal2Str = writeVal2;
+    std::string readVal2Str = readVal2;
+    BOOST_REQUIRE(readVal2Str.compare(writeVal2Str) == 0);
+
+    // 3. Read NULL.
+    BOOST_REQUIRE(arrReader.HasNext());
+
+    BOOST_REQUIRE(arrReader.GetNext(readVal1, 4) == -1);
+    readVal1Str = readVal1;
+    BOOST_REQUIRE(readVal1Str.compare(writeVal1Str) == 0);
+
+    // 4. Read NULL again, this time through another method.
+    BOOST_REQUIRE(arrReader.HasNext());
+
+    std::string readNullVal = arrReader.GetNext();
+
+    BOOST_REQUIRE(readNullVal.length() == 0);
+
+    // 5. Read third value.
+    BOOST_REQUIRE(arrReader.HasNext());
+
+    std::string readVal3 = arrReader.GetNext();
+    BOOST_REQUIRE(readVal3.compare(writeVal3) == 0);
+
+    BOOST_REQUIRE(!arrReader.HasNext());
+
+    try
+    {
+        char res[100];
+
+        arrReader.GetNext(res, 100);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        arrReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestObject)
+{
+    PortableInner writeVal1(1);
+    PortableInner writeVal2(0);
+
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    writer.WriteObject("field1", writeVal1);
+    writer.WriteObject("field2", writeVal2);
+    writer.WriteNull("field3");
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableInner readVal1 = reader.ReadObject<PortableInner>("field1");
+    BOOST_REQUIRE(writeVal1.GetValue() == readVal1.GetValue());
+
+    PortableInner readVal2 = reader.ReadObject<PortableInner>("field2");
+    BOOST_REQUIRE(writeVal2.GetValue() == readVal2.GetValue());
+
+    PortableInner readVal3 = reader.ReadObject<PortableInner>("field3");
+    BOOST_REQUIRE(0 == readVal3.GetValue());
+}
+
+BOOST_AUTO_TEST_CASE(TestNestedObject)
+{
+    PortableOuter writeVal1(1, 2);
+    PortableOuter writeVal2(0, 0);
+
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    writer.WriteObject("field1", writeVal1);
+    writer.WriteObject("field2", writeVal2);
+    writer.WriteNull("field3");
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableOuter readVal1 = reader.ReadObject<PortableOuter>("field1");
+    BOOST_REQUIRE(writeVal1.GetValue() == readVal1.GetValue());
+    BOOST_REQUIRE(writeVal1.GetInner().GetValue() == readVal1.GetInner().GetValue());
+
+    PortableOuter readVal2 = reader.ReadObject<PortableOuter>("field2");
+    BOOST_REQUIRE(writeVal2.GetValue() == readVal2.GetValue());
+    BOOST_REQUIRE(writeVal2.GetInner().GetValue() == readVal2.GetInner().GetValue());
+
+    PortableOuter readVal3 = reader.ReadObject<PortableOuter>("field3");
+    BOOST_REQUIRE(0 == readVal3.GetValue());
+    BOOST_REQUIRE(0 == readVal3.GetInner().GetValue());
+}
+
+BOOST_AUTO_TEST_CASE(TestArrayNull)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    writer.WriteNull("field1");
+    writer.WriteInt8("field2", 1);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableArrayReader<PortableInner> arrReader = reader.ReadArray<PortableInner>("field1");
+
+    BOOST_REQUIRE(arrReader.GetSize() == -1);
+    BOOST_REQUIRE(!arrReader.HasNext());
+    BOOST_REQUIRE(arrReader.IsNull());
+
+    try
+    {
+        arrReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestArrayEmpty) 
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableArrayWriter<PortableInner> arrWriter = writer.WriteArray<PortableInner>("field1");
+
+    CheckWritesRestricted(writer);
+
+    arrWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        arrWriter.Write(1);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        arrWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableArrayReader<PortableInner> arrReader = reader.ReadArray<PortableInner>("field1");
+
+    BOOST_REQUIRE(arrReader.GetSize() == 0);
+    BOOST_REQUIRE(!arrReader.HasNext());
+    BOOST_REQUIRE(!arrReader.IsNull());
+
+    try
+    {
+        arrReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestArray)
+{
+    PortableInner writeVal1 = PortableInner(1);
+    PortableInner writeVal2 = PortableInner(0);
+    PortableInner writeVal3 = PortableInner(2);
+
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableArrayWriter<PortableInner> arrWriter = writer.WriteArray<PortableInner>("field1");
+
+    arrWriter.Write(writeVal1); 
+    arrWriter.Write(writeVal2);
+    arrWriter.Write(writeVal3);
+
+    CheckWritesRestricted(writer);
+
+    arrWriter.Close();
+
+    writer.WriteInt8("field2", 1);
+
+    try
+    {
+        arrWriter.Write(1);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    try
+    {
+        arrWriter.Close();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableArrayReader<PortableInner> arrReader = reader.ReadArray<PortableInner>("field1");
+
+    CheckReadsRestricted(reader);
+
+    BOOST_REQUIRE(arrReader.GetSize() == 3);
+    BOOST_REQUIRE(!arrReader.IsNull());
+
+    BOOST_REQUIRE(arrReader.HasNext());
+    BOOST_REQUIRE(arrReader.GetNext().GetValue() == writeVal1.GetValue());
+
+    BOOST_REQUIRE(arrReader.HasNext());
+    BOOST_REQUIRE(arrReader.GetNext().GetValue() == writeVal2.GetValue());
+
+    BOOST_REQUIRE(arrReader.HasNext());
+    BOOST_REQUIRE(arrReader.GetNext().GetValue() == writeVal3.GetValue());
+
+    BOOST_REQUIRE(!arrReader.HasNext());
+
+    try
+    {
+        arrReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestCollectionNull)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    writer.WriteNull("field1");
+    writer.WriteInt8("field2", 1);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableCollectionReader<PortableInner> colReader = reader.ReadCollection<PortableInner>("field1");
+
+    BOOST_REQUIRE(colReader.GetType() == GG_COLLECTION_UNDEFINED);
+    BOOST_REQUIRE(colReader.GetSize() == -1);
+    BOOST_REQUIRE(!colReader.HasNext());
+    BOOST_REQUIRE(colReader.IsNull()); 
+
+    try
+    {
+        colReader.GetNext();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestCollectionEmpty)
+{
+    CheckCollectionEmpty(NULL);
+}
+
+BOOST_AUTO_TEST_CASE(TestCollectionEmptyTyped)
+{
+    CollectionType typ = GG_COLLECTION_CONCURRENT_SKIP_LIST_SET;
+
+    CheckCollectionEmpty(&typ);
+}
+
+BOOST_AUTO_TEST_CASE(TestCollection)
+{
+    CheckCollection(NULL);
+}
+
+BOOST_AUTO_TEST_CASE(testCollectionTyped)
+{
+    CollectionType typ = GG_COLLECTION_CONCURRENT_SKIP_LIST_SET;
+
+    CheckCollection(&typ);
+}
+
+BOOST_AUTO_TEST_CASE(TestMapNull)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    writer.WriteNull("field1");
+    writer.WriteInt8("field2", 1);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 1000);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableMapReader<int8_t, PortableInner> mapReader = reader.ReadMap<int8_t, PortableInner>("field1");
+
+    BOOST_REQUIRE(mapReader.GetType() == GG_MAP_UNDEFINED);
+    BOOST_REQUIRE(mapReader.GetSize() == -1);
+    BOOST_REQUIRE(!mapReader.HasNext());
+    BOOST_REQUIRE(mapReader.IsNull());
+
+    try
+    {
+        int8_t key;
+        PortableInner val;
+
+        mapReader.GetNext(&key, &val);
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt8("field2") == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestMapEmpty)
+{
+    CheckMapEmpty(NULL);
+}
+
+BOOST_AUTO_TEST_CASE(TestMapEmptyTyped)
+{
+    MapType typ = GG_MAP_CONCURRENT_HASH_MAP;
+
+    CheckMapEmpty(&typ);
+}
+
+BOOST_AUTO_TEST_CASE(TestMap)
+{
+    CheckMap(NULL);
+}
+
+BOOST_AUTO_TEST_CASE(TestMapTyped)
+{
+    MapType typ = GG_MAP_CONCURRENT_HASH_MAP;
+
+    CheckMap(&typ);
+}
+
+BOOST_AUTO_TEST_CASE(TestRawMode)
+{
+    TemplatedPortableIdResolver<PortableDummy> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writerImpl(&out, &idRslvr, NULL, NULL);
+    PortableWriter writer(&writerImpl);
+
+    out.Position(18);
+
+    PortableRawWriter rawWriter = writer.RawWriter();
+
+    try
+    {
+        writer.RawWriter();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    rawWriter.WriteInt8(1);
+
+    CheckWritesRestricted(writer);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl readerImpl(&in, &idRslvr, 0, true, idRslvr.GetTypeId(), 0, 1000, 18);
+    PortableReader reader(&readerImpl);
+
+    in.Position(18);
+
+    PortableRawReader rawReader = reader.RawReader();
+
+    try
+    {
+        reader.RawReader();
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(rawReader.ReadInt8() == 1);
+
+    CheckReadsRestricted(reader);
+}
+
+BOOST_AUTO_TEST_CASE(TestFieldSeek)
+{
+    TemplatedPortableIdResolver<PortableFields> idRslvr;
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writer(&out, NULL);
+
+    PortableFields writeVal(1, 2, 3, 4);
+
+    writer.WriteTopObject<PortableFields>(writeVal);
+
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+
+    int32_t pos = in.Position();
+    in.ReadInt8(); // We do not need a header here.
+    bool usrType = in.ReadBool();
+    int32_t typeId = in.ReadInt32();
+    int32_t hashCode = in.ReadInt32();
+    int32_t len = in.ReadInt32();
+    int32_t rawOff = in.ReadInt32();
+
+    PortableReaderImpl readerImpl(&in, &idRslvr, pos, usrType, typeId, hashCode, len, rawOff);
+    PortableReader reader(&readerImpl);
+
+    // 1. Clockwise.
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+
+    // 2. Counter closkwise.
+    in.Position(18);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+
+    // 3. Same field twice.
+    in.Position(18);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+
+    in.Position(18);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+    
+    // 4. Read missing field in between.
+    in.Position(18);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+    BOOST_REQUIRE(reader.ReadInt32("missing") == 0);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+
+    in.Position(18);
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+    BOOST_REQUIRE(reader.ReadInt32("missing") == 0);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+
+    // 5. Invalid field type.
+    in.Position(18);
+    BOOST_REQUIRE(reader.ReadInt32("val1") == 1);
+
+    try
+    {
+        reader.ReadInt64("val2");
+
+        BOOST_FAIL("Error expected.");
+    }
+    catch (GridError& err)
+    {
+        BOOST_REQUIRE(err.GetCode() == GridError::GG_ERR_PORTABLE);
+    }
+
+    BOOST_REQUIRE(reader.ReadInt32("val2") == 2);
+
+    // 6. Read missing primitive fields.
+    BOOST_REQUIRE(reader.ReadInt8("missing") == 0);
+    BOOST_REQUIRE(reader.ReadBool("missing") == false);
+    BOOST_REQUIRE(reader.ReadInt16("missing") == 0);
+    BOOST_REQUIRE(reader.ReadUInt16("missing") == 0);
+    BOOST_REQUIRE(reader.ReadInt32("missing") == 0);
+    BOOST_REQUIRE(reader.ReadInt64("missing") == 0);
+    BOOST_REQUIRE(reader.ReadFloat("missing") == 0);
+    BOOST_REQUIRE(reader.ReadDouble("missing") == 0);
+
+    BOOST_REQUIRE(reader.ReadGuid("missing").GetMostSignificantBits() == 0);
+    BOOST_REQUIRE(reader.ReadGuid("missing").GetLeastSignificantBits() == 0);
+
+    // 7. Read missing primitive array fields.
+    BOOST_REQUIRE(reader.ReadInt8Array("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadBoolArray("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadInt16Array("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadUInt16Array("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadInt32Array("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadInt64Array("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadFloatArray("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadDoubleArray("missing", NULL, 1) == -1);
+
+    BOOST_REQUIRE(reader.ReadGuidArray("missing", NULL, 1) == -1);
+
+    // 8. Read missing string fields.
+    BOOST_REQUIRE(reader.ReadString("missing", NULL, 1) == -1);
+    BOOST_REQUIRE(reader.ReadString("missing").length() == 0);
+
+    // 9. Read missing object fields.
+    BOOST_REQUIRE(reader.ReadObject<PortableFields*>("missing") == NULL);
+    
+    // 10. Read missing container fields.
+    PortableStringArrayReader stringArrReader = reader.ReadStringArray("missing");
+    BOOST_REQUIRE(stringArrReader.IsNull());
+
+    PortableArrayReader<PortableFields> arrReader = reader.ReadArray<PortableFields>("missing");
+    BOOST_REQUIRE(arrReader.IsNull());
+
+    PortableCollectionReader<PortableFields> colReader = reader.ReadCollection<PortableFields>("missing");
+    BOOST_REQUIRE(colReader.IsNull());
+
+    PortableMapReader<int32_t, PortableFields> mapReader = reader.ReadMap<int32_t, PortableFields>("missing");
+    BOOST_REQUIRE(mapReader.IsNull());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core-test/src/portable_session_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core-test/src/portable_session_test.cpp b/modules/platform/src/main/cpp/core-test/src/portable_session_test.cpp
new file mode 100644
index 0000000..5eb732c
--- /dev/null
+++ b/modules/platform/src/main/cpp/core-test/src/portable_session_test.cpp
@@ -0,0 +1,249 @@
+/*
+ *  Copyright (C) GridGain Systems. All Rights Reserved.
+ *  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+#ifndef _MSC_VER
+    #define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include "gridgain/impl/interop/interop.h"
+#include "gridgain/impl/portable/portable_reader_impl.h"
+#include "gridgain/impl/portable/portable_writer_impl.h"
+
+#include "gridgain/portable_test_defs.h"
+
+using namespace gridgain;
+using namespace gridgain::impl::interop;
+using namespace gridgain::impl::portable;
+using namespace gridgain::portable;
+using namespace gridgain_test::core::portable;
+
+/*
+ * Check primitive value serialization-deserialization.
+ */
+template<typename T>
+void CheckRawPrimitive(T writeVal) 
+{
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem); 
+    PortableWriterImpl writeSes(&out, NULL);
+    writeSes.WriteTopObject<T>(writeVal);
+    out.Synchronize();
+
+    InteropInputStream in(&mem); 
+    PortableReaderImpl reader(&in);
+    T readVal = reader.ReadTopObject<T>();
+
+    BOOST_REQUIRE(readVal == writeVal);
+}
+
+BOOST_AUTO_TEST_SUITE(PortableSessionTestSuite)
+
+BOOST_AUTO_TEST_CASE(TestByte)
+{
+    CheckRawPrimitive<int8_t>(-128);
+    CheckRawPrimitive<int8_t>(-1);
+    CheckRawPrimitive<int8_t>(0);
+    CheckRawPrimitive<int8_t>(1);
+    CheckRawPrimitive<int8_t>(127);
+}
+
+BOOST_AUTO_TEST_CASE(TestBool)
+{
+    CheckRawPrimitive<bool>(true);
+    CheckRawPrimitive<bool>(false);
+}
+
+BOOST_AUTO_TEST_CASE(TestShort)
+{
+    //CheckRawPrimitive<int16_t>(std::numeric_limits<int16_t>::min()); 
+    CheckRawPrimitive<int16_t>(-1);
+    CheckRawPrimitive<int16_t>(0);
+    CheckRawPrimitive<int16_t>(1);
+    //CheckRawPrimitive<int16_t>(std::numeric_limits<int16_t>::max());
+}
+
+BOOST_AUTO_TEST_CASE(TestChar)
+{
+    //CheckRawPrimitive<uint16_t>(std::numeric_limits<uint16_t>::min());
+    CheckRawPrimitive<uint16_t>(1);
+    //CheckRawPrimitive<uint16_t>(std::numeric_limits<uint16_t>::max());
+}
+
+BOOST_AUTO_TEST_CASE(TestInt)
+{
+    //CheckRawPrimitive<int32_t>(std::numeric_limits<int32_t>::min());
+    CheckRawPrimitive<int32_t>(-1);
+    CheckRawPrimitive<int32_t>(0);
+    CheckRawPrimitive<int32_t>(1);
+    //CheckRawPrimitive<int32_t>(std::numeric_limits<int32_t>::max());
+}
+
+BOOST_AUTO_TEST_CASE(TestLong)
+{
+    //CheckRawPrimitive<int64_t>(std::numeric_limits<int64_t>::min());
+    CheckRawPrimitive<int64_t>(-1);
+    CheckRawPrimitive<int64_t>(0);
+    CheckRawPrimitive<int64_t>(1);
+    //CheckRawPrimitive<int64_t>(std::numeric_limits<int64_t>::max());
+}
+
+BOOST_AUTO_TEST_CASE(TestFloat)
+{
+    CheckRawPrimitive<float>(-1.1f);
+    CheckRawPrimitive<float>(0);
+    CheckRawPrimitive<float>(1.1f);
+}
+
+BOOST_AUTO_TEST_CASE(TestDouble)
+{
+    CheckRawPrimitive<double>(-1.1);
+    CheckRawPrimitive<double>(0);
+    CheckRawPrimitive<double>(1.1);
+}
+
+BOOST_AUTO_TEST_CASE(TestGuid)
+{
+    Guid writeVal = Guid(1, 1);
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writeSes(&out, NULL);
+    writeSes.WriteTopObject<Guid>(writeVal);
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl reader(&in);
+    Guid readVal = reader.ReadTopObject<Guid>();
+
+    BOOST_REQUIRE(readVal.GetMostSignificantBits() == writeVal.GetMostSignificantBits());
+    BOOST_REQUIRE(readVal.GetLeastSignificantBits() == writeVal.GetLeastSignificantBits());    
+}
+
+BOOST_AUTO_TEST_CASE(TestString)
+{
+    std::string writeVal = "MyString";
+
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writeSes(&out, NULL);
+    writeSes.WriteTopObject<std::string>(writeVal);
+    out.Synchronize();
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl reader(&in);
+    std::string readVal = reader.ReadTopObject<std::string>();
+
+    BOOST_REQUIRE(readVal.compare(writeVal) == 0);
+}
+
+BOOST_AUTO_TEST_CASE(TestObject)
+{
+    InteropUnpooledMemory mem(1024);
+    
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writer(&out, NULL);
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl reader(&in);
+
+    // 1. Test null object.
+    PortableInner writeVal(0);
+    
+    writer.WriteTopObject<PortableInner>(writeVal);
+    out.Synchronize();
+    
+    in.Synchronize();
+    PortableInner readVal = reader.ReadTopObject<PortableInner>();
+
+    BOOST_REQUIRE(readVal.GetValue() == 0);
+
+    // 2. Test non-null object.
+    out.Position(0);
+    in.Position(0);
+
+    writeVal = PortableInner(1);
+
+    writer.WriteTopObject<PortableInner>(writeVal);
+    out.Synchronize();
+
+    in.Synchronize();
+    readVal = reader.ReadTopObject<PortableInner>();
+
+    BOOST_REQUIRE(readVal.GetValue() == 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestObjectWithRawFields)
+{
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writer(&out, NULL);
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl reader(&in);
+
+    out.Position(0);
+    in.Position(0);
+
+    PortableFields writeVal = PortableFields(1, 2, 3, 4);
+
+    writer.WriteTopObject<PortableFields>(writeVal);
+    out.Synchronize();
+
+    in.Synchronize();
+    PortableFields readVal = reader.ReadTopObject<PortableFields>();
+
+    BOOST_REQUIRE(readVal.val1 == 1);
+    BOOST_REQUIRE(readVal.val2 == 2);
+    BOOST_REQUIRE(readVal.rawVal1 == 3);
+    BOOST_REQUIRE(readVal.rawVal2 == 4);
+}
+
+BOOST_AUTO_TEST_CASE(TestPointer)
+{
+    InteropUnpooledMemory mem(1024);
+
+    InteropOutputStream out(&mem);
+    PortableWriterImpl writer(&out, NULL);
+
+    InteropInputStream in(&mem);
+    PortableReaderImpl reader(&in);
+
+    // 1. Test null object.
+    writer.WriteTopObject<PortableInner*>(NULL);
+    out.Synchronize();
+
+    in.Synchronize();
+    PortableInner* readVal = reader.ReadTopObject<PortableInner*>();
+
+    BOOST_REQUIRE(readVal == NULL);
+
+    // 2. Test non-null object.
+    out.Position(0);
+    in.Position(0);
+
+    PortableInner writeVal = PortableInner(1);
+
+    writer.WriteTopObject<PortableInner*>(&writeVal);
+    out.Synchronize();
+
+    in.Synchronize();
+    readVal = reader.ReadTopObject<PortableInner*>();
+
+    BOOST_REQUIRE(readVal->GetValue() == 1);
+
+    delete readVal;
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core-test/src/portable_test_defs.cpp
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core-test/src/portable_test_defs.cpp b/modules/platform/src/main/cpp/core-test/src/portable_test_defs.cpp
new file mode 100644
index 0000000..bbb1acd
--- /dev/null
+++ b/modules/platform/src/main/cpp/core-test/src/portable_test_defs.cpp
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (C) GridGain Systems. All Rights Reserved.
+ *  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+#include "gridgain/impl/interop/interop.h"
+#include "gridgain/portable/portable.h"
+
+#include "gridgain/portable_test_defs.h"
+
+using namespace gridgain;
+using namespace gridgain::impl::interop;
+using namespace gridgain::impl::portable;
+using namespace gridgain::portable;
+
+namespace gridgain_test
+{
+    namespace core
+    {
+        namespace portable
+        {
+            PortableInner::PortableInner() : val(0)
+            {
+                // No-op.
+            }
+
+            PortableInner::PortableInner(int32_t val) : val(val)
+            {
+                // No-op.
+            }
+
+            int32_t PortableInner::GetValue() const
+            {
+                return val;
+            }
+
+            PortableOuter::PortableOuter(int32_t valIn, int32_t valOut) : inner(valIn), val(valOut)
+            {
+                // No-op.
+            }
+
+            PortableInner PortableOuter::GetInner() const
+            {
+                return inner;
+            }
+
+            int32_t PortableOuter::GetValue() const
+            {
+                return val;
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core-test/src/teamcity_boost.cpp
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core-test/src/teamcity_boost.cpp b/modules/platform/src/main/cpp/core-test/src/teamcity_boost.cpp
new file mode 100644
index 0000000..8a91c4e
--- /dev/null
+++ b/modules/platform/src/main/cpp/core-test/src/teamcity_boost.cpp
@@ -0,0 +1,159 @@
+/* Copyright 2011 JetBrains s.r.o.
+ * 
+ * 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.
+ * 
+ * $Revision: 88625 $
+*/
+
+#define BOOST_TEST_MODULE GridGainCoreTest
+
+#include <sstream>
+
+#include <boost/test/unit_test_suite_impl.hpp>
+#include <boost/test/results_collector.hpp>
+#include <boost/test/utils/basic_cstring/io.hpp>
+#include <boost/test/unit_test_log.hpp>
+#include <boost/test/included/unit_test.hpp>
+
+#include "teamcity_messages.h"
+
+using namespace boost::unit_test;
+using namespace std;
+
+namespace JetBrains {
+
+// Custom formatter for TeamCity messages
+class TeamcityBoostLogFormatter: public boost::unit_test::unit_test_log_formatter {
+    TeamcityMessages messages;
+    std::string currentDetails;
+    std::string flowId;
+    
+public:
+    TeamcityBoostLogFormatter(const std::string &_flowId);
+    TeamcityBoostLogFormatter();
+    
+    void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount);
+    void log_finish(std::ostream&);
+    void log_build_info(std::ostream&);
+
+    void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu);
+    void test_unit_finish(std::ostream&,
+        boost::unit_test::test_unit const& tu,
+        unsigned long elapsed);
+    void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu);
+
+    void log_exception(std::ostream&,
+        boost::unit_test::log_checkpoint_data const&,
+        boost::unit_test::const_string explanation);
+
+    void log_entry_start(std::ostream&,
+        boost::unit_test::log_entry_data const&,
+        log_entry_types let);
+    void log_entry_value(std::ostream&, boost::unit_test::const_string value);
+    void log_entry_finish(std::ostream&);
+};
+
+// Fake fixture to register formatter
+struct TeamcityFormatterRegistrar {
+    TeamcityFormatterRegistrar() {
+        if (JetBrains::underTeamcity()) {
+            boost::unit_test::unit_test_log.set_formatter(new JetBrains::TeamcityBoostLogFormatter());
+            boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::log_successful_tests);
+        }
+    }
+};
+BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar);
+
+// Formatter implementation
+string toString(const_string bstr) {
+    stringstream ss;
+    
+    ss << bstr;
+    
+    return ss.str();
+}
+
+TeamcityBoostLogFormatter::TeamcityBoostLogFormatter(const std::string &_flowId)
+: flowId(_flowId)
+{}
+
+TeamcityBoostLogFormatter::TeamcityBoostLogFormatter()
+: flowId(getFlowIdFromEnvironment())
+{}
+
+void TeamcityBoostLogFormatter::log_start(ostream &out, counter_t test_cases_amount)
+{}
+
+void TeamcityBoostLogFormatter::log_finish(ostream &out)
+{}
+
+void TeamcityBoostLogFormatter::log_build_info(ostream &out)
+{}
+
+void TeamcityBoostLogFormatter::test_unit_start(ostream &out, test_unit const& tu) {
+    messages.setOutput(out);
+
+    if (tu.p_type == tut_case) {
+        messages.testStarted(tu.p_name, flowId);
+    } else {
+        messages.suiteStarted(tu.p_name, flowId);
+    }
+    
+    currentDetails.clear();
+}
+
+void TeamcityBoostLogFormatter::test_unit_finish(ostream &out, test_unit const& tu, unsigned long elapsed) {
+    messages.setOutput(out);
+
+    test_results const& tr = results_collector.results(tu.p_id);
+    if (tu.p_type == tut_case) {
+        if(!tr.passed()) {
+            if(tr.p_skipped) {
+                messages.testIgnored(tu.p_name, "ignored", flowId);
+            } else if (tr.p_aborted) {
+                messages.testFailed(tu.p_name, "aborted", currentDetails, flowId);
+            } else {
+                messages.testFailed(tu.p_name, "failed", currentDetails, flowId);
+            }
+        }
+        
+        messages.testFinished(tu.p_name, elapsed / 1000, flowId);
+    } else {
+        messages.suiteFinished(tu.p_name, flowId);
+    }
+}
+
+void TeamcityBoostLogFormatter::test_unit_skipped(ostream &out, test_unit const& tu)
+{}
+
+void TeamcityBoostLogFormatter::log_exception(ostream &out, log_checkpoint_data const&, const_string explanation) {
+    string what = toString(explanation);
+    
+    out << what << endl;
+    currentDetails += what + "\n";
+}
+
+void TeamcityBoostLogFormatter::log_entry_start(ostream&, log_entry_data const&, log_entry_types let)
+{}
+
+void TeamcityBoostLogFormatter::log_entry_value(ostream &out, const_string value) {
+    out << value;
+    currentDetails += toString(value);
+}
+
+void TeamcityBoostLogFormatter::log_entry_finish(ostream &out) {
+    out << endl;
+    currentDetails += "\n";
+}
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core-test/src/teamcity_messages.cpp
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core-test/src/teamcity_messages.cpp b/modules/platform/src/main/cpp/core-test/src/teamcity_messages.cpp
new file mode 100644
index 0000000..087409e
--- /dev/null
+++ b/modules/platform/src/main/cpp/core-test/src/teamcity_messages.cpp
@@ -0,0 +1,150 @@
+/* Copyright 2011 JetBrains s.r.o.
+ * 
+ * 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.
+ *
+ * $Revision: 88625 $
+*/
+
+#include <stdlib.h>
+#include <sstream>
+
+#include "teamcity_messages.h"
+
+using namespace std;
+
+namespace JetBrains {
+
+std::string getFlowIdFromEnvironment() {
+    const char *flowId = getenv("TEAMCITY_PROCESS_FLOW_ID");
+    return flowId == NULL ? "" : flowId;
+}
+
+bool underTeamcity() {
+    return getenv("TEAMCITY_PROJECT_NAME") != NULL;
+}
+
+TeamcityMessages::TeamcityMessages()
+: m_out(&cout)
+{}
+
+void TeamcityMessages::setOutput(ostream &out) {
+    m_out = &out;
+}
+
+string TeamcityMessages::escape(string s) {
+    string result;
+    
+    for (size_t i = 0; i < s.length(); i++) {
+        char c = s[i];
+        
+        switch (c) {
+        case '\n': result.append("|n"); break;
+        case '\r': result.append("|r"); break;
+        case '\'': result.append("|'"); break;
+        case '|':  result.append("||"); break;
+        case ']':  result.append("|]"); break;
+        default:   result.append(&c, 1);
+        }
+    }
+    
+    return result;
+}
+
+void TeamcityMessages::openMsg(const string &name) {
+    // endl for http://jetbrains.net/tracker/issue/TW-4412
+    *m_out << endl << "##teamcity[" << name;
+}
+
+void TeamcityMessages::closeMsg() {
+    *m_out << "]";
+    // endl for http://jetbrains.net/tracker/issue/TW-4412
+    *m_out << endl;
+    m_out->flush();
+}
+
+void TeamcityMessages::writeProperty(string name, string value) {
+    *m_out << " " << name << "='" << escape(value) << "'";
+}
+
+void TeamcityMessages::suiteStarted(string name, string flowid) {
+    openMsg("testSuiteStarted");
+    writeProperty("name", name);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+    
+    closeMsg();
+}
+
+void TeamcityMessages::suiteFinished(string name, string flowid) {
+    openMsg("testSuiteFinished");
+    writeProperty("name", name);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+    
+    closeMsg();
+}
+
+void TeamcityMessages::testStarted(string name, string flowid) {
+    openMsg("testStarted");
+    writeProperty("name", name);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+    
+    closeMsg();
+}
+
+void TeamcityMessages::testFinished(string name, int durationMs, string flowid) {
+    openMsg("testFinished");
+
+    writeProperty("name", name);
+
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    if(durationMs >= 0) {
+        stringstream out;
+        out << durationMs;
+        writeProperty("duration", out.str());
+    }
+    
+    closeMsg();
+}
+
+void TeamcityMessages::testFailed(string name, string message, string details, string flowid) {
+    openMsg("testFailed");
+    writeProperty("name", name);
+    writeProperty("message", message);
+    writeProperty("details", details);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+    
+    closeMsg();
+}
+
+void TeamcityMessages::testIgnored(std::string name, std::string message, string flowid) {
+    openMsg("testIgnored");
+    writeProperty("name", name);
+    writeProperty("message", message);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+    
+    closeMsg();
+}
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core/Makefile.am b/modules/platform/src/main/cpp/core/Makefile.am
new file mode 100644
index 0000000..3f791f8
--- /dev/null
+++ b/modules/platform/src/main/cpp/core/Makefile.am
@@ -0,0 +1,49 @@
+ACLOCAL_AMFLAGS = "-Im4"
+
+SUBDIRS = . include os/linux/include
+DIST_SUBDIRS = . include os/linux/include
+
+AM_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/os/linux/include -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux -DIGNITE_IMPL
+AM_CXXFLAGS = -Wall -std=c++0x
+LIB_LDFLAGS = -no-undefined -version-info 1
+
+COMMON_SRC = os/linux/src/impl/utils.cpp \
+             src/grid_error.cpp \
+             src/guid.cpp \
+             src/impl/handle_registry.cpp \
+             src/impl/interop/interop_memory.cpp \
+             src/impl/interop/interop_input_stream.cpp \
+             src/impl/interop/interop_output_stream.cpp \
+             src/portable/portable_type.cpp \
+             src/impl/portable/portable_metadata_snapshot.cpp \
+             src/impl/portable/portable_metadata_handler.cpp \
+             src/impl/portable/portable_metadata_updater.cpp \
+             src/impl/portable/portable_metadata_manager.cpp \
+             src/impl/portable/portable_utils.cpp \
+             src/impl/portable/portable_reader_impl.cpp \
+             src/impl/portable/portable_writer_impl.cpp \
+             src/portable/portable_containers.cpp \
+             src/portable/portable_raw_reader.cpp \
+             src/portable/portable_raw_writer.cpp \
+             src/portable/portable_reader.cpp \
+             src/portable/portable_writer.cpp \
+             src/impl/portable/portable_metadata_updater_impl.cpp \
+             src/impl/grid_environment.cpp \
+             src/impl/cache/query/query_impl.cpp \
+             src/impl/cache/cache_impl.cpp \
+             src/impl/grid_impl.cpp \
+             src/grid.cpp \
+             src/grid_factory.cpp
+
+lib_LTLIBRARIES = libgridgain.la
+libgridgain_la_SOURCES = $(COMMON_SRC)
+libgridgain_la_LDFLAGS = $(LIB_LDFLAGS) -L/usr/local/lib -lignite-common -ldl -version-info 0:0:0 -release $(PACKAGE_VERSION)
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gridgain.pc
+
+clean-local:
+	$(RM) *.gcno *.gcda
+
+clean-docs:
+	$(RM) $(DX_CLEANFILES)

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core/configure.ac
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core/configure.ac b/modules/platform/src/main/cpp/core/configure.ac
new file mode 100644
index 0000000..bc9ecde
--- /dev/null
+++ b/modules/platform/src/main/cpp/core/configure.ac
@@ -0,0 +1,45 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.69])
+AC_INIT([GridGain for C++], [7.4.1], [info@gridgain.com], [gridgain], [www.gridgain.com])
+AC_CONFIG_SRCDIR(src)
+
+AC_CANONICAL_SYSTEM
+AC_CONFIG_MACRO_DIR([m4])
+AC_LANG([C++])
+
+# Initialize automake
+AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
+AC_CONFIG_HEADER(config.h)
+
+AM_PROG_AR
+
+# Checks for programs.
+GXX="-g -O2"
+
+AC_PROG_CXX
+
+# Initialize Libtool
+LT_INIT
+
+# Checks for libraries.
+AC_CHECK_LIB([pthread], [pthread_mutex_lock])
+
+# Checks for header files.
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_INLINE
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_INT64_T
+AC_TYPE_INT8_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_ERROR_AT_LINE
+
+AC_CONFIG_FILES(Makefile include/Makefile os/linux/include/Makefile gridgain.pc)
+
+AC_OUTPUT

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core/gridgain.pc.in
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core/gridgain.pc.in b/modules/platform/src/main/cpp/core/gridgain.pc.in
new file mode 100644
index 0000000..f248f8c
--- /dev/null
+++ b/modules/platform/src/main/cpp/core/gridgain.pc.in
@@ -0,0 +1,9 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gridgain
+Description: GridGain for C++.
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lgridgain

http://git-wip-us.apache.org/repos/asf/ignite/blob/1e18fa32/modules/platform/src/main/cpp/core/include/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platform/src/main/cpp/core/include/Makefile.am b/modules/platform/src/main/cpp/core/include/Makefile.am
new file mode 100644
index 0000000..cf56655
--- /dev/null
+++ b/modules/platform/src/main/cpp/core/include/Makefile.am
@@ -0,0 +1,44 @@
+ACLOCAL_AMFLAGS = "-Im4"
+
+nobase_include_HEADERS = gridgain/cache/cache.h \
+                         gridgain/cache/cache_entry.h \
+                         gridgain/cache/cache_peek_mode.h \
+                         gridgain/cache/query/query_argument.h \
+                         gridgain/cache/query/query_cursor.h \
+                         gridgain/cache/query/query_scan.h \
+                         gridgain/cache/query/query_sql.h \
+                         gridgain/cache/query/query_text.h \
+                         gridgain/cache/query/query.h \
+                         gridgain/impl/cache/cache_impl.h \
+                         gridgain/impl/cache/query/query_impl.h \
+                         gridgain/impl/interop/interop.h \
+                         gridgain/impl/interop/interop_input_stream.h \
+                         gridgain/impl/interop/interop_memory.h \
+                         gridgain/impl/interop/interop_output_stream.h \
+                         gridgain/impl/portable/portable_metadata_handler.h \
+                         gridgain/impl/portable/portable_metadata_manager.h \
+                         gridgain/impl/portable/portable_metadata_snapshot.h \
+                         gridgain/impl/portable/portable_metadata_updater.h \
+                         gridgain/impl/portable/portable_metadata_updater_impl.h \
+                         gridgain/impl/portable/portable_common.h \
+                         gridgain/impl/portable/portable_id_resolver.h \
+                         gridgain/impl/portable/portable_reader_impl.h \
+                         gridgain/impl/portable/portable_utils.h \
+                         gridgain/impl/portable/portable_writer_impl.h \
+                         gridgain/impl/grid_environment.h \
+                         gridgain/impl/grid_impl.h \
+                         gridgain/impl/handle_registry.h \
+                         gridgain/impl/operations.h \
+                         gridgain/portable/portable.h \
+                         gridgain/portable/portable_consts.h \
+                         gridgain/portable/portable_containers.h \
+                         gridgain/portable/portable_type.h \
+                         gridgain/portable/portable_raw_reader.h \
+                         gridgain/portable/portable_raw_writer.h \
+                         gridgain/portable/portable_reader.h \
+                         gridgain/portable/portable_writer.h \
+                         gridgain/grid.h \
+                         gridgain/grid_configuration.h \
+                         gridgain/grid_error.h \
+                         gridgain/grid_factory.h \
+                         gridgain/guid.h