diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java index 68c1c57ef6..536ab2d30a 100644 --- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java +++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java @@ -30,6 +30,7 @@ import static org.junit.Assert.fail; import android.net.MacAddress; import android.os.Build; import android.system.ErrnoException; +import android.system.Os; import android.system.OsConstants; import android.util.ArrayMap; @@ -42,6 +43,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import java.io.File; import java.net.InetAddress; import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicInteger; @@ -393,4 +395,34 @@ public final class BpfMapTest { assertEquals(OsConstants.ENOENT, expected.errno); } } + + private static int getNumOpenFds() { + return new File("/proc/" + Os.getpid() + "/fd").listFiles().length; + } + + @Test + public void testNoFdLeaks() throws Exception { + // Due to #setUp has called #initTestMap to open map and BpfMap is using persistent fd + // cache, expect that the fd amount is not increased in the iterations. + // See the comment of BpfMap#close. + final int iterations = 1000; + final int before = getNumOpenFds(); + for (int i = 0; i < iterations; i++) { + try (BpfMap map = new BpfMap<>( + TETHER_DOWNSTREAM6_FS_PATH, BpfMap.BPF_F_RDWR, + TetherDownstream6Key.class, Tether6Value.class)) { + // do nothing + } + } + final int after = getNumOpenFds(); + + // Check that the number of open fds is the same as before. + // If this exact match becomes flaky, we probably need to distinguish that fd is belong + // to "bpf-map". + // ex: + // $ adb shell ls -all /proc/16196/fd + // [..] network_stack 64 2022-07-26 22:01:02.300002956 +0800 749 -> anon_inode:bpf-map + // [..] network_stack 64 2022-07-26 22:01:02.188002956 +0800 75 -> anon_inode:[eventfd] + assertEquals("Fd leak after " + iterations + " iterations: ", before, after); + } }