Package nexj.core.persistence.file

Source Code of nexj.core.persistence.file.FileAdapterTest

// Copyright 2010-2011 NexJ Systems Inc. This software is licensed under the terms of the Eclipse Public License 1.0
package nexj.core.persistence.file;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.Writer;
import java.util.Locale;
import java.util.Properties;

import junit.framework.TestCase;

import nexj.core.meta.Metaclass;
import nexj.core.meta.Metadata;
import nexj.core.meta.MetadataLoaderDispatcher;
import nexj.core.meta.persistence.DataSource;
import nexj.core.meta.persistence.file.FileDataSourceFragment;
import nexj.core.meta.xml.XMLMetadataLoader;
import nexj.core.persistence.OID;
import nexj.core.persistence.OptimisticLockException;
import nexj.core.persistence.Query;
import nexj.core.rpc.file.ra.FileManagedConnection;
import nexj.core.runtime.Instance;
import nexj.core.runtime.InstanceList;
import nexj.core.runtime.InvocationContext;
import nexj.core.runtime.ThreadContextHolder;
import nexj.core.scripting.GlobalEnvironment;
import nexj.core.scripting.SchemeParser;
import nexj.core.util.Binary;
import nexj.core.util.IOUtil;
import nexj.core.util.SysUtil;
import nexj.core.util.XMLUtil;
import nexj.test.util.TempFileUtil;


/**
* Test the file persistence adapter.
*/
public class FileAdapterTest extends TestCase
{
   // associations

   /**
    * Cached environment.
    */
   private GlobalEnvironment m_env;


   // operations

   /**
    * @see junit.framework.TestCase#setUp()
    */
   protected void setUp() throws Exception
   {
      m_env = new GlobalEnvironment();
   }

   /**
    * @see junit.framework.TestCase#tearDown()
    */
   protected void tearDown() throws Exception
   {
      super.tearDown();

      m_env = null;
   }

   /**
    * Tests fragment replication of creates, updates, and deletes
    * with the file persistence adapter.
    */
   public void testFragmentReplicationUpdateDelete() throws Exception
   {
      Metadata metadata = loadMetadata("filestoragefragment");
      InvocationContext context = new InvocationContext(metadata);
     
      try
      {
         ThreadContextHolder.setContext(context);
     
         File mainDir = TempFileUtil.makeTemporaryDirectory(getName());
         File tempDir = new File(mainDir, "temp");
         File dataDir = new File(mainDir, "data");
         File jrnlDir = new File(mainDir, "journal");
        
         File tempDir1 = new File(mainDir, "temp1");
         File dataDir1 = new File(mainDir, "data1");
         File jrnlDir1 = new File(mainDir, "journal1");
        
         assertTrue(tempDir.mkdir());
         assertTrue(dataDir.mkdir());
         assertTrue(jrnlDir.mkdir());
        
         assertTrue(tempDir1.mkdir());
         assertTrue(dataDir1.mkdir());
         assertTrue(jrnlDir1.mkdir());
        
         DataSource ds = metadata.getDataSource("TestFilePersistenceDataSource");
        
         assertEquals(2, ds.getFragmentCount());
        
         FileDataSourceFragment defaultFrag = (FileDataSourceFragment)ds.getDefaultFragment();
         FileDataSourceFragment fragment1 = (FileDataSourceFragment)ds.getFragment("fragment1");
        
         defaultFrag.debugSettings(dataDir.getAbsolutePath(),
            tempDir.getAbsolutePath(),
            jrnlDir.getAbsolutePath());
        
         fragment1.debugSettings(dataDir1.getAbsolutePath(),
            tempDir1.getAbsolutePath(),
            jrnlDir1.getAbsolutePath());
        
         // Create it
         assertNull(context.beginTransaction());
        
         Metaclass testFPA = metadata.getMetaclass("TestFPA");
         Instance a = (Instance)testFPA.invoke("new");
        
         a.setValue("data", new Binary("Creation (\u4e2d\u6587) data.".getBytes("utf-8")));
        
         // Replicate
         context.getUnitOfWork().addReplicationFragment(a, "fragment1");
        
         commit(context);
  
         OID oidA = a.getOID();
         String sOidName = (String)oidA.getValue(0);
        
         // Verify
         File defaultFile = FileManagedConnection.splitNameToSubdirs(dataDir, sOidName, 3, 2, false);
        
         assertTrue(defaultFile.exists());
         assertEquals("Creation (\u4e2d\u6587) data.", readFileToString(defaultFile));
        
         File fragment1File = FileManagedConnection.splitNameToSubdirs(dataDir1, sOidName, 3, 2, false);
        
         assertTrue(fragment1File.exists());
         assertEquals("Creation (\u4e2d\u6587) data.", readFileToString(fragment1File));
        
         // Update it
         assertNull(context.beginTransaction());
        
         a.setValue("data", new Binary("Modified data.\nModified.".getBytes("utf-8")));
        
         // Replication
         context.getUnitOfWork().addReplicationFragment(a, "fragment1");
        
         commit(context);
        
         // Verify
         assertTrue(defaultFile.exists());
         assertEquals("Modified data.\nModified.", readFileToString(defaultFile));
         assertTrue(fragment1File.exists());
         assertEquals("Modified data.\nModified.", readFileToString(fragment1File));
        
         // Delete it
         assertNull(context.beginTransaction());
        
         a.invoke("delete");
        
         // Replication
         context.getUnitOfWork().addReplicationFragment(a, "fragment1");
        
         commit(context);
        
         //Verify
         assertFalse(defaultFile.exists());
         assertFalse(fragment1File.exists());
      }
      finally
      {
         context.complete(false);
         ThreadContextHolder.setContext(null);
      }
   }


   /**
    * Tests basic functionality of adapter by executing create,
    * read, update, and delete statements. Uses adapter to
    * verify that the operations are performed successfully.
    */
   public void testCreateReadUpdateDelete() throws Exception
   {
      Metadata metadata = loadMetadata("filestorage");
      InvocationContext context = new InvocationContext(metadata);
     
      try
      {
         ThreadContextHolder.setContext(context);
     
         /* ***** Configure the data source connection with temporary directories ***** */
         File mainDir = TempFileUtil.makeTemporaryDirectory(getName());
         File tempDir = new File(mainDir, "temp");
         File dataDir = new File(mainDir, "data");
         File jrnlDir = new File(mainDir, "journal");
        
         assertTrue(tempDir.mkdir());
         assertTrue(dataDir.mkdir());
         assertTrue(jrnlDir.mkdir());
        
        
         DataSource ds = metadata.getDataSource("TestFilePersistenceDataSource");
        
         assertEquals(1, ds.getFragmentCount());
        
         FileDataSourceFragment defaultFrag = (FileDataSourceFragment)ds.getDefaultFragment();
        
         defaultFrag.debugSettings(dataDir.getAbsolutePath(),
            tempDir.getAbsolutePath(),
            jrnlDir.getAbsolutePath());
        
        
         // Create it
         assertNull(context.beginTransaction());
        
         Metaclass testFPA = metadata.getMetaclass("TestFPA");
         Instance a = (Instance)testFPA.invoke("new");
        
         a.setValue("data", new Binary("Creation data.".getBytes("utf-8")));
        
         commit(context);
       
         OID oidA = a.getOID();
         String sOidName = (String)oidA.getValue(0);
        
         // Read
         assertNull(context.beginTransaction());
         a.invoke("read", new Object[]{
            parse("(data)"),
            parse("(= (@ id) \"" + sOidName + "\")"), null, null, null, null
         });
         assertEquals(new Binary("Creation data.".getBytes("utf-8")), a.getValue("data"));
  
         // Update
         a.setValue("data", new Binary("Update data.".getBytes("utf-8")));
        
         commit(context);
        
         // Read
         assertNull(context.beginTransaction());
         a.invoke("read", new Object[]{
            parse("(data)"),
            parse("(= (@ id) \"" + sOidName + "\")"), null, null, null, null
         });
         assertEquals(new Binary("Update data.".getBytes("utf-8")), a.getValue("data"));
        
         // Delete
         a.invoke("delete");
        
         commit(context);
        
         // Read (NOT FOUND)
         assertNull(context.beginTransaction());
           
         Query query = Query.createRead(testFPA, null, parse("(= (@ id) \"" + sOidName + "\")"), null, 10, 0, false, Query.SEC_NONE, context);
         InstanceList resultList = query.read();
           
         assertEquals(0, resultList.getCount());
        
         commit(context);

         // Create it (test that the read operation doesn't add the not-found instance to the invocation context)
         assertNull(context.beginTransaction());

         a = (Instance)testFPA.invoke("new");
         a.setOID(oidA);
         a.setValue("data", new Binary("Creation data #2.".getBytes("utf-8")));

         commit(context);
      }
      finally
      {
         context.complete(false);
         ThreadContextHolder.setContext(null);
      }
   }


   /**
    * Tests that the adapter can create multiple files in one transaction.
    */
   public void testCreateMultiple() throws Exception
   {
      Metadata metadata = loadMetadata("filestorage");
      InvocationContext context = new InvocationContext(metadata);
     
      try
      {
         ThreadContextHolder.setContext(context);
     
         /* ***** Configure the data source connection with temporary directories ***** */
         File mainDir = TempFileUtil.makeTemporaryDirectory(getName());
         File tempDir = new File(mainDir, "temp");
         File dataDir = new File(mainDir, "data");
         File jrnlDir = new File(mainDir, "journal");
        
         assertTrue(tempDir.mkdir());
         assertTrue(dataDir.mkdir());
         assertTrue(jrnlDir.mkdir());
        
        
         DataSource ds = metadata.getDataSource("TestFilePersistenceDataSource");
        
         assertEquals(1, ds.getFragmentCount());
        
         FileDataSourceFragment defaultFrag = (FileDataSourceFragment)ds.getDefaultFragment();
        
         defaultFrag.debugSettings(dataDir.getAbsolutePath(),
            tempDir.getAbsolutePath(),
            jrnlDir.getAbsolutePath());
        
        
         // Create it
         assertNull(context.beginTransaction());
        
         Metaclass testFPA = metadata.getMetaclass("TestFPA");
         Instance a = (Instance)testFPA.invoke("new");
        
         a.setValue("data", new Binary("Creation data for 'a'.".getBytes("utf-8")));
        
         Instance b = (Instance)testFPA.invoke("new");
        
         b.setValue("data", new Binary("Creation data for 'b'.".getBytes("utf-8")));
        
         commit(context);
       
         OID oidA = a.getOID();
         String sOidNameA = (String)oidA.getValue(0);
         OID oidB = b.getOID();
         String sOidNameB = (String)oidB.getValue(0);

         // Read
         assertNull(context.beginTransaction());
         a.invoke("read", new Object[]{
            parse("(data)"),
            parse("(= (@ id) \"" + sOidNameA + "\")"), null, null, null, null
         });
         assertEquals(new Binary("Creation data for 'a'.".getBytes("utf-8")), a.getValue("data"));
  
         b.invoke("read", new Object[]{
            parse("(data)"),
            parse("(= (@ id) \"" + sOidNameB + "\")"), null, null, null, null
         });
         assertEquals(new Binary("Creation data for 'b'.".getBytes("utf-8")), b.getValue("data"));

         commit(context);
      }
      finally
      {
         context.complete(false);
         ThreadContextHolder.setContext(null);
      }
   }


   /**
    * Tests that optimistic locking prevents UPDATE if file is modified
    * externally.
    */
   public void testOptimisticLockingUpdateFail() throws Exception
   {
      Metadata metadata = loadMetadata("filestorage");
      InvocationContext context = new InvocationContext(metadata);

      try
      {
         /* ***** Configure the data source connection with temporary directories ***** */
         File mainDir = TempFileUtil.makeTemporaryDirectory(getName());
         File tempDir = new File(mainDir, "temp");
         File dataDir = new File(mainDir, "data");
         File jrnlDir = new File(mainDir, "journal");
        
         assertTrue(tempDir.mkdir());
         assertTrue(dataDir.mkdir());
         assertTrue(jrnlDir.mkdir());
        
        
         DataSource ds = metadata.getDataSource("TestFilePersistenceDataSource");
        
         assertEquals(1, ds.getFragmentCount());
        
         FileDataSourceFragment defaultFrag = (FileDataSourceFragment)ds.getDefaultFragment();
        
         defaultFrag.debugSettings(dataDir.getAbsolutePath(),
            tempDir.getAbsolutePath(),
            jrnlDir.getAbsolutePath());
        
         //Write a data file
         File dataFile = new File(dataDir, "u_" + SysUtil.FILE_SEP + "__" + SysUtil.FILE_SEP + "__" + SysUtil.FILE_SEP + "u");
        
         assertTrue(dataFile.getParentFile().mkdirs());

         Writer writer = IOUtil.openBufferedWriter(dataFile, XMLUtil.ENCODING);

         writer.write("Original contents");
         writer.close();
        
         long lOriginalModified = dataFile.lastModified();
        
         //Now try to do a query.
         assertNull(context.beginTransaction());
        
         Metaclass testFPA = metadata.getMetaclass("TestFPA");
         Object where = parse("(= (@ id) \"u\")");
         Query query = Query.createRead(testFPA, null, where, null, 10, 0, false, Query.SEC_NONE, context);
        
         InstanceList resultList = query.read();
        
         assertEquals(1, resultList.size());
        
         Instance result = resultList.getInstance(0);
        
         assertEquals(new Binary("Original contents".getBytes("utf-8")), result.getValue("data"));
        
         result.setValue("data", new Binary("Modified through adapter.".getBytes("utf-8")));
        
         //Edit the data file outside the adapter
         writer = IOUtil.openBufferedWriter(dataFile, XMLUtil.ENCODING);
         writer.write("Modified directly.");
         writer.close();
         dataFile.setLastModified(lOriginalModified + 1);
        
         //Try to commit
         try
         {
            commit(context);
            fail("Expected OptimisticLockException");
         }
         catch (OptimisticLockException ex)
         {
            assertEquals("TestFPA", ex.getClassName());
         }
        
         context.getUnitOfWork().rollback(true);
        
         assertNull(context.beginTransaction());
        
         //Re-read
         result.invoke("read", new Object[]{
            parse("(data)"),
            parse("(= (@ id) \"u\")"), null, null, null, null
         });
         assertEquals(new Binary("Modified directly.".getBytes("utf-8")), result.getValue("data"));
      }
      finally
      {
         context.complete(false);
         ThreadContextHolder.setContext(null);
      }
   }


   /**
    * Tests that optimistic locking prevents DELETE if file is modified
    * externally.
    */
   public void testOptimisticLockingDeleteFail() throws Exception
   {
      Metadata metadata = loadMetadata("filestorage");
      InvocationContext context = new InvocationContext(metadata);
     
      try
      {
         /* ***** Configure the data source connection with temporary directories ***** */
         File mainDir = TempFileUtil.makeTemporaryDirectory(getName());
         File tempDir = new File(mainDir, "temp");
         File dataDir = new File(mainDir, "data");
         File jrnlDir = new File(mainDir, "journal");
        
         assertTrue(tempDir.mkdir());
         assertTrue(dataDir.mkdir());
         assertTrue(jrnlDir.mkdir());
        
        
         DataSource ds = metadata.getDataSource("TestFilePersistenceDataSource");
        
         assertEquals(1, ds.getFragmentCount());
        
         FileDataSourceFragment defaultFrag = (FileDataSourceFragment)ds.getDefaultFragment();
        
         defaultFrag.debugSettings(dataDir.getAbsolutePath(),
            tempDir.getAbsolutePath(),
            jrnlDir.getAbsolutePath());
        
         //Write a data file
         File dataFile = new File(dataDir, "d_" + SysUtil.FILE_SEP + "__" + SysUtil.FILE_SEP + "__" + SysUtil.FILE_SEP + "d");
        
         assertTrue(dataFile.getParentFile().mkdirs());
        
         Writer writer = IOUtil.openBufferedWriter(dataFile, XMLUtil.ENCODING);
        
         writer.write("Original contents");
         writer.close();
        
         long lOriginalModified = dataFile.lastModified();
        
         //Now try to do a query.
         assertNull(context.beginTransaction());
        
         Metaclass testFPA = metadata.getMetaclass("TestFPA");
         Object where = parse("(= (@ id) \"d\")");
         Query query = Query.createRead(testFPA, null, where, null, 10, 0, false, Query.SEC_NONE, context);
        
         InstanceList resultList = query.read();
        
         assertEquals(1, resultList.size());
        
         Instance result = resultList.getInstance(0);
        
         assertEquals(new Binary("Original contents".getBytes("utf-8")), result.getValue("data"));
        
         //DELETE it
         result.invoke("delete");
        
         //Edit the data file outside the adapter
         writer = IOUtil.openBufferedWriter(dataFile, XMLUtil.ENCODING);
         writer.write("Modified directly.");
         writer.close();
         dataFile.setLastModified(lOriginalModified + 1);
        
         //Try to commit
         try
         {
            commit(context);
            fail("Expected OptimisticLockException");
         }
         catch (OptimisticLockException ex)
         {
            assertEquals("TestFPA", ex.getClassName());
         }
        
         context.getUnitOfWork().rollback(true);
        
         assertNull(context.beginTransaction());
        
         //Re-read
         result.invoke("read", new Object[]{
            parse("(data)"),
            parse("(= (@ id) \"d\")"), null, null, null, null
         });

         assertEquals(new Binary("Modified directly.".getBytes("utf-8")), result.getValue("data"));
      }
      finally
      {
         context.complete(false);
         ThreadContextHolder.setContext(null);
      }
   }


   /**
    * Parse the given scheme string.
    *
    * @param sExpr Some scheme code.
    * @return The result of running the scheme parser on the parameter.
    */
   protected Object parse(String sExpr)
   {
      return new SchemeParser(m_env).parse(new StringReader(sExpr), null);
   }

   /**
    * Loads a repository configured for a given persistence engine.
    * @param sAdapter The engine to use.
    * @return The loaded metadata object.
    */
   protected static Metadata loadMetadata(String sAdapter)
   {
      Properties props = SysUtil.getConfigProperties();

      props = new Properties(props);
      props.setProperty(XMLMetadataLoader.CONNECTIONS_URL_PROPERTY, "/nexj/" + sAdapter.toLowerCase(Locale.ENGLISH) + ".connections");

      return new MetadataLoaderDispatcher().load(null, props, 0, null);
   }


   /**
    * Reads a file as a string, using utf-8 encoding.
    *
    * @param f The file to read.
    * @return The string representing the contents of the file, decoded using utf-8.
    */
   protected static String readFileToString(File f) throws Exception
   {
      FileInputStream istream = new FileInputStream(f);
      InputStreamReader reader = new InputStreamReader(istream, "utf-8");
      BufferedReader reader2 = new BufferedReader(reader);
     
      int nRead = reader2.read();
      StringBuilder buf = new StringBuilder();
     
      while (nRead >= 0)
      {
         buf.appendCodePoint(nRead);
         nRead = reader2.read();
      }
     
      reader2.close();
      reader.close();
      istream.close();
     
      return buf.toString();
   }

   /**
    * Commits the current unit of work and the distributed transaction.
    * @param context The context to get the current unit of work.
    */
   protected static void commit(InvocationContext context)
   {
      context.getUnitOfWork().setRaw(true);
      context.getUnitOfWork().commit(true);
   }
}
TOP

Related Classes of nexj.core.persistence.file.FileAdapterTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.