Exemple #1
0
int main(int argc, char **argv) {

  // create a simulator
  simphys::SimEngine sim;

  auto clock_ptr = std::make_shared< simphys::Clock<fseconds> >(fseconds{0.0f});
  clock_ptr->setScale(0.01f);
  sim.setClock(clock_ptr);

  // create a world to simulate
  auto world_ptr = std::make_shared<simphys::SimWorld>(); 
  sim.setSimWorld(world_ptr);

  // create and initialize an object
  simphys::Particle p;
  simphys::Sprite s;
  simphys::SimObject2D testObject(p,s);
  auto obj_ptr = std::make_shared<simphys::SimObject2D>(testObject);
  auto objState = testObject.getState();
  objState->setPosition(simphys::vec3{40, 50, 0});
  objState->setVelocity(simphys::vec3{50.0, 100.0, 0});
  objState->setAcceleration(simphys::vec3{0, -20.0, 0});
  objState->setMass(10000.0f);
  
  // create and initialize another object
  simphys::Particle p2;
  simphys::Sprite s2;
  simphys::SimObject2D testObject2(p2,s2);
  auto obj_ptr2 = std::make_shared<simphys::SimObject2D>(testObject2);
  auto objState2 = testObject2.getState();
  objState2->setPosition(simphys::vec3{550, 50, 0});
  objState2->setVelocity(simphys::vec3{-50.0, 100.0, 0});
  objState2->setAcceleration(simphys::vec3{0, -20.0, 0});
  objState2->setMass(100.0f);
  objState2->setColor(1.0f,0.0f,0.0f);
  objState2->setRadius(45.0f);
  
  // Command line velocity setting
  if( argc == 4 )
  {
  	objState->setVelocity(simphys::vec3{ float(atof(argv[1])), float(atof(argv[2])), 0});
  	objState2->setVelocity(simphys::vec3{ float(atof(argv[1]) * -1), float(atof(argv[2])), 0});
  }
  if( argc == 3 )
  {
  	objState->setVelocity(simphys::vec3{ float(atof(argv[1])), float(atof(argv[2])), 0});
  	objState2->setVelocity(simphys::vec3{ float(atof(argv[1]) * -1), float(atof(argv[2])), 0});
  }

  // add objects to the world.
  world_ptr->add(obj_ptr);
  world_ptr->add(obj_ptr2);

  // initialize the simulator and run it.
  sim.init();
  sim.run();

}
void test_a_dbobject_with_an_object::should_use_transactions()
{
    DBObject testObject(connection);
    CPPUNIT_ASSERT(testObject.find(1));
    CPPUNIT_ASSERT(testObject.isValid());

    bool value1 = true;
    unsigned long value2 = 0x87654321;
    unsigned long value3 = 0xBDEBDBED;
    ByteString value4 = "AAAAAAAAAAAAAAAFFFFFFFFFFFFFFF";

    OSAttribute attr1(value1);
    OSAttribute attr2(value2);
    OSAttribute attr3(value3);
    OSAttribute attr4(value4);

    CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));

    // Create secondary instance for the same object.
    // This needs to have a different connection to the database to simulate
    // another process accessing the data.
    DBObject testObject2(connection2);
    CPPUNIT_ASSERT(testObject2.find(1));
    CPPUNIT_ASSERT(testObject2.isValid());

    // Check that it has the same attributes
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());

    // Check that the attributes have the same values as set on testObject.
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4);

    // New values
    bool value1a = false;
    unsigned long value2a = 0x12345678;
    unsigned long value3a = 0xABABABAB;
    ByteString value4a = "EDEDEDEDEDEDEDEDEDEDEDEDEDEDED";

    OSAttribute attr1a(value1a);
    OSAttribute attr2a(value2a);
    OSAttribute attr3a(value3a);
    OSAttribute attr4a(value4a);

    // Start transaction on object
    CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));

    // Change the attributes
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3a));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4a));

    // Verify that the attributes were set
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());

    CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4a);

    // Verify that they are unchanged on the other instance
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());

    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4);

    // Commit the transaction
    CPPUNIT_ASSERT(testObject.commitTransaction());

    // Verify that non-modifiable attributes did not propagate but modifiable attributes
    // have now changed on the other instance
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());

    // NOTE: 3 attributes below cannot be modified after creation and therefore are not required to propagate.
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() != value1a);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() != value2a);
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() != value3a);

    // CKA_ID attribute can be modified after creation and therefore should have propagated.
    CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4a);

    // Start transaction on object
    CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));

    // Change the attributes
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
    CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));

    // Verify that the attributes were set
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());

    CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4);

    // Create a fresh third instance for the same object to force the data to be retrieved from the database.
    DBObject testObject3(connection2);
    CPPUNIT_ASSERT(testObject3.find(1));
    CPPUNIT_ASSERT(testObject3.isValid());

    // Verify that they are unchanged on the other instance, while the transaction is still in progress.
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).isByteStringAttribute());

    // Verify that the attributes from the database are still hodling the same value as when the transaction started.
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).getByteStringValue() == value4a);

    // Abort the transaction
    CPPUNIT_ASSERT(testObject.abortTransaction());

    // Verify that after aborting the transaction the values in testObject have reverted back to their
    // original state.
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());

    // After aborting a transaction the testObject should be back to pre transaction state.
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
    CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4a);

    // Verify that testObject3 still has the original values.
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).isBooleanAttribute());
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).isByteStringAttribute());

    // Verify that testObject3 still has the original values.
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
    CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).getByteStringValue() == value4a);
}
Exemple #3
0
bool Game::InitGame()
{


	// register all events
	VRegisterGameEvents();

	//
	// Initialize the ResCache - Chapter 5, page 141
	//
	//    Note - this is a little different from the book. Here we have a speccial resource ZIP file class, DevelopmentResourceZipFile,
	//    that actually reads directly from the source asset files, rather than the ZIP file. This is MUCH better during development, since
	//    you don't want to have to rebuild the ZIP file every time you make a minor change to an asset.
	//
	/*
	IResourceFile *zipFile = (m_bIsEditorRunning || m_Options.m_useDevelopmentDirectories) ?
		GCC_NEW DevelopmentResourceZipFile(L"Assets.zip", DevelopmentResourceZipFile::Editor) :
		GCC_NEW ResourceZipFile(L"Assets.zip");

	m_ResCache = GCC_NEW ResCache(50, zipFile);

	if (!m_ResCache->Init())
	{
		GCC_ERROR("Failed to initialize resource cache!  Are your paths set up correctly?");
		return false;
	}
	*/

	/*
	extern std::shared_ptr<IResourceLoader> CreateWAVResourceLoader();
	extern std::shared_ptr<IResourceLoader> CreateOGGResourceLoader();
	extern std::shared_ptr<IResourceLoader> CreateDDSResourceLoader();
	extern std::shared_ptr<IResourceLoader> CreateJPGResourceLoader();
	extern std::shared_ptr<IResourceLoader> CreateXmlResourceLoader();
	extern std::shared_ptr<IResourceLoader> CreateSdkMeshResourceLoader();
	extern std::shared_ptr<IResourceLoader> CreateScriptResourceLoader();
	*/

	// Note - register these in order from least specific to most specific! They get pushed onto a list.
	// RegisterLoader is discussed in Chapter 5, page 142

	/*
	m_ResCache->RegisterLoader(CreateWAVResourceLoader());
	m_ResCache->RegisterLoader(CreateOGGResourceLoader());
	m_ResCache->RegisterLoader(CreateDDSResourceLoader());
	m_ResCache->RegisterLoader(CreateJPGResourceLoader());
	m_ResCache->RegisterLoader(CreateXmlResourceLoader());
	m_ResCache->RegisterLoader(CreateSdkMeshResourceLoader());
	m_ResCache->RegisterLoader(CreateScriptResourceLoader());
	*/

	/*
	if (!LoadStrings("English"))
	{
		GCC_ERROR("Failed to load strings");
		return false;
	}
	*/


	//Initialize Lua Script Manager 
	if (!EngineSubsystems::getInstance().m_pLuaStateManager->VInit())
	{
		//Log error
		Engine::getInstance().Sys_Printf(stdout, "Could not load LUA");
		return false;
	}


	// Load the preinit file.  This is within braces to create a scope and destroy the resource once it's loaded.  We
	// don't need to do anything with it, we just need to load it.
	{
		//Resource resource(SCRIPT_PREINIT_FILE);
		//shared_ptr<ResHandle> pResourceHandle = m_ResCache->GetHandle(&resource);  // this actually loads the XML file from the zip file
	}

	// Register function exported from C++
	//ScriptExports::Register();
	//ScriptProcess::RegisterScriptClass();
	//BaseScriptComponent::RegisterScriptFunctions();


	//This could be done differently. Depending on players choice.
	//We could initialize specific renderer
	//For ex: If player choosed OpenGL -> Create new GLRenderer
	//If player choosed Vulkan -> Create new VulkanRenderer and so on
	g_pRendGL->VSetBackgroundColor(255, 20, 20, 200);
	g_pRendGL->VOnRestore();

	

	//In Game Code Complete 4 each Game View has a list of SceneNodes  but I think it's not right because due to duplicated data
	//My game view holds only orientation and position of player and renders ui specific to that game view. (still thinking about rendering in game view....)
	//Think about game view as a camera specific to each actor. :). Each actor will have it's own game view :)
	//Game view should only update it's positions and orientation in 3D world
	//Game view takes our current renderer
	m_pGame = VCreateGameAndView();
	if (!m_pGame)
	{
		return false;
	}

	// now that all the major systems are initialized, preload resources 
	//Preload calls are discussed in Chapter 5, page 148
	//m_ResCache->Preload("*.ogg", NULL);
	//m_ResCache->Preload("*.dds", NULL);
	//m_ResCache->Preload("*.jpg", NULL);




	std::shared_ptr<TestCube> testObject1(TYW_NEW TestCube("Cube", glx::vec3<float>(0.0f, 2.0f, 5.0f)));
	std::shared_ptr<TestCube> testObject2(TYW_NEW TestCube("Cube", glx::vec3<float>(5.0f, 2.0f, 5.0f)));
	std::shared_ptr<TestCube> testObject3(TYW_NEW TestCube("Cube", glx::vec3<float>(0.0f, 10.0f, 5.0f)));
	std::shared_ptr<TestCube> testObject4(TYW_NEW TestCube("Cube", glx::vec3<float>(-5.0f, 2.0f, 5.0f)));


	EngineSubsystems::getInstance().m_pSceneManager->AddChild(1, testObject1);
	EngineSubsystems::getInstance().m_pSceneManager->AddChild(2, testObject2);
	EngineSubsystems::getInstance().m_pSceneManager->AddChild(3, testObject3);
	EngineSubsystems::getInstance().m_pSceneManager->AddChild(4, testObject4);

	//Allocate memory
	EngineSubsystems::getInstance().m_pSceneManager->OnRestore();

	m_bIsRunning = true;
	return true;
}
void test_a_dbobject_with_an_object::can_refresh_attributes()
{
    bool value1 = true;
    bool value1a = false;
    ByteString value2 = "BDEBDBEDBBDBEBDEBE792759537328";
    ByteString value2a = "466487346943785684957634";
    ByteString value3 = "0102010201020102010201020102010201020102";

    // Create the test object
    {
        DBObject testObject(connection);
        CPPUNIT_ASSERT(testObject.find(1));
        CPPUNIT_ASSERT(testObject.isValid());

        OSAttribute attr1(value1);
        OSAttribute attr2(value2);

        CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
        CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr2));
    }

    // Now read back the object
    {
        DBObject testObject(connection);
        CPPUNIT_ASSERT(testObject.find(1));
        CPPUNIT_ASSERT(testObject.isValid());

        CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
        CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
        CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));

        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());

        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue());
        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value2);

        OSAttribute attr1(value1a);
        OSAttribute attr2(value2a);

        // Change the attributes
        CPPUNIT_ASSERT(testObject.isValid());

        CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
        CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr2));

        // Check the attributes
        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());

        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
        CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value2a);

        // Open the object a second time
        DBObject testObject2(connection);
        CPPUNIT_ASSERT(testObject2.find(1));
        CPPUNIT_ASSERT(testObject2.isValid());

        // Check the attributes on the second instance
        CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SIGN).isBooleanAttribute());
        CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT).isByteStringAttribute());

        CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
        CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT).getByteStringValue() == value2a);

        // Add an attribute on the second object
        OSAttribute attr3(value3);

        CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr3));

        // Check the attribute
        CPPUNIT_ASSERT(testObject2.attributeExists(CKA_ID));
        CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
        CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value3);

        // Now check that the first instance also knows about it
        CPPUNIT_ASSERT(testObject.attributeExists(CKA_ID));
        CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
        CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value3);
    }
}
void test_a_dbobject_with_an_object::can_refresh_attributes()
{
	bool value1 = true;
	bool value1a = false;
	unsigned long value2 = 0x87654321;
	unsigned long value2a = 0x76767676;
	unsigned long value2b = 0x89898989;
	ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
	ByteString value3a = "466487346943785684957634";
	ByteString value4 = "0102010201020102010201020102010201020102";	

	// Create the test object
	{
		DBObject testObject(connection);
		CPPUNIT_ASSERT(testObject.find(1));
		CPPUNIT_ASSERT(testObject.isValid());

		OSAttribute attr1(value1);
		OSAttribute attr2(value2);
		OSAttribute attr3(value3);

		CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
		CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
		CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr3));
	}

	// Now read back the object
	{
		DBObject testObject(connection);
		CPPUNIT_ASSERT(testObject.find(1));
		CPPUNIT_ASSERT(testObject.isValid());

		CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
		CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
		CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
		CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));

		CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->isByteStringAttribute());

		CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue());
		CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue(), value2);
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->getByteStringValue() == value3);

		OSAttribute attr1(value1a);
		OSAttribute attr2(value2a);
		OSAttribute attr3(value3a);

		// Change the attributes
		CPPUNIT_ASSERT(testObject.isValid());

		CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
		CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
		CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr3));

		// Check the attributes
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->isBooleanAttribute());
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->isByteStringAttribute());

		CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT)->getByteStringValue() == value3a);

		// Open the object a second time
		DBObject testObject2(connection);
		CPPUNIT_ASSERT(testObject2.find(1));
		CPPUNIT_ASSERT(testObject2.isValid());

		// Check the attributes on the second instance
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->isBooleanAttribute());
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT)->isByteStringAttribute());

		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN)->getBooleanValue() == value1a);
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2a);
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT)->getByteStringValue() == value3a);

		// Add an attribute on the second object
		OSAttribute attr4(value4);

		CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));

		// Check the attribute
		CPPUNIT_ASSERT(testObject2.attributeExists(CKA_ID));
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID)->isByteStringAttribute());
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID)->getByteStringValue() == value4);

		// Now check that the first instance also knows about it
		CPPUNIT_ASSERT(testObject.attributeExists(CKA_ID));
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID)->isByteStringAttribute());
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID)->getByteStringValue() == value4);

		// Now change another attribute
		OSAttribute attr2b(value2b);

		CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2b));

		// Check the attribute
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
		CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() == value2b);

		// Now check that the second instance also knows about the change
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->isUnsignedLongAttribute());
		
		// Note that the CKA_PRIME_BITS attribute cannot officially be modified.
		// We optimize inside DBObject to only propagate to the database modifiable attributes.
		// Therefore we don't expect changes to CKA_PRIME_BITS to propagate to testObject2.
		CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS)->getUnsignedLongValue() != value2b);
	}
}