    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package javax.jdo.spi;
    19
    20  import java.lang.reflect.InvocationHandler;
    21  import java.lang.reflect.Proxy;
    22
    23  import javax.jdo.JDOHelper;
    24  import javax.jdo.PersistenceManager;
    25
    26  import javax.jdo.util.AbstractTest;
    27  import javax.jdo.util.BatchTestRunner;
    28
    29  /**
    30   * This class tests the StateInterrogation interface. The test is in
    31   * several parts:
    32   * <ul><li>  Add and remove the StateInterrogation instance
    33   * </li><li> test interrogatives to return the correct answer
    34   * </li><li> test getters to return the correct answer
    35   * </li><li> test makeDirty to return.
    36   * </li></ul>
    37   * We use an mock implementation of StateInterrogation interface to
    38   * log when calls are received and to return the correct replies.
    39   * We use a java.lang.reflect.Proxy for the getPersistenceManager call
    40   * because it's too much work to mock it.
    41   */
    42  public class StateInterrogationTest extends AbstractTest {
    43
    44      private JDOImplHelper implHelper = JDOImplHelper.getInstance();
    45
    46      private JDOHelper helper = new JDOHelper();
    47
    48      /** Creates a new instance of StateInterrogationTest */
    49      public StateInterrogationTest() {
    50      }
    51
    52      /**
    53       * @param args the command line arguments
    54       */
    55      public static void main(String[] args) {
    56          BatchTestRunner.run(StateInterrogationTest.class);
    57      }
    58
    59      public void testGetObjectIdNull() {
    60          Object id2 = helper.getObjectId(nbcpc2);
    61          assertNull("ObjectId should be null before addStateInterrogations",
    62                  id2);
    63          addStateInterrogations();
    64          Object id = helper.getObjectId(Boolean.TRUE);
    65          assertNull("ObjectId should be null for non-pc instances",
    66                  id);
    67      }
    68
    69      public void testGetObjectId() {
    70          addStateInterrogations();
    71          Object id2 = helper.getObjectId(nbcpc2);
    72          assertNotNull("ObjectId should not be null",
    73                  id2);
    74          assertEquals("ObjectId should be 2",
    75                  2, id2.hashCode());
    76          Object id20 = helper.getObjectId(nbcpc2);
    77          assertEquals("ObjectIds from same object should be equal",
    78                  id2, id20);
    79      }
    80
    81      public void testRemoveStateInterrogation() {
    82          addStateInterrogations();
    83          Object id2 = helper.getObjectId(nbcpc2);
    84          assertNotNull("ObjectId should not be null",
    85                  id2);
    86          assertEquals("ObjectId should be 2",
    87                  2, id2.hashCode());
    88          implHelper.removeStateInterrogation(si2);
    89          implHelper.removeStateInterrogation(si0);
    90          Object id21 = helper.getObjectId(nbcpc2);
    91          assertNull("ObjectId should be null after RemoveStateInterrogation",
    92                  id21);
    93          Object id1 = helper.getObjectId(nbcpc1);
    94          assertNotNull("ObjectId should not be null",
    95                  id1);
    96          assertEquals("ObjectId should be 1",
    97                  1, id1.hashCode());
    98      }
    99
    100     public void testGetTransactionalObjectIdNull() {
    101         Object id2 = helper.getTransactionalObjectId(nbcpc2);
    102         assertNull("TransactionalObjectId should be null before addStateInterrogations",
    103                 id2);
    104         addStateInterrogations();
    105         Object id = helper.getTransactionalObjectId(Boolean.TRUE);
    106         assertNull("TransactionalObjectId should be null for non-pc instances",
    107                 id);
    108     }
    109
    110     public void testGetTransactionalObjectId() {
    111         addStateInterrogations();
    112         Object id2 = helper.getTransactionalObjectId(nbcpc2);
    113         assertNotNull("TransactionalObjectId should not be null",
    114                 id2);
    115         assertEquals("TransactionalObjectId should be 2",
    116                 2, id2.hashCode());
    117         Object id20 = helper.getTransactionalObjectId(nbcpc2);
    118         assertEquals("TransactionalObjectIds from same object should be equal",
    119                 id2, id20);
    120     }
    121
    122     public void testGetPersistenceManagerNull() {
    123         Object pm2 = helper.getPersistenceManager(nbcpc2);
    124         assertNull("PersistenceManager should be null before addStateInterrogations",
    125                 pm2);
    126         addStateInterrogations();
    127         Object pm = helper.getPersistenceManager(Boolean.TRUE);
    128         assertNull("PersistenceManager should be null for non-pc instances",
    129                 pm);
    130     }
    131
    132     public void testGetPersistenceManager() {
    133         addStateInterrogations();
    134         Object pm2 = helper.getPersistenceManager(nbcpc2);
    135         assertNotNull("PersistenceManager should not be null",
    136                 pm2);
    137         assertEquals("PersistenceManager should be 2",
    138                 2, pm2.hashCode());
    139         Object pm20 = helper.getPersistenceManager(nbcpc2);
    140         assertEquals("PersistenceManagers from same object should be equal",
    141                 pm2, pm20);
    142     }
    143
    144     public void testGetVersionNull() {
    145         Object id2 = helper.getVersion(nbcpc2);
    146         assertNull("Version should be null before addStateInterrogations",
    147                 id2);
    148         addStateInterrogations();
    149         Object id = helper.getVersion(Boolean.TRUE);
    150         assertNull("Version should be null for non-pc instances",
    151                 id);
    152     }
    153
    154     public void testGetVersion() {
    155         addStateInterrogations();
    156         Object id2 = helper.getVersion(nbcpc2);
    157         assertNotNull("Version should not be null",
    158                 id2);
    159         assertEquals("Version should be 2",
    160                 2, id2.hashCode());
    161         Object id20 = helper.getVersion(nbcpc2);
    162         assertEquals("Versions from same object should be equal",
    163                 id2, id20);
    164     }
    165
    166     public void testIsDeletedFalse() {
    167         assertFalse("IsDeleted should be false before addStateInterrogations",
    168                 helper.isDeleted(nbcpc2));
    169         addStateInterrogations();
    170         assertFalse("IsDeleted should be false for non-pc instances",
    171                 helper.isDeleted(Boolean.TRUE));
    172         implHelper.removeStateInterrogation(si2);
    173         assertFalse("IsDeleted should be false after removeStateInterrogations",
    174                 helper.isDeleted(nbcpc2));
    175     }
    176
    177     public void testIsDeletedMine() {
    178         addStateInterrogations();
    179         assertTrue("IsDeleted should be true for nbcpc1",
    180                 helper.isDeleted(nbcpc1));
    181         assertFalse("IsDeleted should be false for nbcpc2",
    182                 helper.isDeleted(nbcpc2));
    183     }
    184
    185     public void testIsDetachedFalse() {
    186         assertFalse("IsDetached should be false before addStateInterrogations",
    187                 helper.isDetached(nbcpc2));
    188         addStateInterrogations();
    189         assertFalse("IsDetached should be false for non-pc instances",
    190                 helper.isDetached(Boolean.TRUE));
    191         implHelper.removeStateInterrogation(si2);
    192         assertFalse("IsDetached should be false after removeStateInterrogations",
    193                 helper.isDetached(nbcpc2));
    194     }
    195
    196     public void testIsDetachedMine() {
    197         addStateInterrogations();
    198         assertTrue("IsDetached should be true for nbcpc1",
    199                 helper.isDetached(nbcpc1));
    200         assertFalse("IsDetached should be false for nbcpc2",
    201                 helper.isDetached(nbcpc2));
    202     }
    203
    204     public void testIsDirtyFalse() {
    205         assertFalse("IsDirty should be false before addStateInterrogations",
    206                 helper.isDirty(nbcpc2));
    207         addStateInterrogations();
    208         assertFalse("IsDirty should be false for non-pc instances",
    209                 helper.isDirty(Boolean.TRUE));
    210         implHelper.removeStateInterrogation(si2);
    211         nbcpc2.setDirty(true);
    212         assertFalse("IsDirty should be false after removeStateInterrogations",
    213                 helper.isDirty(nbcpc2));
    214         nbcpc2.setDirty(false);
    215     }
    216
    217     public void testIsDirtyMine() {
    218         addStateInterrogations();
    219         nbcpc1.setDirty(true);
    220         assertTrue("IsDirty should be true for nbcpc1 after setDirty(true)",
    221                 helper.isDirty(nbcpc1));
    222         nbcpc1.setDirty(false);
    223         assertFalse("IsDirty should be false for nbcpc1 after setDirty(false)",
    224                 helper.isDirty(nbcpc1));
    225         assertFalse("IsDirty should be false for nbcpc2",
    226                 helper.isDirty(nbcpc2));
    227     }
    228
    229     public void testIsNewFalse() {
    230         assertFalse("IsNew should be false before addStateInterrogations",
    231                 helper.isNew(nbcpc2));
    232         addStateInterrogations();
    233         assertFalse("IsNew should be false for non-pc instances",
    234                 helper.isNew(Boolean.TRUE));
    235         implHelper.removeStateInterrogation(si2);
    236         assertFalse("IsNew should be false after removeStateInterrogations",
    237                 helper.isNew(nbcpc2));
    238     }
    239
    240     public void testIsNewMine() {
    241         addStateInterrogations();
    242         assertTrue("IsNew should be true for nbcpc1",
    243                 helper.isNew(nbcpc1));
    244         assertFalse("IsNew should be false for nbcpc2",
    245                 helper.isNew(nbcpc2));
    246     }
    247
    248     public void testIsPersistentFalse() {
    249         assertFalse("IsPersistent should be false before addStateInterrogations",
    250                 helper.isPersistent(nbcpc2));
    251         addStateInterrogations();
    252         assertFalse("IsPersistent should be false for non-pc instances",
    253                 helper.isPersistent(Boolean.TRUE));
    254         implHelper.removeStateInterrogation(si2);
    255         assertFalse("IsPersistent should be false after removeStateInterrogations",
    256                 helper.isPersistent(nbcpc2));
    257     }
    258
    259     public void testIsPersistentMine() {
    260         addStateInterrogations();
    261         assertTrue("IsPersistent should be true for nbcpc1",
    262                 helper.isPersistent(nbcpc1));
    263         assertFalse("IsPersistent should be false for nbcpc2",
    264                 helper.isPersistent(nbcpc2));
    265     }
    266
    267     public void testIsTransactionalFalse() {
    268         assertFalse("IsTransactional should be false before addStateInterrogations",
    269                 helper.isTransactional(nbcpc2));
    270         addStateInterrogations();
    271         assertFalse("IsTransactional should be false for non-pc instances",
    272                 helper.isTransactional(Boolean.TRUE));
    273         implHelper.removeStateInterrogation(si2);
    274         assertFalse("IsTransactional should be false after removeStateInterrogations",
    275                 helper.isTransactional(nbcpc2));
    276     }
    277
    278     public void testIsTransactionalMine() {
    279         addStateInterrogations();
    280         assertTrue("IsTransactional should be true for nbcpc1",
    281                 helper.isTransactional(nbcpc1));
    282         assertFalse("IsTransactional should be false for nbcpc2",
    283                 helper.isTransactional(nbcpc2));
    284     }
    285
    286     public void testMakeDirtyFalse() {
    287         helper.makeDirty(nbcpc2, "");
    288         nbcpc2.setDirty(true);
    289         assertFalse("IsDirty should be false before addStateInterrogations",
    290                 helper.isDirty(nbcpc2));
    291         addStateInterrogations();
    292         implHelper.removeStateInterrogation(si2);
    293         nbcpc2.setDirty(false);
    294         helper.makeDirty(nbcpc2, "");
    295         assertFalse("IsDirty should be false after removeStateInterrogations",
    296                 helper.isDirty(nbcpc2));
    297     }
    298
    299     public void testMakeDirtyMine() {
    300         addStateInterrogations();
    301         helper.makeDirty(nbcpc1, "");
    302         assertTrue("IsDirty should be true for nbcpc1",
    303                 helper.isDirty(nbcpc1));
    304         nbcpc1.setDirty(false);
    305         assertFalse("IsDirty should be false after setDirty(false)",
    306                 helper.isDirty(nbcpc1));
    307     }
    308
    309     public void tearDown() {
    310         removeStateInterrogations();
    311     }
    312
    313     public void addStateInterrogations() {
    314         implHelper.addStateInterrogation(si0);
    315         implHelper.addStateInterrogation(si1);
    316         implHelper.addStateInterrogation(si2);
    317     }
    318
    319     public void removeStateInterrogations() {
    320         implHelper.removeStateInterrogation(si0);
    321         implHelper.removeStateInterrogation(si1);
    322         implHelper.removeStateInterrogation(si2);
    323     }
    324
    325     /**
    326      * The non-binary-compatible PersistenceManager class instances.
    327      */
    328     static private PersistenceManager pmProxy0 = (PersistenceManager)
    329             Proxy.newProxyInstance(
    330                 PersistenceManager.class.getClassLoader(),
    331                 new Class[] {PersistenceManager.class},
    332                 new InvocationHandlerImpl(0));
    333
    334     /**
    335      * The non-binary-compatible PersistenceManager class instances.
    336      */
    337     static private PersistenceManager pmProxy1 = (PersistenceManager)
    338             Proxy.newProxyInstance(
    339                 PersistenceManager.class.getClassLoader(),
    340                 new Class[] {PersistenceManager.class},
    341                 new InvocationHandlerImpl(1));
    342
    343     /**
    344      * The non-binary-compatible PersistenceManager class instances.
    345      */
    346     static private PersistenceManager pmProxy2 = (PersistenceManager)
    347             Proxy.newProxyInstance(
    348                 PersistenceManager.class.getClassLoader(),
    349                 new Class[] {PersistenceManager.class},
    350                 new InvocationHandlerImpl(2));
    351
    352     /**
    353      * The array of PersistenceManager proxies
    354      */
    355     static PersistenceManager[] pmProxies = {pmProxy0, pmProxy1, pmProxy2};
    356
    357     /**
    358      * The array of NonBinaryCompatiblePersistenceCapable instances.
    359      */
    360     NonBinaryCompatiblePersistenceCapable nbcpc0 =
    361        new NonBinaryCompatiblePersistenceCapable(0);
    362     NonBinaryCompatiblePersistenceCapable nbcpc1 =
    363        new NonBinaryCompatiblePersistenceCapable(1);
    364     NonBinaryCompatiblePersistenceCapable nbcpc2 =
    365        new NonBinaryCompatiblePersistenceCapable(2);
    366
    367     NonBinaryCompatiblePersistenceCapable[] nbcpcs = {nbcpc0, nbcpc1, nbcpc2};
    368
    369     /**
    370      * The array of StateInterrogations
    371      */
    372     static StateInterrogation si0 = new StateInterrogationImpl(0);
    373     static StateInterrogation si1 = new StateInterrogationImpl(1);
    374     static StateInterrogation si2 = new StateInterrogationImpl(2);
    375     static StateInterrogation[] sis = {si0, si1, si2};
    376
    377     /**
    378      * The StateInterrogation implementation manages
    379      * NonBinaryCompatiblePersistenceCapable instances that have a
    380      * hashCode equal to their own.
    381      *
    382      * <P>For the methods returning Object, return null if the object
    383      * is not managed by this StateInterrogation.
    384      *
    385      * <P>For the methods returning Boolean, return null if the object
    386      * is not managed by this StateInterrogation.
    387      *
    388      * <P>For the makeDirty method, return false if the object
    389      * is not managed by this StateInterrogation.
    390      */
    391     private static class StateInterrogationImpl implements StateInterrogation {
    392
    393         private int id;
    394
    395         public int hashCode() {
    396             return id;
    397         }
    398
    399         private StateInterrogationImpl(int id) {
    400             this.id = id;
    401         }
    402
    403         public boolean equals(Object other) {
    404             if (other.getClass() != StateInterrogationImpl.class) return false;
    405             return (other.hashCode() == id);
    406         }
    407
    408         private boolean isMine(Object pc) {
    409             return pc.hashCode() == id;
    410         }
    411
    412         public javax.jdo.PersistenceManager getPersistenceManager(Object pc) {
    413             return isMine(pc)?pmProxies[id]:null;
    414         }
    415
    416         public Object getObjectId(Object pc) {
    417             return isMine(pc)?new ObjectIdImpl(id):null;
    418         }
    419
    420         public Object getTransactionalObjectId(Object pc) {
    421             return isMine(pc)?new ObjectIdImpl(id):null;
    422         }
    423
    424         public Object getVersion(Object pc) {
    425             return isMine(pc)?new ObjectIdImpl(id):null;
    426         }
    427
    428         public Boolean isDeleted(Object pc) {
    429             if (isMine(pc)) {
    430                 return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
    431             } else return null;
    432         }
    433
    434         public Boolean isDetached(Object pc) {
    435             if (isMine(pc)) {
    436                 return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
    437             } else return null;
    438         }
    439
    440         public Boolean isDirty(Object pc) {
    441             if (isMine(pc)) {
    442                 return ((NonBinaryCompatiblePersistenceCapable)pc).isDirty()
    443                     ?Boolean.TRUE:Boolean.FALSE;
    444             } else return null;
    445         }
    446
    447         public Boolean isNew(Object pc) {
    448             if (isMine(pc)) {
    449                 return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
    450             } else return null;
    451         }
    452
    453         public Boolean isPersistent(Object pc) {
    454             if (isMine(pc)) {
    455                 return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
    456             } else return null;
    457         }
    458
    459         public Boolean isTransactional(Object pc) {
    460             if (isMine(pc)) {
    461                 return (pc.hashCode()==1)?Boolean.TRUE:Boolean.FALSE;
    462             } else return null;
    463         }
    464
    465         public boolean makeDirty(Object pc, String fieldName) {
    466             if (isMine(pc)) {
    467                 ((NonBinaryCompatiblePersistenceCapable)pc).setDirty(true);
    468                 return true;
    469             } else return false;
    470         }
    471     }
    472
    473     /**
    474      * The non-binary-compatible PersistenceCapable class.
    475      */
    476     public static class NonBinaryCompatiblePersistenceCapable {
    477         private int id;
    478         private boolean dirty = false;
    479         private NonBinaryCompatiblePersistenceCapable(int id) {
    480             this.id = id;
    481         }
    482         public int hashCode() {
    483             return id;
    484         }
    485         public void setDirty(boolean dirty) {
    486             this.dirty = dirty;
    487         }
    488         public boolean isDirty() {
    489             return dirty;
    490         }
    491     }
    492
    493     /**
    494      * The non-binary-compatible object id class.
    495      */
    496     public static class ObjectIdImpl {
    497         private int id;
    498         private ObjectIdImpl(int id) {
    499             this.id = id;
    500         }
    501         public int hashCode() {
    502             return id;
    503         }
    504         public boolean equals(Object other) {
    505             if (other.getClass() != ObjectIdImpl.class) return false;
    506             return (other.hashCode() == id);
    507         }
    508     }
    509
    510     /**
    511      * The non-binary-compatible InvocationHandler class
    512      *  for PersistenceManager proxy.
    513      */
    514     private static class InvocationHandlerImpl implements InvocationHandler {
    515         private int id;
    516         private InvocationHandlerImpl(int id) {
    517             this.id = id;
    518         }
    519          public int hashCode() {
    520             return id;
    521         }
    522         public boolean equals(Object other) {
    523             if (other.getClass() != ObjectIdImpl.class) return false;
    524             return (other.hashCode() == id);
    525         }
    526         public Object invoke(Object obj, java.lang.reflect.Method method,
    527                 Object[] params) throws Throwable {
    528             String name = method.getName();
    529             if (name == "hashCode") {
    530                 return new Integer(id);
    531             } else if (name == "equals") {
    532                 Object other = params[0];
    533                 if (!(other instanceof PersistenceManager)) return Boolean.FALSE;
    534                 int otherid = Proxy.getInvocationHandler(other).hashCode();
    535                 if (otherid == id) return Boolean.TRUE;
    536                 return Boolean.FALSE;
    537             }
    538             return null;
    539         }
    540     }
    541 }