Convert Vsock test to device test

Vsock test depends on two process groups running simultanously:
VirtManager+CrosVM and vsock_server. This was orchestrated by a Java
test runner running on the PC. With all the recent changes to the test,
it is now possible to run the former from AndroidTest.xml (and
eventually that will be completely removed) and convert vsock_server to
a GTest binary installed and invoked directly by TradeFed.

A common GTest class VirtualizationTest is added for hosting individual
test cases and sharing common code. Vsock test is converted to a single
TEST_F instance.

The test target is now called VirtualizationTestCases (dropped Host).

Bug: 181615964
Test: atest VirtualizationTestCases
Change-Id: I5a64d25ecc8f278250cfc3b196b8910ca8b8af52
diff --git a/tests/Android.bp b/tests/Android.bp
new file mode 100644
index 0000000..1b747fe
--- /dev/null
+++ b/tests/Android.bp
@@ -0,0 +1,95 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+kernel_version = "5.10"
+
+kernel_stem = "kernel_prebuilts-" + kernel_version
+kernel_modules_stem = "virt_device_prebuilts_kernel_modules-" + kernel_version
+
+cc_test {
+    name: "VirtualizationTestCases",
+    test_suites: ["device-tests"],
+    srcs: [
+        "common.cc",
+        "vsock_test.cc",
+    ],
+    local_include_dirs: ["include"],
+    data: [
+        ":virt_test_kernel",
+        ":virt_test_initramfs",
+        "vsock_config.json",
+    ],
+    static_libs: [
+        // The existence of the library in the system partition is not guaranteed.
+        // Let's have our own copy of it.
+        "android.system.virtmanager-cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
+
+cc_defaults {
+    name: "virt_test_guest_binary",
+    static_libs: [
+        "libbase",
+        "liblog",
+    ],
+    static_executable: true,
+    installable: false,
+}
+
+cc_binary {
+    name: "virt_test_vsock_guest",
+    srcs: ["vsock_guest.cc"],
+    stem: "vsock_client",
+    defaults: ["virt_test_guest_binary"],
+}
+
+prebuilt_etc {
+    name: "virt_test_kernel",
+    src: "nofile",
+    arch: {
+        arm64: {
+            src: ":" + kernel_stem + "-arm64",
+        },
+        x86_64: {
+            src: ":" + kernel_stem + "-x86_64",
+        },
+    },
+}
+
+android_filesystem {
+    name: "virt_test_initramfs",
+    arch: {
+        arm64: {
+            deps: [kernel_modules_stem + "-arm64"],
+        },
+        x86_64: {
+            deps: [kernel_modules_stem + "-x86_64"],
+        },
+    },
+    deps: [
+        "virt_test_guest_init",
+        "virt_test_vsock_guest",
+    ],
+    type: "cpio",
+}
diff --git a/tests/hostside/AndroidTest.xml b/tests/AndroidTest.xml
similarity index 60%
rename from tests/hostside/AndroidTest.xml
rename to tests/AndroidTest.xml
index 0995881..1f42bff 100644
--- a/tests/hostside/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<configuration description="Config for Virtualization host tests">
+<configuration description="Config for Virtualization tests">
 
     <!-- Basic checks that the device has all the prerequisites. -->
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
@@ -33,18 +33,27 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="abort-on-push-failure" value="true" />
-        <option name="push-file" key="vm_config.json" value="/data/local/tmp/virt-test/vm_config.json" />
-        <option name="push-file" key="virt_hostside_tests_kernel" value="/data/local/tmp/virt-test/kernel" />
-        <option name="push-file" key="virt_hostside_tests_initramfs.img" value="/data/local/tmp/virt-test/initramfs" />
-        <option name="push-file" key="vsock_server" value="/data/local/tmp/virt-test/vsock_server" />
+        <option name="push-file" key="VirtualizationTestCases" value="/data/local/tmp/virt-test/VirtualizationTestCases" />
+        <option name="push-file" key="virt_test_kernel"        value="/data/local/tmp/virt-test/kernel" />
+        <option name="push-file" key="virt_test_initramfs.img" value="/data/local/tmp/virt-test/initramfs" />
+        <option name="push-file" key="vsock_config.json"       value="/data/local/tmp/virt-test/vsock_config.json" />
     </target_preparer>
 
     <!-- Root currently needed to run CrosVM.
          TODO: Give sufficient permissions to the adb shell user (b/171240450). -->
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
-    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
-        <option name="jar" value="VirtualizationHostTestCases.jar" />
-        <option name="runtime-hint" value="2m" />
+    <!-- Run Virt Manager for the duration of the test.
+         TODO: Run Virt Manager as a system service. -->
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="throw-if-cmd-fail" value="true" />
+        <option name="run-bg-command" value="/apex/com.android.virt/bin/virtmanager" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp/virt-test" />
+        <option name="module-name" value="VirtualizationTestCases" />
+        <!-- test-timeout unit is ms, value = 2 minutes -->
+        <option name="native-test-timeout" value="120000" />
     </test>
 </configuration>
diff --git a/tests/common.cc b/tests/common.cc
new file mode 100644
index 0000000..10c98b6
--- /dev/null
+++ b/tests/common.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "virt/VirtualizationTest.h"
+
+namespace virt {
+
+void VirtualizationTest::SetUp() {
+    status_t err = getService<IVirtManager>(String16("android.system.virtmanager"), &mVirtManager);
+    ASSERT_EQ(err, 0);
+}
+
+} // namespace virt
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
deleted file mode 100644
index 7946080..0000000
--- a/tests/hostside/Android.bp
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-kernel_version = "5.10"
-
-kernel_stem = "kernel_prebuilts-" + kernel_version
-kernel_modules_stem = "virt_device_prebuilts_kernel_modules-" + kernel_version
-
-// JAR containing all virtualization host-side tests.
-java_test_host {
-    name: "VirtualizationHostTestCases",
-    srcs: ["java/**/*.java"],
-    test_suites: ["device-tests"],
-    libs: ["tradefed"],
-    data: [
-        ":virt_hostside_tests_kernel",
-        ":virt_hostside_tests_initramfs",
-        ":virt_hostside_tests_vm_config",
-    ],
-    required: [
-        "virt_hostside_tests_vsock_server",
-    ],
-}
-
-prebuilt_etc {
-    name: "virt_hostside_tests_kernel",
-    src: "nofile",
-    arch: {
-        arm64: {
-            src: ":" + kernel_stem + "-arm64",
-        },
-        x86_64: {
-            src: ":" + kernel_stem + "-x86_64",
-        },
-    },
-}
-
-// Copy config files to output directory so that AndroidTest.xml can copy them to the device.
-filegroup {
-    name: "virt_hostside_tests_vm_config",
-    srcs: ["vm_config.json"],
-}
-
-android_filesystem {
-    name: "virt_hostside_tests_initramfs",
-    arch: {
-        arm64: {
-            deps: [kernel_modules_stem + "-arm64"],
-        },
-        x86_64: {
-            deps: [kernel_modules_stem + "-x86_64"],
-        },
-    },
-    deps: [
-        "virt_hostside_tests_guest_init",
-        "virt_hostside_tests_vsock_client",
-    ],
-    type: "cpio",
-}
diff --git a/tests/hostside/java/android/virt/test/VirtTestCase.java b/tests/hostside/java/android/virt/test/VirtTestCase.java
deleted file mode 100644
index 5c030a8..0000000
--- a/tests/hostside/java/android/virt/test/VirtTestCase.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.virt.test;
-
-import static org.junit.Assert.*;
-
-import com.android.tradefed.testtype.DeviceTestCase;
-
-import org.junit.Before;
-
-import java.util.ArrayList;
-
-public abstract class VirtTestCase extends DeviceTestCase {
-
-    private static final String DEVICE_DIR = "/data/local/tmp/virt-test";
-
-    @Before
-    public void setUp() throws Exception {
-        getDevice().waitForDeviceAvailable();
-    }
-
-    protected String getDevicePathForTestBinary(String targetName) throws Exception {
-        String path = String.format("%s/%s", DEVICE_DIR, targetName);
-        if (!getDevice().doesFileExist(path)) {
-            throw new IllegalArgumentException(String.format(
-                    "Binary for target %s not found on device at \"%s\"", targetName, path));
-        }
-        return path;
-    }
-
-    protected static String createCommand(String prog, Object... args) {
-        ArrayList<String> strings = new ArrayList<>();
-        strings.add(prog);
-        for (Object arg : args) {
-            strings.add(arg.toString());
-        }
-        for (String str : strings) {
-            if (str.indexOf(' ') != -1) {
-                throw new IllegalArgumentException("TODO: implement quotes around arguments");
-            } else if (str.indexOf('\'') != -1) {
-                throw new IllegalArgumentException("TODO: implement escaping arguments");
-            }
-        }
-        return String.join(" ", strings);
-    }
-
-}
diff --git a/tests/hostside/java/android/virt/test/VsockTest.java b/tests/hostside/java/android/virt/test/VsockTest.java
deleted file mode 100644
index 9de4f2e..0000000
--- a/tests/hostside/java/android/virt/test/VsockTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.virt.test;
-
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.util.CommandResult;
-
-import org.junit.Test;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-public class VsockTest extends VirtTestCase {
-    private static final long     TIMEOUT = 2L;
-    private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MINUTES;
-    private static final int      RETRIES = 0;
-
-    private static final Integer  GUEST_PORT = 45678;
-    private static final String   TEST_MESSAGE = "HelloWorld";
-
-    private static final String   SERVER_TARGET = "vsock_server";
-    private static final String   VIRT_MANAGER_COMMAND = "/apex/com.android.virt/bin/virtmanager";
-
-    @Test
-    public void testVsockServer() throws Exception {
-        ExecutorService executor = Executors.newFixedThreadPool(2);
-
-        final String serverPath = getDevicePathForTestBinary(SERVER_TARGET);
-        final String vmConfigPath = getDevicePathForTestBinary("vm_config.json");
-        final String serverCmd = createCommand(serverPath, GUEST_PORT, vmConfigPath);
-
-        // Start Virt Manager. This will eventually be a system service, but for now we run it
-        // manually.
-        Future<?> virtManagerTask = executor.submit(() -> {
-            CommandResult res = getDevice().executeShellV2Command(
-                    VIRT_MANAGER_COMMAND, TIMEOUT, TIMEOUT_UNIT, RETRIES);
-            CLog.d(res.getStdout());
-            return null;
-        });
-
-        // Start server in Android that listens for vsock connections.
-        // It will receive a message from a client in the guest VM.
-        Future<?> serverTask = executor.submit(() -> {
-            CommandResult res = getDevice().executeShellV2Command(
-                    serverCmd, TIMEOUT, TIMEOUT_UNIT, RETRIES);
-            assertEquals(TEST_MESSAGE, res.getStdout().trim());
-            return null;
-        });
-
-        // Wait for the server to finish processing the message.
-        serverTask.get(TIMEOUT, TIMEOUT_UNIT);
-    }
-}
diff --git a/tests/hostside/native/vsock/Android.bp b/tests/hostside/native/vsock/Android.bp
deleted file mode 100644
index 5151d62..0000000
--- a/tests/hostside/native/vsock/Android.bp
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_test {
-    name: "virt_hostside_tests_vsock_server",
-    srcs: ["server.cc"],
-    static_libs: [
-        // The existence of the library in the system partition is not guaranteed.
-        // Let's have our own copy of it.
-        "android.system.virtmanager-cpp",
-    ],
-    shared_libs: [
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libutils",
-    ],
-    test_suites: ["device-tests"],
-    stem: "vsock_server",
-}
-
-cc_binary {
-    name: "virt_hostside_tests_vsock_client",
-    srcs: ["client.cc"],
-    static_libs: [
-        "libbase",
-        "liblog",
-    ],
-    static_executable: true,
-    installable: false,
-    stem: "vsock_client",
-}
diff --git a/tests/hostside/native/vsock/server.cc b/tests/hostside/native/vsock/server.cc
deleted file mode 100644
index 1a1aa37..0000000
--- a/tests/hostside/native/vsock/server.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/socket.h>
-#include <unistd.h>
-
-// Needs to be included after sys/socket.h
-#include <linux/vm_sockets.h>
-
-#include <iostream>
-
-#include "android-base/file.h"
-#include "android-base/logging.h"
-#include "android-base/parseint.h"
-#include "android-base/unique_fd.h"
-#include "android/system/virtmanager/IVirtManager.h"
-#include "android/system/virtmanager/IVirtualMachine.h"
-#include "binder/IServiceManager.h"
-
-using namespace android;
-using namespace android::base;
-using namespace android::system::virtmanager;
-
-int main(int argc, const char *argv[]) {
-    unsigned int port;
-    if (argc != 3 || !ParseUint(argv[1], &port)) {
-        LOG(ERROR) << "Usage: " << argv[0] << " <port> <vm_config.json>";
-        return EXIT_FAILURE;
-    }
-    String16 vm_config(argv[2]);
-
-    unique_fd server_fd(TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM, 0)));
-    if (server_fd < 0) {
-        PLOG(ERROR) << "socket";
-        return EXIT_FAILURE;
-    }
-
-    struct sockaddr_vm server_sa = (struct sockaddr_vm){
-            .svm_family = AF_VSOCK,
-            .svm_port = port,
-            .svm_cid = VMADDR_CID_ANY,
-    };
-
-    int ret = TEMP_FAILURE_RETRY(bind(server_fd, (struct sockaddr *)&server_sa, sizeof(server_sa)));
-    if (ret != 0) {
-        PLOG(ERROR) << "bind";
-        return EXIT_FAILURE;
-    }
-
-    LOG(INFO) << "Listening on port " << port << "...";
-    ret = TEMP_FAILURE_RETRY(listen(server_fd, 1));
-    if (ret != 0) {
-        PLOG(ERROR) << "listen";
-        return EXIT_FAILURE;
-    }
-
-    LOG(INFO) << "Getting Virt Manager";
-    sp<IVirtManager> virt_manager;
-    status_t err = getService<IVirtManager>(String16("android.system.virtmanager"), &virt_manager);
-    if (err != 0) {
-        LOG(ERROR) << "Error getting Virt Manager from Service Manager: " << err;
-        return EXIT_FAILURE;
-    }
-    sp<IVirtualMachine> vm;
-    binder::Status status = virt_manager->startVm(vm_config, &vm);
-    if (!status.isOk()) {
-        LOG(ERROR) << "Error starting VM: " << status;
-        return EXIT_FAILURE;
-    }
-    int32_t cid;
-    status = vm->getCid(&cid);
-    if (!status.isOk()) {
-        LOG(ERROR) << "Error getting CID: " << status;
-        return EXIT_FAILURE;
-    }
-    LOG(INFO) << "VM starting with CID " << cid;
-
-    LOG(INFO) << "Accepting connection...";
-    struct sockaddr_vm client_sa;
-    socklen_t client_sa_len = sizeof(client_sa);
-    unique_fd client_fd(
-            TEMP_FAILURE_RETRY(accept(server_fd, (struct sockaddr *)&client_sa, &client_sa_len)));
-    if (client_fd < 0) {
-        PLOG(ERROR) << "accept";
-        return EXIT_FAILURE;
-    }
-    LOG(INFO) << "Connection from CID " << client_sa.svm_cid << " on port " << client_sa.svm_port;
-
-    LOG(INFO) << "Reading message from the client...";
-    std::string msg;
-    if (!ReadFdToString(client_fd, &msg)) {
-        PLOG(ERROR) << "ReadFdToString";
-        return EXIT_FAILURE;
-    }
-
-    // Print the received message to stdout.
-    std::cout << msg << std::endl;
-
-    LOG(INFO) << "Exiting...";
-    return EXIT_SUCCESS;
-}
diff --git a/tests/hostside/nofile b/tests/hostside/nofile
deleted file mode 100644
index eb4638a..0000000
--- a/tests/hostside/nofile
+++ /dev/null
@@ -1,2 +0,0 @@
-// This file is used as src of virt_hostside_tests_kernel module for the architectures
-// other than arm64 and x86_64
diff --git a/tests/include/virt/VirtualizationTest.h b/tests/include/virt/VirtualizationTest.h
new file mode 100644
index 0000000..a996f11
--- /dev/null
+++ b/tests/include/virt/VirtualizationTest.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android/system/virtmanager/IVirtManager.h"
+#include "android/system/virtmanager/IVirtualMachine.h"
+#include "binder/IServiceManager.h"
+#include "gtest/gtest.h"
+
+using namespace android;
+using namespace android::system::virtmanager;
+
+namespace virt {
+
+class VirtualizationTest : public ::testing::Test {
+protected:
+    void SetUp() override;
+
+    sp<IVirtManager> mVirtManager;
+};
+
+} // namespace virt
diff --git a/tests/hostside/native/init/Android.bp b/tests/init/Android.bp
similarity index 94%
rename from tests/hostside/native/init/Android.bp
rename to tests/init/Android.bp
index f2c179b..1643acd 100644
--- a/tests/hostside/native/init/Android.bp
+++ b/tests/init/Android.bp
@@ -17,7 +17,7 @@
 }
 
 cc_binary {
-    name: "virt_hostside_tests_guest_init",
+    name: "virt_test_guest_init",
     srcs: ["main.cc"],
     static_executable: true,
     installable: false,
diff --git a/tests/hostside/native/init/main.cc b/tests/init/main.cc
similarity index 100%
rename from tests/hostside/native/init/main.cc
rename to tests/init/main.cc
diff --git a/tests/nofile b/tests/nofile
new file mode 100644
index 0000000..9e4b854
--- /dev/null
+++ b/tests/nofile
@@ -0,0 +1,2 @@
+// This file is used as src of virt_test_kernel module for the architectures
+// other than arm64 and x86_64
diff --git a/tests/hostside/vm_config.json b/tests/vsock_config.json
similarity index 100%
rename from tests/hostside/vm_config.json
rename to tests/vsock_config.json
diff --git a/tests/hostside/native/vsock/client.cc b/tests/vsock_guest.cc
similarity index 100%
rename from tests/hostside/native/vsock/client.cc
rename to tests/vsock_guest.cc
diff --git a/tests/vsock_test.cc b/tests/vsock_test.cc
new file mode 100644
index 0000000..74e984f
--- /dev/null
+++ b/tests/vsock_test.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/socket.h>
+#include <unistd.h>
+
+// Needs to be included after sys/socket.h
+#include <linux/vm_sockets.h>
+
+#include <iostream>
+
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "android-base/parseint.h"
+#include "android-base/unique_fd.h"
+
+#include "virt/VirtualizationTest.h"
+
+using namespace android::base;
+
+namespace virt {
+
+static constexpr int kGuestPort = 45678;
+static constexpr const char kVmConfigPath[] = "/data/local/tmp/virt-test/vsock_config.json";
+static constexpr const char kTestMessage[] = "HelloWorld";
+
+TEST_F(VirtualizationTest, TestVsock) {
+    binder::Status status;
+
+    unique_fd server_fd(TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM, 0)));
+    ASSERT_GE(server_fd, 0) << strerror(errno);
+
+    struct sockaddr_vm server_sa = (struct sockaddr_vm){
+            .svm_family = AF_VSOCK,
+            .svm_port = kGuestPort,
+            .svm_cid = VMADDR_CID_ANY,
+    };
+
+    int ret = TEMP_FAILURE_RETRY(bind(server_fd, (struct sockaddr *)&server_sa, sizeof(server_sa)));
+    ASSERT_EQ(ret, 0) << strerror(errno);
+
+    LOG(INFO) << "Listening on port " << kGuestPort << "...";
+    ret = TEMP_FAILURE_RETRY(listen(server_fd, 1));
+    ASSERT_EQ(ret, 0) << strerror(errno);
+
+    sp<IVirtualMachine> vm;
+    status = mVirtManager->startVm(String16(kVmConfigPath), &vm);
+    ASSERT_TRUE(status.isOk()) << "Error starting VM: " << status;
+
+    int32_t cid;
+    status = vm->getCid(&cid);
+    ASSERT_TRUE(status.isOk()) << "Error getting CID: " << status;
+    LOG(INFO) << "VM starting with CID " << cid;
+
+    LOG(INFO) << "Accepting connection...";
+    struct sockaddr_vm client_sa;
+    socklen_t client_sa_len = sizeof(client_sa);
+    unique_fd client_fd(
+            TEMP_FAILURE_RETRY(accept(server_fd, (struct sockaddr *)&client_sa, &client_sa_len)));
+    ASSERT_GE(client_fd, 0) << strerror(errno);
+    LOG(INFO) << "Connection from CID " << client_sa.svm_cid << " on port " << client_sa.svm_port;
+
+    LOG(INFO) << "Reading message from the client...";
+    std::string msg;
+    ASSERT_TRUE(ReadFdToString(client_fd, &msg));
+
+    LOG(INFO) << "Received message: " << msg;
+    ASSERT_EQ(msg, kTestMessage);
+}
+
+} // namespace virt