tests: Add NDK program semaphore tests

Test: berberis_run_host_tests
Bug: 276830819
Change-Id: I58041eaba771b5993194d9e2627dbe5ef37291d3
diff --git a/tests/ndk_program_tests/Android.bp b/tests/ndk_program_tests/Android.bp
index efe8b63..9e03440 100644
--- a/tests/ndk_program_tests/Android.bp
+++ b/tests/ndk_program_tests/Android.bp
@@ -33,6 +33,7 @@
         "div_test.cc",
         "epoll_test.cc",
         "ptrace_test.cc",
+        "sem_test.cc",
         "string_test.cc",
         "thread_test.cc",
         "time_test.cc",
diff --git a/tests/ndk_program_tests/sem_test.cc b/tests/ndk_program_tests/sem_test.cc
new file mode 100644
index 0000000..d3f5979
--- /dev/null
+++ b/tests/ndk_program_tests/sem_test.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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 "gtest/gtest.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+TEST(Sem, SingleThread) {
+  sem_t sem;
+  ASSERT_EQ(sem_init(&sem, 0, 0), 0);
+  ASSERT_EQ(sem_post(&sem), 0);
+  int value;
+  ASSERT_EQ(sem_getvalue(&sem, &value), 0);
+  ASSERT_EQ(value, 1);
+  ASSERT_EQ(sem_wait(&sem), 0);
+  ASSERT_EQ(sem_trywait(&sem), -1);
+  ASSERT_EQ(errno, EAGAIN);
+  ASSERT_EQ(sem_destroy(&sem), 0);
+}
+
+static void* SeparateThread(void* arg) {
+  sem_post(reinterpret_cast<sem_t*>(arg));
+  return nullptr;
+}
+
+TEST(Sem, UnlockOnDifferentThread) {
+  sem_t sem;
+  ASSERT_EQ(sem_init(&sem, 0, 0), 0);
+  pthread_t thread;
+  ASSERT_EQ(pthread_create(&thread, nullptr, &SeparateThread, reinterpret_cast<void*>(&sem)), 0);
+  ASSERT_EQ(sem_wait(&sem), 0);
+  ASSERT_EQ(pthread_join(thread, nullptr), 0);
+}