Add arguments validation to Java APIs.
authorChanhee Lee <ch2102.lee@samsung.com>
Thu, 21 Oct 2021 05:59:19 +0000 (14:59 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Thu, 28 Oct 2021 10:48:14 +0000 (19:48 +0900)
[Problem] There are not arguments validation in some Java APIs.
[Solution] Add null-checks and other validation logics to Java APIs.

* Add exceptions to Java class constructors.

* Synchronize the return type of setEventListener.

* Synchronize return types of Java functions.

* Add instance null-checkings to all Java APIs.

* Apply NonNull annotation.

* Apply PowerMock to handle static initialization blocks.

Change-Id: I978e78ab2028a0acdfdf1cf398485ffd81e5db89

20 files changed:
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/AuthenticatorUnitTest/AuthenticatorUnitTest.java
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/DiscoveryUnitTest/DiscoveryActivationUnitTest.java
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/DiscoveryUnitTest/DiscoveryCallbackUnitTest.java
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/DiscoveryUnitTest/DiscoveryConstructionUnitTest.java
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/DiscoveryUnitTest/DiscoveryItemUnitTest.java
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/InferenceUnitTest/InferencePeerUnitTest.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/EventListener.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/NativeInstance.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/NativeResourceManager.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/authenticator/Authenticator.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/discovery/Discovery.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/InferenceHandler.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/InferenceModuleFactory.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/Peer.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/TensorOutputCallback.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/tensor/Tensor.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/tensor/TensorHandler.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/tensor/TensorInfo.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/tensor/TensorSet.java
subprojects/libbeyond-android/src/test/java/com/samsung/android/beyond/InferenceModuleFactoryUnitTest.java

index 03d3b93fc466f2465a34ffa345bd730b021c5849..c76cc53e628d3a674d50fb199b5fd4dd33cde007 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.samsung.android.beyond;
+package com.samsung.android.beyond.AuthenticatorUnitTest;
 
 import android.content.Context;
 import android.os.Looper;
@@ -22,6 +22,7 @@ import android.os.Looper;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.samsung.android.beyond.ConfigType;
 import com.samsung.android.beyond.authenticator.Authenticator;
 import com.samsung.android.beyond.module.authenticator.SSL.SSLModule;
 
@@ -33,6 +34,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import static android.os.Looper.myLooper;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 @RunWith(AndroidJUnit4.class)
 public class AuthenticatorUnitTest {
@@ -49,7 +51,7 @@ public class AuthenticatorUnitTest {
     public void testPositiveCreate()
     {
         String[] args = {
-                SSLModule.NAME
+            SSLModule.NAME
         };
         Authenticator auth = new Authenticator(args);
         assertNotNull(auth);
@@ -60,12 +62,13 @@ public class AuthenticatorUnitTest {
     public void testPositiveConfigure()
     {
         String[] args = {
-                SSLModule.NAME
+            SSLModule.NAME
         };
         Authenticator auth = new Authenticator(args);
         assertNotNull(auth);
-        int ret = auth.configure(ConfigType.JSON, "{'hello':'world'}");
-        assertEquals(ret, -22);
+
+        assertTrue(auth.configure(ConfigType.JSON, "{\"hello\":\"world\"}"));
+
         auth.close();
     }
 
@@ -73,17 +76,15 @@ public class AuthenticatorUnitTest {
     public void testPositivePrepare()
     {
         String[] args = {
-                SSLModule.NAME,
+            SSLModule.NAME,
         };
         Authenticator auth = new Authenticator(args);
         assertNotNull(auth);
-
         auth.activate();
 
         auth.prepare();
 
         auth.deactivate();
-
         auth.close();
     }
 
@@ -91,7 +92,7 @@ public class AuthenticatorUnitTest {
     public void testPositiveDestructor()
     {
         String[] args = {
-                SSLModule.NAME,
+            SSLModule.NAME,
         };
 
         for (int i = 0; i < 10; i++) {
@@ -109,46 +110,34 @@ public class AuthenticatorUnitTest {
 
             }
         }
-
-
     }
 
     @Test
     public void testPositivePrepareCA()
     {
-        int ret;
         String[] args = {
-                SSLModule.NAME,
+            SSLModule.NAME,
         };
 
         Authenticator auth;
         auth = new Authenticator(args);
         assertNotNull(auth);
-        ret = auth.configure(ConfigType.JSON, "{\"ssl\": {\"bits\":-1,\"days\":365,\"serial\": 1,\"enable_base64\": 1,\"is_ca\": 1}}");
-        assertEquals(ret, 0);
-        ret = auth.activate();
-        assertEquals(ret, 0);
-        ret = auth.prepare();
-        assertEquals(ret, 0);
+        assertTrue(auth.configure(ConfigType.JSON, "{\"ssl\": {\"bits\":-1,\"days\":365,\"serial\": 1,\"enable_base64\": 1,\"is_ca\": 1}}"));
+        assertTrue(auth.activate());
+        assertTrue(auth.prepare());
 
         Authenticator authEE;
         authEE = new Authenticator(args);
         assertNotNull(authEE);
-        ret = authEE.configure(ConfigType.AUTHENTICATOR, auth);
-        assertEquals(ret, 0);
-        ret = authEE.configure(ConfigType.JSON, "{\"ssl\": {\"bits\":-1,\"days\":365,\"serial\": 1,\"enable_base64\": 1,\"is_ca\": 0}}");
-        assertEquals(ret, 0);
-        ret = authEE.activate();
-        assertEquals(ret, 0);
-        ret = authEE.prepare();
-        assertEquals(ret, 0);
-
-        ret = authEE.deactivate();
-        assertEquals(ret, 0);
+        assertTrue(authEE.configure(ConfigType.AUTHENTICATOR, auth));
+        assertTrue(authEE.configure(ConfigType.JSON, "{\"ssl\": {\"bits\":-1,\"days\":365,\"serial\": 1,\"enable_base64\": 1,\"is_ca\": 0}}"));
+        assertTrue(authEE.activate());
+        assertTrue(authEE.prepare());
+
+        assertTrue(authEE.deactivate());
         authEE.close();
 
-        ret = auth.deactivate();
-        assertEquals(ret, 0);
+        assertTrue(auth.deactivate());
         auth.close();
     }
 
@@ -158,8 +147,8 @@ public class AuthenticatorUnitTest {
         Looper.prepare();
 
         String[] args = {
-                SSLModule.NAME,
-                SSLModule.ARGUMENT_ASYNC_MODE,
+            SSLModule.NAME,
+            SSLModule.ARGUMENT_ASYNC_MODE,
         };
         Authenticator auth = new Authenticator(args);
         assertNotNull(auth);
index 5642d0c6f8e9970fdc6555ada618ba2642999620..2f748b8a441cf007c5dc10827c779514ed1aa52d 100644 (file)
@@ -28,7 +28,9 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 public class DiscoveryActivationUnitTest {
     Context context = ApplicationProvider.getApplicationContext();
@@ -45,8 +47,9 @@ public class DiscoveryActivationUnitTest {
         String[] args_server = { DNSSDModule.NAME, DNSSDModule.ARGUMENT_SERVER };
         try (Discovery server = new Discovery(context, args_server)) {
             assertNotNull(server);
-            int ret = server.activate();
-            assertEquals(0, ret);
+
+            assertTrue(server.activate());
+
             server.deactivate();
         }
     }
@@ -56,27 +59,30 @@ public class DiscoveryActivationUnitTest {
         String[] args_client = { DNSSDModule.NAME };
         try (Discovery client = new Discovery(context, args_client)) {
             assertNotNull(client);
-            int ret = client.activate();
-            assertEquals(0, ret);
+
+            assertTrue(client.activate());
+
             client.deactivate();
         }
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testActivateAfterClosed() {
         String[] args_client = { DNSSDModule.NAME };
         Discovery client = new Discovery(context, args_client);
         assertNotNull(client);
         client.close();
-        client.activate();
+
+        assertFalse(client.activate());
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testDeactivateAfterClosed() {
         String[] args_client = { DNSSDModule.NAME };
         Discovery client = new Discovery(context, args_client);
         assertNotNull(client);
         client.close();
-        client.deactivate();
+
+        assertFalse(client.deactivate());
     }
 }
index ea1a02ea698d638391e7c75a71edebdc067de579..57db827061a1677bfe247b2b45354e6cb473fa93 100644 (file)
@@ -18,6 +18,7 @@ package com.samsung.android.beyond.DiscoveryUnitTest;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
 import android.os.Looper;
@@ -56,8 +57,7 @@ public class DiscoveryCallbackUnitTest {
                 assertEquals(1, invoked.get());
                 Looper.myLooper().quit();
             });
-            int ret = server.activate();
-            assertEquals(0, ret);
+            assertTrue(server.activate());
 
             Looper.loop();
 
index b40997c9351ce5a6b7c027f6c1193edd5ed53139..ef9ea5895b22bd97a4b13f66b80162b4370f6098 100644 (file)
@@ -54,7 +54,7 @@ public class DiscoveryConstructionUnitTest {
         }
     }
 
-    @Test(expected = IllegalArgumentException.class)
+    @Test(expected = NullPointerException.class)
     public void testCreateWithNullArgs() {
         try (Discovery inst = new Discovery(context, null)) {
         }
index ec4ed76ade604dda9e78285d5727f74581a8a516..c2a3c2b48c3b2e1cd456f8f3cc0f4f026e4e4d7f 100644 (file)
@@ -7,13 +7,14 @@ import androidx.test.core.app.ApplicationProvider;
 
 import com.samsung.android.beyond.discovery.Discovery;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import com.samsung.android.beyond.module.discovery.DNSSD.DNSSDModule;
 
 public class DiscoveryItemUnitTest {
@@ -31,14 +32,11 @@ public class DiscoveryItemUnitTest {
         String[] args_server = { DNSSDModule.NAME, DNSSDModule.ARGUMENT_SERVER };
         try (Discovery server = new Discovery(context, args_server)) {
             assertNotNull(server);
-
-            int ret = server.activate();
-            assertEquals(0, ret);
+            assertTrue(server.activate());
 
             String key = "key";
             byte[] value = "hello".getBytes();
-            ret = server.setItem(key, value);
-            assertEquals(0, ret);
+            assertTrue(server.setItem(key, value));
 
             server.deactivate();
         }
@@ -49,21 +47,18 @@ public class DiscoveryItemUnitTest {
         String[] args_server = { DNSSDModule.NAME, DNSSDModule.ARGUMENT_SERVER };
         try (Discovery server = new Discovery(context, args_server)) {
             assertNotNull(server);
-            int ret = server.activate();
-            assertEquals(0, ret);
+            assertTrue(server.activate());
             String key = "key";
             byte[] value = "hello".getBytes();
-            ret = server.setItem(key, value);
-            assertEquals(0, ret);
+            assertTrue(server.setItem(key, value));
 
-            ret = server.removeItem(key);
-            assertEquals(0, ret);
+            assertTrue(server.removeItem(key));
 
             server.deactivate();
         }
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testSetItemAfterClosed() {
         String[] args_server = { DNSSDModule.NAME, DNSSDModule.ARGUMENT_SERVER };
         Discovery server = new Discovery(context, args_server);
@@ -72,10 +67,10 @@ public class DiscoveryItemUnitTest {
 
         String key = "key";
         byte[] value = "hello".getBytes();
-        server.setItem(key, value);
+        assertFalse(server.setItem(key, value));
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testRemoveItemAfterClosed() {
         String[] args_server = { DNSSDModule.NAME, DNSSDModule.ARGUMENT_SERVER };
         Discovery server = new Discovery(context, args_server);
@@ -83,6 +78,6 @@ public class DiscoveryItemUnitTest {
         server.close();
 
         String key = "key";
-        server.removeItem(key);
+        assertFalse(server.removeItem(key));
     }
 }
index 661e9282b44ddf8d563c5b916896da3bed94aa0d..2822a3a35e0f4ce1ec6efe3a566fee74d872c06c 100644 (file)
@@ -85,10 +85,8 @@ public class InferencePeerUnitTest {
         Authenticator auth = new Authenticator(args);
         assertNotNull(auth);
 
-        int ret = auth.activate();
-        assertEquals(ret, 0);
-        ret = auth.prepare();
-        assertEquals(ret, 0);
+        assertTrue(auth.activate());
+        assertTrue(auth.prepare());
 
         inferencePeer = InferenceModuleFactory.createPeerServer(context, NNModule.NAME);
         assertNotNull(inferencePeer);
index a7d4c068d56a47160e5d487ca1f479492511a60f..7be393f94b791a38be69bec1cd6fb2dd5bc2735e 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.samsung.android.beyond;
 
+import androidx.annotation.NonNull;
+
 public interface EventListener {
-    public void onEvent(EventObject eventObject);
+    public void onEvent(@NonNull EventObject eventObject);
 }
index 062d0f8dab383035146449f07a5d6aee284a9f90..4ea42d58bf370678c3fa563b4e73863e6c20b3d1 100644 (file)
@@ -18,6 +18,8 @@ package com.samsung.android.beyond;
 
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import java.util.function.Consumer;
 
 public abstract class NativeInstance implements AutoCloseable {
@@ -31,7 +33,7 @@ public abstract class NativeInstance implements AutoCloseable {
         private long nativeInstance;
         private Consumer<Long> function;
 
-        public Destructor(long instance, Consumer<Long> function) {
+        public Destructor(@NonNull long instance, @NonNull Consumer<Long> function) {
             nativeInstance = instance;
             this.function = function;
         }
@@ -55,7 +57,7 @@ public abstract class NativeInstance implements AutoCloseable {
     protected long instance;
     private Destructor destructor;
 
-    protected void registerNativeInstance(long nativeInstance, Consumer<Long> function) {
+    protected void registerNativeInstance(@NonNull long nativeInstance, @NonNull Consumer<Long> function) {
         instance = nativeInstance;
         destructor = new Destructor(instance, function);
         NativeResourceManager.register(this, destructor);
index 94586344d7055f25b3b43009a390d8204d13c809..d2cb7941139ba1f433e5c4342b2f8601f6e9b894 100644 (file)
@@ -18,6 +18,8 @@ package com.samsung.android.beyond;
 
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import java.lang.ref.*;
 import java.lang.Thread;
 import java.util.HashMap;
@@ -62,7 +64,7 @@ public class NativeResourceManager {
         manager.start();
     }
 
-    public static void register(Object object, Destroyable info) {
+    static void register(@NonNull Object object, @NonNull Destroyable info) {
         instance.referenceMap.put(new PhantomReference<>(object, instance.queue), info);
     }
 }
index ed679cb796edd13815d597839ea21fd2c28bf396..2f77be9a57da3d38072e0bc29c2a4e9338667074 100644 (file)
@@ -18,6 +18,8 @@ package com.samsung.android.beyond.authenticator;
 
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import com.samsung.android.beyond.EventListener;
 import com.samsung.android.beyond.EventObject;
 import com.samsung.android.beyond.NativeInstance;
@@ -31,58 +33,109 @@ public class Authenticator extends NativeInstance {
     public class DefaultEventObject extends EventObject {
     }
 
+    private EventListener eventListener;
     private static final String TAG = "BEYOND_ANDROID_AUTH";
 
-    public Authenticator(String[] arguments) {
-        registerNativeInstance(create(arguments), (Long instance) -> destroy(instance));
+    public Authenticator(@NonNull String[] arguments) {
+        if (arguments.length == 0) {
+            throw new IllegalArgumentException("Arguments are invalid.");
+        }
+
+        long nativeInstance = create(arguments);
+        if (nativeInstance == 0L) {
+            throw new RuntimeException("The native instance of Authenticator is not created successfully.");
+        }
+        registerNativeInstance(nativeInstance, (Long instance) -> destroy(instance));
         Log.d(TAG, "Authenticator created");
     }
 
-    public void setEventListener(EventListener eventListener) {
-        if (this.setEventListener(instance, eventListener) < 0) {
-            // TODO: throw an exception
+    public boolean setEventListener(@NonNull EventListener eventListener) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        this.eventListener = eventListener;
+        if (setEventListener(instance, eventListener) < 0) {
+            Log.e(TAG, "Fail to set the given event listener.");
+            return false;     // TODO: Change as an exception
         }
+
+        return true;
     }
 
-    public int configure(char type, String jsonString) {
-        return this.configure(instance, type, jsonString);
+    public boolean configure(@NonNull char type, @NonNull String jsonString) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        if (Character.isDefined(type) == false) {
+            Log.e(TAG, "Arguments are invalid.");
+            return false;
+        }
+
+        return configure(instance, type, jsonString) == 0 ? true : false;
     }
 
-    public int configure(char type, Object obj) {
+    public boolean configure(@NonNull char type, @NonNull Object obj) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        if (Character.isDefined(type) == false) {
+            Log.e(TAG, "Arguments are invalid.");
+            return false;
+        }
+
         if (type == ConfigType.CONTEXT_ANDROID) {
             if (obj.getClass().getName().equals("android.app.Application") == true) {
-                return this.configure(instance, type, obj);
+                return configure(instance, type, obj) == 0 ? true : false;
             }
 
-            // TODO:
-            // The error code should be declared or the function should generate a proper exception
-            return -22;
+            // TODO: the function can generate a proper exception
+            return false;
         }
 
         if (type == ConfigType.JSON) {
-            // TODO:
-            // The error code should be declared or the function should generate a proper exception
-            return -22;
+            // TODO: the function can generate a proper exception
+            return false;
         }
 
         try {
             NativeInstance nativeInstance = (NativeInstance)obj;
-            return this.configure(instance, type, nativeInstance.getNativeInstance());
+            return configure(instance, type, nativeInstance.getNativeInstance()) == 0 ? true : false;
         } catch (ClassCastException e) {
-            return this.configure(instance, type, obj);
+            return configure(instance, type, obj) == 0 ? true : false;
         }
     }
 
-    public int deactivate() {
-        return this.deactivate(instance);
+    public boolean deactivate() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        return deactivate(instance) == 0 ? true : false;
     }
 
-    public int activate() {
-        return this.activate(instance);
+    public boolean activate() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        return activate(instance) == 0 ? true: false;
     }
 
-    public int prepare() {
-        return this.prepare(instance);
+    public boolean prepare() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        return this.prepare(instance) == 0 ? true: false;
     }
 
     private static native void initialize();
index df9880b13c0066fcfa76849e510ece6dcf1a50ca..f3677e1e37bcf0874a247d3f7d6a73530a489e80 100644 (file)
@@ -19,6 +19,8 @@ package com.samsung.android.beyond.discovery;
 import android.util.Log;
 import android.content.Context;
 
+import androidx.annotation.NonNull;
+
 import com.samsung.android.beyond.EventListener;
 import com.samsung.android.beyond.EventObject;
 import com.samsung.android.beyond.NativeInstance;
@@ -39,70 +41,104 @@ public class Discovery extends NativeInstance {
     public class DefaultEventObject extends EventObject {
     }
 
+    private EventListener eventListener;
     private static final String TAG = "BEYOND_ANDROID_DISCOVERY";
 
-    public Discovery(Context context, String[] arguments) {
-        if (context == null || arguments == null || arguments.length == 0) {
+    public Discovery(@NonNull Context context, @NonNull String[] arguments) {
+        if (arguments.length == 0) {
             throw new IllegalArgumentException("There is no argument");
         }
 
-        registerNativeInstance(create(arguments), (Long instance) -> destroy(instance));
+        long nativeInstance = create(arguments);
+        if (nativeInstance == 0L) {
+            throw new RuntimeException("The native instance of Discovery is not created successfully.");
+        }
+        registerNativeInstance(nativeInstance, (Long instance) -> destroy(instance));
 
-        if (this.configure(ConfigType.CONTEXT_ANDROID, context) != 0) {
-            Log.e(TAG, "Failed to configure the android context");
+        if (configure(ConfigType.CONTEXT_ANDROID, context) == false) {
+            throw new RuntimeException("Failed to configure the android context");
         }
+
+        eventListener = null;
     }
 
-    public int activate() {
-        if (instance == 0) {
-            throw new IllegalStateException();
+    public boolean activate() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
         }
 
-        return activate(instance);
+        return activate(instance) == 0 ? true : false;
     }
 
-    public int deactivate() {
-        if (instance == 0) {
-            throw new IllegalStateException();
+    public boolean deactivate() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
         }
 
-        return deactivate(instance);
+        return deactivate(instance) == 0 ? true: false;
     }
 
-    public int setItem(String key, byte[] value) {
-        if (instance == 0) {
-            throw new IllegalStateException();
+    public boolean setItem(@NonNull String key, @NonNull byte[] value) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid now.");
+            return false;
         }
 
-        return setItem(instance, key, value);
+        if (value.length == 0) {
+            Log.e(TAG, "Arguments are invalid.");
+            return false;
+        }
+
+        return setItem(instance, key, value) == 0 ? true : false;
     }
 
-    public int removeItem(String key) {
-        if (instance == 0) {
-            throw new IllegalStateException();
+    public boolean removeItem(@NonNull String key) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid now.");
+            return false;
         }
 
-        return removeItem(instance, key);
+        return removeItem(instance, key) == 0 ? true : false;
     }
 
-    public int configure(char type, Object obj) {
+    public boolean configure(@NonNull char type, @NonNull Object obj) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        if (Character.isDefined(type) == false) {
+            Log.e(TAG, "Arguments are invalid.");
+            return false;
+        }
+
         if (type == ConfigType.CONTEXT_ANDROID) {
             if (obj.getClass().getName().equals("android.app.Application") == true) {
-                return this.configure(instance, type, obj);
+                return configure(instance, type, obj) == 0 ? true : false;
             }
 
-            // TODO:
-            // This function should generate a proper exception
-            return -22;
+            // TODO: This function can generate a proper exception
+            return false;
         }
 
-        return -22;
+        return true;
     }
 
-    public void setEventListener(EventListener eventListener) {
-        if (setEventListener(instance, eventListener) < 0) {
-            // TODO: throw an exception
+    public boolean setEventListener(@NonNull EventListener eventListener) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
         }
+
+        this.eventListener = eventListener;
+        if (setEventListener(instance, this.eventListener) < 0) {
+            Log.e(TAG, "Fail to set the given event listener.");
+            return false;     // TODO: Change as an exception
+        }
+
+        return true;
     }
 
     private static native void initialize();
index 317a51243777b6f5aeca52dad9cb66bf0cee993a..c4f1088c31ed57fcf66ec4dac90abeabd0a0943f 100644 (file)
@@ -23,40 +23,74 @@ import com.samsung.android.beyond.NativeInstance;
 
 import static com.samsung.android.beyond.inference.Option.TAG;
 
+import androidx.annotation.NonNull;
+
 public class InferenceHandler extends NativeInstance {
 
     private TensorOutputCallback tensorOutputCallback;
 
-    InferenceHandler(InferenceMode inferenceMode) {
-        long handle = nativeCreateInference(inferenceMode.toString());
-        if (handle == 0L) {
-            throw new RuntimeException("Fail to create a native instance for InferenceHandler.");
+    InferenceHandler(@NonNull InferenceMode inferenceMode) {
+        long nativeInstance = nativeCreateInference(inferenceMode.toString());
+        if (nativeInstance == 0L) {
+            throw new RuntimeException("The native instance of InferenceHandler is not created successfully.");
         }
-        registerNativeInstance(handle, (Long instance) -> destroy(instance));
+
+        registerNativeInstance(nativeInstance, (Long instance) -> destroy(instance));
     }
 
-    public boolean addInferencePeer(Peer inferencePeer) {
+    public boolean addInferencePeer(@NonNull Peer inferencePeer) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        if (inferencePeer.getNativeInstance() == 0L) {
+            Log.e(TAG, "The given peer instance is invalid.");
+            return false;
+        }
+
         return addPeer(instance, inferencePeer.getNativeInstance());
     }
 
-    public boolean loadModel(String modelPath) {
+    public boolean loadModel(@NonNull String modelPath) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
         Log.i(TAG, "Model path in a client : " + modelPath);
         return loadModel(instance, modelPath);
     }
 
     public boolean prepare() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
         return prepare(instance);
     }
 
-    public boolean run(TensorSet inputTensors) {
+    public boolean run(@NonNull TensorSet inputTensors) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        if (inputTensors.getTensorsInstance() == 0L) {
+            Log.e(TAG, "The given tensor set is invalid.");
+            return false;
+        }
+
         return run(instance, inputTensors.getTensorsInstance(), inputTensors.getTensors().length);
     }
 
-    public boolean setOutputCallback(TensorOutputCallback tensorOutputCallback) {
-        if (tensorOutputCallback == null) {
-            Log.e(TAG, "Output callback is null.");
+    public boolean setOutputCallback(@NonNull TensorOutputCallback tensorOutputCallback) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
             return false;
         }
+
         this.tensorOutputCallback = tensorOutputCallback;
 
         if (setCallback(instance, tensorOutputCallback) < 0) {
index 0d6da4183c77e71ba6affb101d52b24f31912bb1..d28bb5a9b2c2584136ef1ca293ba7a4dd6ac548f 100644 (file)
@@ -18,29 +18,19 @@ package com.samsung.android.beyond.inference;
 
 import android.content.Context;
 
-public class InferenceModuleFactory {
+import androidx.annotation.NonNull;
 
-    public static InferenceHandler createHandler(InferenceMode inferenceMode) {
-        if (inferenceMode == null) {
-            throw new IllegalArgumentException("inferenceMode is null.");
-        }
+public class InferenceModuleFactory {
 
+    public static InferenceHandler createHandler(@NonNull InferenceMode inferenceMode) {
         return new InferenceHandler(inferenceMode);
     }
 
-    public static Peer createPeerServer(Context context, String peerType) {
-        if (context == null || peerType == null) {
-            throw new IllegalArgumentException("Arguments are not correct.");
-        }
-
+    public static Peer createPeerServer(@NonNull Context context, @NonNull String peerType) {
         return new Peer(context, peerType, NodeType.SERVER);
     }
 
-    public static Peer createPeerClient(Context context, String peerType) {
-        if (context == null || peerType == null) {
-            throw new IllegalArgumentException("Arguments are not correct.");
-        }
-
+    public static Peer createPeerClient(@NonNull Context context, @NonNull String peerType) {
         return new Peer(context, peerType, NodeType.CLIENT);
     }
 }
index 1b3ba5618d1e056a5560b0fd86d2b9f4257c30f0..59b3a66a24979ae0759d569d0a5eed147726f9b4 100644 (file)
 
 package com.samsung.android.beyond.inference;
 
+import androidx.annotation.NonNull;
+
 import android.content.Context;
 import android.util.Log;
 
 import java.util.regex.Pattern;
-import java.nio.ByteBuffer;
 
 import com.samsung.android.beyond.EventListener;
 import com.samsung.android.beyond.NativeInstance;
 import com.samsung.android.beyond.ConfigType;
 import static com.samsung.android.beyond.inference.Option.TAG;
 
-import static com.samsung.android.beyond.inference.Option.TAG;
-
 public class Peer extends NativeInstance {
     static {
         initialize();
@@ -44,7 +43,7 @@ public class Peer extends NativeInstance {
 
         public Info() {}
 
-        public Info(String host, int port) {
+        public Info(@NonNull String host, int port) {
             this.host = host;
             this.port = port;
         }
@@ -52,7 +51,7 @@ public class Peer extends NativeInstance {
 
     private EventListener eventListener;
 
-    Peer(Context context, String peerType, NodeType nodeType) {
+    Peer(@NonNull Context context, @NonNull String peerType, @NonNull NodeType nodeType) {
         switch (nodeType) {
             case SERVER:
                 String[] serverConfiguration = new String[4];
@@ -74,19 +73,24 @@ public class Peer extends NativeInstance {
                 break;
         }
 
-        if (instance == 0) {
+        if (instance == 0L) {
             Log.e(TAG, "Fail to create a native peer");
             return;
         }
 
         registerNativeInstance(instance, (Long instance) -> destroy(instance));
 
-        if (this.configure(instance, ConfigType.CONTEXT_ANDROID, context) == false) {
+        if (configure(instance, ConfigType.CONTEXT_ANDROID, context) == false) {
             Log.e(TAG, "Unable to set the android context");
         }
     }
 
-    public boolean setIPPort(String IP, int port) {
+    public boolean setIPPort(@NonNull String IP, int port) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
         if (validateIPv4(IP) == false || port < 0) {
             Log.e(TAG, "Arguments are invalid.");
             return false;
@@ -95,17 +99,18 @@ public class Peer extends NativeInstance {
         return setInfo(instance, new Info(IP, port));
     }
 
-    private boolean validateIPv4(String IP) {
-        if (IP == null) {
-            Log.e(TAG, "IP is null.");
-        }
-
+    private boolean validateIPv4(@NonNull String IP) {
         String regexIPv4 = "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$";
         Pattern pattern = Pattern.compile(regexIPv4);
         return pattern.matcher(IP).matches();
     }
 
     public boolean setInfo() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
         Info info = new Info();
         info.host = "0.0.0.0";
         info.port = 3000;
@@ -113,20 +118,40 @@ public class Peer extends NativeInstance {
         return setInfo(instance, info);
     }
 
-    public boolean setInfo(Info info) {
+    public boolean setInfo(@NonNull Info info) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
         return setInfo(instance, info);
     }
 
     public Info getInfo() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return null;
+        }
+
         return getInfo(instance);
     }
 
     public boolean activateControlChannel() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
         return activate(instance);
     }
 
-    public boolean configure(char type, Object obj) {
-        if (Character.isDefined(type) == false || obj == null) {
+    public boolean configure(@NonNull char type, @NonNull Object obj) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
+        if (Character.isDefined(type) == false) {
             Log.e(TAG, "Arguments are invalid.");
             return false;
         }
@@ -142,14 +167,20 @@ public class Peer extends NativeInstance {
     }
 
     public boolean deactivateControlChannel() {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
+            return false;
+        }
+
         return deactivate(instance);
     }
 
-    public boolean registerEventListener(EventListener eventListener) {
-        if (eventListener == null) {
-            Log.e(TAG, "Output callback is null.");
+    public boolean registerEventListener(@NonNull EventListener eventListener) {
+        if (instance == 0L) {
+            Log.e(TAG, "Instance is invalid.");
             return false;
         }
+
         this.eventListener = eventListener;
 
         if (setEventListener(instance, eventListener) < 0) {
index ba02387abf55eb213c04921d0dc21c9918800775..14b03d69021b8f172bc5cb878fdd101b428e0952 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.samsung.android.beyond.inference;
 
+import androidx.annotation.NonNull;
+
 import com.samsung.android.beyond.inference.tensor.TensorHandler;
 import com.samsung.android.beyond.inference.tensor.TensorInfo;
 import com.samsung.android.beyond.inference.tensor.TensorSet;
@@ -31,7 +33,7 @@ public class TensorOutputCallback extends OutputCallback {
 
     public TensorOutputCallback() {}
 
-    public TensorOutputCallback(TensorHandler tensorHandler, TensorInfo[] tensorInfoArray) {
+    public TensorOutputCallback(@NonNull TensorHandler tensorHandler, @NonNull TensorInfo[] tensorInfoArray) {
         this.tensorHandler = tensorHandler;
         this.tensorInfoArray = tensorInfoArray;
         byteBufferArray = new ByteBuffer[tensorInfoArray.length];
@@ -45,7 +47,7 @@ public class TensorOutputCallback extends OutputCallback {
         return tensorSet;
     }
 
-    public void organizeTensorSet(long instance) {
+    public void organizeTensorSet(@NonNull long instance) {
         tensorSet = tensorHandler.createTensorSet(instance, tensorInfoArray, byteBufferArray);
     }
 
index 64e390f1b0ccfcdade69e828f1fc1f28ffcfa066..1548e1896a1dc60cd6744b9fd7e7c83cb23a9823 100644 (file)
@@ -10,6 +10,8 @@ import java.util.Map;
 
 import static com.samsung.android.beyond.inference.Option.TAG;
 
+import androidx.annotation.NonNull;
+
 public class Tensor<T> {
 
     private final TensorInfo tensorInfo;
@@ -18,17 +20,12 @@ public class Tensor<T> {
 
     private ByteBuffer buffer;
 
-    protected Tensor(Class<T> classType, TensorInfo tensorInfo) {
+    protected Tensor(@NonNull Class<T> classType, @NonNull TensorInfo tensorInfo) {
         this.classType = classType;
         this.tensorInfo = tensorInfo;
     }
 
-    public boolean setData(Buffer dataBuffer) {
-        if (dataBuffer == null) {
-            Log.e(TAG, "The given dataBuffer is null.");
-            return false;
-        }
-
+    public boolean setData(@NonNull Buffer dataBuffer) {
         try {
             switch (getTensorInfo().getDataType()) {
                 case UINT8:
@@ -98,12 +95,7 @@ public class Tensor<T> {
         return tensorInfo;
     }
 
-    protected boolean setBuffer(ByteBuffer buffer) {
-        if (buffer == null) {
-            Log.e(TAG, "The given data is null.");
-            return false;
-        }
-
+    protected boolean setBuffer(@NonNull ByteBuffer buffer) {
         this.buffer = buffer;
         this.buffer.clear();
 
@@ -114,7 +106,7 @@ public class Tensor<T> {
         return buffer;
     }
 
-    public static DataType fromClass(Class<?> c) {
+    private static DataType fromClass(@NonNull Class<?> c) {
         DataType dataType = typeCodes.get(c);
         if (dataType == null) {
             throw new IllegalArgumentException(
@@ -123,7 +115,7 @@ public class Tensor<T> {
         return dataType;
     }
 
-    public static Class<?> fromValue(DataType dataType) {
+    static Class<?> fromValue(@NonNull DataType dataType) {
         for (Class<?> classType : typeCodes.keySet()) {
             if (dataType.equals(fromClass(classType))) {
                 return classType;
index 6212e90f94d1b4936e540f8647a9b35396e738cf..5e9ae869138428ff6f821471fe3b1b870bbfa69e 100644 (file)
@@ -10,11 +10,13 @@ import java.util.List;
 
 import static com.samsung.android.beyond.inference.Option.TAG;
 
+import androidx.annotation.NonNull;
+
 public class TensorHandler {
 
     private final InferenceHandler inferenceHandler;
 
-    public TensorHandler(InferenceHandler inferenceHandler) {
+    public TensorHandler(@NonNull InferenceHandler inferenceHandler) {
         this.inferenceHandler = inferenceHandler;
     }
 
@@ -53,7 +55,7 @@ public class TensorHandler {
         return tensorInfoArray;
     }
 
-    private boolean organizeTensorsInfo(TensorInfo[] tensorInfoArray, List<Integer> dataTypeValues, List<List<Integer>> dimensionsList) {
+    private boolean organizeTensorsInfo(@NonNull TensorInfo[] tensorInfoArray, @NonNull List<Integer> dataTypeValues, @NonNull List<List<Integer>> dimensionsList) {
         if (dataTypeValues.size() != dimensionsList.size()) {
             Log.e(TAG, "The number of tensors is abnormal.");
             return false;
@@ -80,18 +82,17 @@ public class TensorHandler {
         return true;
     }
 
-    public TensorSet allocateTensorSet(TensorInfo[] tensorInfoArray) {
+    public TensorSet allocateTensorSet(@NonNull TensorInfo[] tensorInfoArray) {
         ByteBuffer[] bufferArray = new ByteBuffer[tensorInfoArray.length];
         long tensorsInstance = allocateTensors(inferenceHandler.getNativeInstance(), tensorInfoArray, tensorInfoArray.length, bufferArray);
         if (tensorsInstance == 0L) {
-            Log.e(TAG, "Fail to allocate the buffers of tensors.");
-            return null;
+            throw new RuntimeException("Fail to allocate the buffers of tensors.");
         }
 
         return organizeTensorSet(tensorsInstance, tensorInfoArray, bufferArray);
     }
 
-    private TensorSet organizeTensorSet(long tensorsInstance, TensorInfo[] tensorInfoArray, ByteBuffer[] bufferArray) {
+    private TensorSet organizeTensorSet(@NonNull long tensorsInstance, @NonNull TensorInfo[] tensorInfoArray, @NonNull ByteBuffer[] bufferArray) {
         Tensor[] tensorArray = new Tensor[tensorInfoArray.length];
         for (int i = 0; i < tensorInfoArray.length; i++) {
             TensorInfo tensorInfo = tensorInfoArray[i];
@@ -111,20 +112,22 @@ public class TensorHandler {
         return tensorSet;
     }
 
-    public TensorSet getOutput(TensorInfo[] tensorInfoArray) {
+    public TensorSet getOutput(@NonNull TensorInfo[] tensorInfoArray) {
         ByteBuffer[] bufferArray = new ByteBuffer[tensorInfoArray.length];
         long tensorsInstance = getOutput(inferenceHandler.getNativeInstance(), bufferArray);
+        if (tensorsInstance == 0L) {
+            throw new RuntimeException("Fail to get output tensors.");
+        }
 
         return organizeTensorSet(tensorsInstance, tensorInfoArray, bufferArray);
     }
 
-    public int freeTensors(TensorSet tensorSet) {
+    public void freeTensors(@NonNull TensorSet tensorSet) {
         freeTensors(inferenceHandler.getNativeInstance(), tensorSet.getTensorsInstance(), tensorSet.getTensors().length);
-        return 0;
     }
 
-    public TensorSet createTensorSet(long tensorsInstance, TensorInfo[] tensorInfoArray, ByteBuffer[] bufferArray) {
-        if (tensorsInstance == 0L || tensorInfoArray == null || bufferArray == null) {
+    public TensorSet createTensorSet(@NonNull long tensorsInstance, @NonNull TensorInfo[] tensorInfoArray, @NonNull ByteBuffer[] bufferArray) {
+        if (tensorInfoArray.length == 0 || bufferArray.length == 0) {
             throw new IllegalArgumentException("Arguments are invalid.");
         }
 
index a0424a278be3f492d93dece3cf9308aaaa3ab236..c2ec2a35ae470d0848e2c0b63f769c88c98333a3 100644 (file)
@@ -4,6 +4,8 @@ import android.util.Log;
 
 import static com.samsung.android.beyond.inference.Option.TAG;
 
+import androidx.annotation.NonNull;
+
 import java.util.ArrayList;
 
 public class TensorInfo {
@@ -16,14 +18,14 @@ public class TensorInfo {
 
     private int dataByteSize;
 
-    TensorInfo(DataType dataType, int[] dimensions) {
+    TensorInfo(@NonNull DataType dataType, @NonNull int[] dimensions) {
         this.dataType = dataType;
         this.rank = dimensions.length;
         this.dimensions = dimensions;
         this.dataByteSize = calculateDataByteSize(dataType, dimensions);
     }
 
-    private int calculateDataByteSize(DataType dataType, int[] dimensions) {
+    private int calculateDataByteSize(@NonNull DataType dataType, @NonNull int[] dimensions) {
         int dataSize = dataType.getByteSize();
         for (int dimension : dimensions) {
             dataSize *= dimension;
index 0072d89510a2d3052a16ffdffb5987f25361c1c5..dfd7b7944c662b2ba2e5f0e3f3d188577b4e6a37 100644 (file)
@@ -6,13 +6,15 @@ import com.samsung.android.beyond.NativeInstance;
 
 import static com.samsung.android.beyond.inference.Option.TAG;
 
+import androidx.annotation.NonNull;
+
 public class TensorSet extends NativeInstance {
 
     private final long tensorsInstance;
 
     private Tensor[] tensors;
 
-    TensorSet(long tensorsInstance, TensorHandler tensorHandler) {
+    TensorSet(@NonNull long tensorsInstance, @NonNull TensorHandler tensorHandler) {
         this.tensorsInstance = tensorsInstance;
         registerNativeInstance(tensorsInstance, (Long instance) -> tensorHandler.freeTensors(this));
         Log.i(TAG, "Phantom Reference is set to a tensor set.");
@@ -26,7 +28,7 @@ public class TensorSet extends NativeInstance {
         return tensors;
     }
 
-    void setTensors(Tensor[] tensors) {
+    void setTensors(@NonNull Tensor[] tensors) {
         this.tensors = tensors;
     }
 }
index 62f4e4430595a7583fa320780a8399653eb59e58..f91a9a380005b86f12b0e616536c29ff17f1511b 100644 (file)
@@ -22,25 +22,28 @@ import com.samsung.android.beyond.inference.InferenceModuleFactory;
 import com.samsung.android.beyond.module.peer.NN.NNModule;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@SuppressStaticInitializationFor({"com.samsung.android.beyond.NativeInstance", "com.samsung.android.beyond.inference.Peer"})
 public class InferenceModuleFactoryUnitTest {
 
     private static Context context;
 
-    @Test(expected = IllegalArgumentException.class)
+    @Test(expected = NullPointerException.class)
     public void testCreateHandlerWithNullArgument() {
         InferenceModuleFactory.createHandler(null);
     }
 
-    @Test(expected = IllegalArgumentException.class)
-    public void testCreatePeerServerWithNullArguments() {
+    @Test(expected = NullPointerException.class)
+    public void testCreatePeerWithNullArguments() {
         InferenceModuleFactory.createPeerServer(context, null);
 
         InferenceModuleFactory.createPeerServer(null, NNModule.NAME);
-    }
 
-    @Test(expected = IllegalArgumentException.class)
-    public void testCreatePeerClientWithNullArgument() {
         InferenceModuleFactory.createPeerClient(context, null);
 
         InferenceModuleFactory.createPeerClient(null, NNModule.NAME);