Browse Source

test rewritable

Ranides Atterwim 4 years ago
parent
commit
f8579eaee7

+ 7 - 3
assira.core/src/test/java/net/ranides/assira/reflection/impl/RConstructorTest.java

@@ -124,11 +124,15 @@ public class RConstructorTest {
         assertEquals("Record{1:2:3}", c3.invoke(1, 2, 3).toString());
     }
 
-    @Ignore("very bad reflection")
     @Test
     public void testAccessor() {
-        // @todo (assira #3) test Constructor#accessor in sane way
-        // bierzemy konstruktor enum?! przecież to jest bezczelność
+        // we search for constructors of "enum" types
+        // although it is quite strange behaviour, we do this intentionally because
+        // it is most important use-case for #accessor method anyway
+        //
+        // accessor is useful if you want to bypass all sanity checks inside Class#newInstance
+        // most of them can be disabled by calling AccessibleObject#setAccessible
+        // but not all. it applies especially for enum.
 
         AnyFunction<Letters> aLetters = IClass.typeinfo(Letters.class).constructors()
             .require(IAttribute.DECLARED)

+ 48 - 5
assira.core/src/test/java/net/ranides/assira/reflection/impl/RFieldTest.java

@@ -6,14 +6,21 @@
  */
 package net.ranides.assira.reflection.impl;
 
-import java.lang.invoke.WrongMethodTypeException;
-import java.util.Arrays;
-import java.util.List;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assume;
+import org.junit.Test;
+
 import net.ranides.assira.generic.TypeToken;
 import net.ranides.assira.generic.Wrapper;
 import net.ranides.assira.reflection.*;
 import net.ranides.assira.reflection.mockup.ForFields;
-import org.junit.Test;
+
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
 import static net.ranides.assira.junit.NewAssert.*;
 
 /**
@@ -132,7 +139,43 @@ public class RFieldTest {
         });
          
     }
-    
+
+    @Test
+    public void testRewritable() {
+        IField field = cr.field("frozen").get().rewritable();
+
+        ForFields.Record record = new ForFields.Record();
+        Wrapper<Object> wrapper = field.bind(record);
+
+        assertEquals(11, field.get(record));
+        assertEquals(11, wrapper.get());
+        assertEquals(11, record.frozen);
+
+        field.set(record, 99);
+
+        // reflective call will see changes
+        assertEquals(99, field.get(record));
+        assertEquals(99, wrapper.get());
+
+        // direct access can return updated value but it is not guaranteed
+        Assume.assumeThat(record.frozen, CoreMatchers.equalTo(99));
+    }
+
+    @Test
+    public void testRewritableThread() throws InterruptedException, ExecutionException {
+        IField field = cr.field("frozen").get().rewritable();
+
+        ForFields.Record record = Executors.newSingleThreadExecutor().submit(() -> {
+            ForFields.Record temp = new ForFields.Record();
+            field.set(temp, 77);
+            return temp;
+        }).get();
+
+        // it is more or less guaranteed that change is visible because
+        // object was created in another thread and field was modified before any read operation
+        assertEquals(77, record.frozen);
+    }
+
     private static void assertEquiList(List<String> expected, List<String> values) {
         while(values.remove("$jacocoData")) { }
         while(values.remove("Record $jacocoData")) { }

+ 3 - 1
assira.core/src/test/java/net/ranides/assira/reflection/mockup/ForFields.java

@@ -82,9 +82,11 @@ public class ForFields {
         
         public String name = "R.";
 
+        public final Number frozen = new Integer(11);
+
         @Override
         public String toString() {
-            return super.toString()+"#{" + rid + ":" + pid + ":" + name + '}';
+            return super.toString()+"#{" + rid + ":" + pid + ":" + name + ":" + frozen +  "}";
         }