1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.ravenwoodtest.bivalenttest;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.fail;
20 
21 import android.platform.test.ravenwood.RavenwoodRule;
22 import android.util.Log;
23 
24 import androidx.test.ext.junit.runners.AndroidJUnit4;
25 
26 import libcore.util.NativeAllocationRegistry;
27 
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 
32 @RunWith(AndroidJUnit4.class)
33 public class RavenwoodNativeAllocationRegistryTest {
34     private static final String TAG = RavenwoodNativeAllocationRegistryTest.class.getSimpleName();
35     static {
RavenwoodJniTest.initializeJni()36         RavenwoodJniTest.initializeJni();
37     }
38 
39     @Rule
40     public final RavenwoodRule mRavenwoodRule = new RavenwoodRule();
41 
42     private static class Data {
43         private final long mNativePtr;
44 
nMalloc(int value)45         private static native long nMalloc(int value);
nGet(long ptr)46         private static native int nGet(long ptr);
nGetNativeFinalizer()47         private static native long nGetNativeFinalizer();
48 
nGetTotalAlloc()49         public static native int nGetTotalAlloc();
50 
get()51         public int get() {
52             return nGet(mNativePtr);
53         }
54 
55         private static class NarHolder {
56             public static final NativeAllocationRegistry sRegistry =
57                     NativeAllocationRegistry.createMalloced(
58                             Data.class.getClassLoader(), nGetNativeFinalizer());
59         }
60 
Data(int value)61         public Data(int value) {
62             mNativePtr = nMalloc(value);
63             NarHolder.sRegistry.registerNativeAllocation(this, mNativePtr);
64         }
65     }
66 
67     @Test
testNativeAllocationRegistry()68     public void testNativeAllocationRegistry() {
69 
70         final long timeoutTime = mRavenwoodRule.realCurrentTimeMillis() + 10_000;
71 
72         final int startAlloc = Data.nGetTotalAlloc();
73 
74         int totalAlloc = 0;
75 
76         // Keep allocation new objects, until some get released.
77 
78         while (true) {
79             for (int i = 0; i < 1000; i++) {
80                 totalAlloc++;
81                 Data d = new Data(i);
82                 assertEquals(i, d.get());
83             }
84             System.gc();
85 
86             final int currentAlloc = Data.nGetTotalAlloc() - startAlloc;
87             Log.i(TAG, "# of currently allocated objects=" + currentAlloc);
88 
89             if (currentAlloc < totalAlloc) {
90                 break; // Good, some objects have been released;
91             }
92             if (mRavenwoodRule.realCurrentTimeMillis() > timeoutTime) {
93                 fail("No objects have been released before timeout");
94             }
95         }
96     }
97 }
98