Merge "Add a script to update the bionic headers."
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 0861015..cf0fd6b 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2174,6 +2174,10 @@
time_t
mktime(struct tm *tmp)
{
+#if __ANDROID__
+ int saved_errno = errno;
+#endif
+
time_t t;
int err = lock();
if (err) {
@@ -2183,6 +2187,10 @@
tzset_unlocked();
t = mktime_tzname(lclptr, tmp, true);
unlock();
+
+#if __ANDROID__
+ errno = (t == -1) ? EOVERFLOW : saved_errno;
+#endif
return t;
}
diff --git a/tests/Android.build.prebuilt.mk b/tests/Android.build.prebuilt.mk
index d50656c..09c2366 100644
--- a/tests/Android.build.prebuilt.mk
+++ b/tests/Android.build.prebuilt.mk
@@ -16,13 +16,15 @@
include $(CLEAR_VARS)
LOCAL_MULTILIB := both
-LOCAL_MODULE := $(module)
+LOCAL_MODULE := $(bionic_tests_module)
LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/prebuilt-elf-files
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/prebuilt-elf-files
LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SRC_FILES_arm := prebuilt-elf-files/arm/$(module)
-LOCAL_SRC_FILES_arm64 := prebuilt-elf-files/arm64/$(module)
-LOCAL_SRC_FILES_x86 := prebuilt-elf-files/x86/$(module)
-LOCAL_SRC_FILES_x86_64 := prebuilt-elf-files/x86_64/$(module)
+LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
+
+LOCAL_SRC_FILES_arm := prebuilt-elf-files/arm/$(bionic_tests_module)
+LOCAL_SRC_FILES_arm64 := prebuilt-elf-files/arm64/$(bionic_tests_module)
+LOCAL_SRC_FILES_x86 := prebuilt-elf-files/x86/$(bionic_tests_module)
+LOCAL_SRC_FILES_x86_64 := prebuilt-elf-files/x86_64/$(bionic_tests_module)
include $(BUILD_PREBUILT)
diff --git a/tests/Android.mk b/tests/Android.mk
index 3fe62a8..e1efbbe 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -20,13 +20,25 @@
# https://github.com/google/kati/issues/83 is currently blocking it.
# Move prebuilt test elf-files to $(TARGET_OUT_NATIVE_TESTS)
-module := libtest_invalid-rw_load_segment.so
+bionic_tests_module := libtest_invalid-rw_load_segment.so
include $(LOCAL_PATH)/Android.build.prebuilt.mk
-module := libtest_invalid-unaligned_shdr_offset.so
+bionic_tests_module := libtest_invalid-unaligned_shdr_offset.so
include $(LOCAL_PATH)/Android.build.prebuilt.mk
-module := libtest_invalid-zero_shentsize.so
+bionic_tests_module := libtest_invalid-zero_shentsize.so
+include $(LOCAL_PATH)/Android.build.prebuilt.mk
+
+bionic_tests_module := libtest_invalid-zero_shstrndx.so
+include $(LOCAL_PATH)/Android.build.prebuilt.mk
+
+bionic_tests_module := libtest_invalid-empty_shdr_table.so
+include $(LOCAL_PATH)/Android.build.prebuilt.mk
+
+bionic_tests_module := libtest_invalid-zero_shdr_table_offset.so
+include $(LOCAL_PATH)/Android.build.prebuilt.mk
+
+bionic_tests_module := libtest_invalid-zero_shdr_table_content.so
include $(LOCAL_PATH)/Android.build.prebuilt.mk
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 6e78082..ecc2a12 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1144,7 +1144,7 @@
}
// Bionic specific tests
-#if defined(__BIONIC__)
+#if defined(__BIONIC__) && !defined(__mips__)
#if defined(__LP64__)
#define NATIVE_TESTS_PATH "/nativetest64"
@@ -1178,4 +1178,36 @@
ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
}
+TEST(dlfcn, dlopen_invalid_zero_shstrndx) {
+ std::string libpath = std::string(getenv("ANDROID_DATA")) + PREBUILT_ELF_PATH + "/libtest_invalid-zero_shstrndx.so";
+ void* handle = dlopen(libpath.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle == nullptr);
+ std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid e_shstrndx";
+ ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
+}
+
+TEST(dlfcn, dlopen_invalid_empty_shdr_table) {
+ std::string libpath = std::string(getenv("ANDROID_DATA")) + PREBUILT_ELF_PATH + "/libtest_invalid-empty_shdr_table.so";
+ void* handle = dlopen(libpath.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle == nullptr);
+ std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has no section headers";
+ ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
+}
+
+TEST(dlfcn, dlopen_invalid_zero_shdr_table_offset) {
+ std::string libpath = std::string(getenv("ANDROID_DATA")) + PREBUILT_ELF_PATH + "/libtest_invalid-zero_shdr_table_offset.so";
+ void* handle = dlopen(libpath.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle == nullptr);
+ std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" has invalid shdr offset/size: 0/";
+ ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
+}
+
+TEST(dlfcn, dlopen_invalid_zero_shdr_table_content) {
+ std::string libpath = std::string(getenv("ANDROID_DATA")) + PREBUILT_ELF_PATH + "/libtest_invalid-zero_shdr_table_content.so";
+ void* handle = dlopen(libpath.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle == nullptr);
+ std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\" .dynamic section header was not found";
+ ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
+}
+
#endif
diff --git a/tests/prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..ebeaa19
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_content.so b/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_content.so
new file mode 100755
index 0000000..829c7c2
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_content.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_offset.so b/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_offset.so
new file mode 100755
index 0000000..347cf8b
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shstrndx.so
new file mode 100755
index 0000000..25355d0
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..12ce90f
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so
new file mode 100755
index 0000000..819a032
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so
new file mode 100755
index 0000000..0a07e1c
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
new file mode 100755
index 0000000..625a0e6
--- /dev/null
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..97cf006
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_content.so b/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_content.so
new file mode 100755
index 0000000..9bb21ed
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_content.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_offset.so b/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_offset.so
new file mode 100755
index 0000000..ca814ea
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shstrndx.so
new file mode 100755
index 0000000..f5ff987
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so
new file mode 100755
index 0000000..2052442
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so
new file mode 100755
index 0000000..5ad764c
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so
new file mode 100755
index 0000000..1fae589
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
new file mode 100755
index 0000000..d4f6502
--- /dev/null
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 028a359..48c299a 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -102,20 +102,41 @@
#if !defined(__LP64__)
// 32-bit bionic stupidly had a signed 32-bit time_t.
ASSERT_EQ(-1, mktime(&t));
+ ASSERT_EQ(EOVERFLOW, errno);
#else
// Everyone else should be using a signed 64-bit time_t.
ASSERT_GE(sizeof(time_t) * 8, 64U);
setenv("TZ", "America/Los_Angeles", 1);
tzset();
+ errno = 0;
ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
+ ASSERT_EQ(0, errno);
setenv("TZ", "UTC", 1);
tzset();
+ errno = 0;
ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
+ ASSERT_EQ(0, errno);
#endif
}
+TEST(time, mktime_EOVERFLOW) {
+ struct tm t;
+ memset(&t, 0, sizeof(tm));
+ t.tm_year = 0;
+ t.tm_mon = 2;
+ t.tm_mday = 10;
+
+ errno = 0;
+ ASSERT_NE(static_cast<time_t>(-1), mktime(&t));
+ ASSERT_EQ(0, errno);
+
+ t.tm_year = INT_MAX;
+ ASSERT_EQ(static_cast<time_t>(-1), mktime(&t));
+ ASSERT_EQ(EOVERFLOW, errno);
+}
+
TEST(time, strftime) {
setenv("TZ", "UTC", 1);
diff --git a/tools/versioner/run_tests.py b/tools/versioner/run_tests.py
index 9bac3e2..f3bb6db 100755
--- a/tools/versioner/run_tests.py
+++ b/tools/versioner/run_tests.py
@@ -53,13 +53,33 @@
print("{} {}".format(prefix_pass, test_name))
return True
+
+def usage():
+ print("Usage: run_tests.py [-f]")
+ print(" -f\t\tdon't run slow tests")
+ sys.exit(0)
+
+
root_dir = os.path.dirname(os.path.realpath(__file__))
test_dir = os.path.join(root_dir, "tests")
tests = os.listdir(test_dir)
+run_slow = True
+
+if len(sys.argv) > 2:
+ usage()
+elif len(sys.argv) == 2:
+ if sys.argv[1] != "-f":
+ usage()
+ run_slow = False
success = True
for test in sorted(tests):
- if not run_test(test, os.path.join(test_dir, test)):
+ if test.startswith("slow") and not run_slow:
+ continue
+ path = os.path.join(test_dir, test)
+ if not os.path.isdir(path):
+ continue
+ if not run_test(test, path):
success = False
sys.exit(0 if success else 1)
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
index 8e8d84f..88f7b55 100644
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ b/tools/versioner/src/DeclarationDatabase.cpp
@@ -288,7 +288,7 @@
std::string to_string(const CompilationType& type) {
std::stringstream ss;
- ss << to_string(type.arch) << "-" << type.api_level;
+ ss << to_string(type.arch) << "-" << type.api_level << " [fob = " << type.file_offset_bits << "]";
return ss.str();
}
diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h
index 8fe12ea..b130ca9 100644
--- a/tools/versioner/src/DeclarationDatabase.h
+++ b/tools/versioner/src/DeclarationDatabase.h
@@ -43,10 +43,11 @@
struct CompilationType {
Arch arch;
int api_level;
+ int file_offset_bits;
private:
auto tie() const {
- return std::tie(arch, api_level);
+ return std::tie(arch, api_level, file_offset_bits);
}
public:
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
index 33531bd..8d0b943 100644
--- a/tools/versioner/src/Preprocessor.cpp
+++ b/tools/versioner/src/Preprocessor.cpp
@@ -93,12 +93,12 @@
}
DeclarationAvailability result = decl_av;
- if (result.global_availability.introduced < global_min_api_visible) {
+ if (result.global_availability.introduced <= global_min_api_visible) {
result.global_availability.introduced = 0;
}
for (Arch arch : supported_archs) {
- if (result.arch_availability[arch].introduced < arch_visibility[arch]) {
+ if (result.arch_availability[arch].introduced <= arch_visibility[arch]) {
result.arch_availability[arch].introduced = 0;
}
}
@@ -459,7 +459,7 @@
}
}
- // Copy over any unchanged files directly.
+ // Copy over the original headers before preprocessing.
char* fts_paths[2] = { const_cast<char*>(src_dir.c_str()), nullptr };
FTS* fts = fts_open(fts_paths, FTS_LOGICAL, nullptr);
while (FTSENT* ent = fts_read(fts)) {
@@ -473,18 +473,14 @@
}
std::string rel_path = path.substr(src_dir.length() + 1);
- if (guards.count(rel_path) == 0) {
- std::string dst_path = dst_dir + "/" + rel_path;
- llvm::StringRef parent_path = llvm::sys::path::parent_path(dst_path);
- if (llvm::sys::fs::create_directories(parent_path)) {
- errx(1, "failed to ensure existence of directory '%s'", parent_path.str().c_str());
- }
- if (llvm::sys::fs::copy_file(path, dst_path)) {
- errx(1, "failed to copy '%s/%s' to '%s'", src_dir.c_str(), path.str().c_str(),
- dst_path.c_str());
- }
-
- printf("Copied unmodified header %s\n", dst_path.c_str());
+ std::string dst_path = dst_dir + "/" + rel_path;
+ llvm::StringRef parent_path = llvm::sys::path::parent_path(dst_path);
+ if (llvm::sys::fs::create_directories(parent_path)) {
+ errx(1, "failed to ensure existence of directory '%s'", parent_path.str().c_str());
+ }
+ if (llvm::sys::fs::copy_file(path, dst_path)) {
+ errx(1, "failed to copy '%s/%s' to '%s'", src_dir.c_str(), path.str().c_str(),
+ dst_path.c_str());
}
}
fts_close(fts);
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index b18c3c2..432fd66 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -89,6 +89,8 @@
command.push_back(std::move(header_path));
}
+ command.push_back("-D_FILE_OFFSET_BITS="s + std::to_string(type.file_offset_bits));
+
return CompileCommand(cwd, filename, command);
}
@@ -184,8 +186,13 @@
if (api_level < min_api) {
continue;
}
- CompilationType type = { .arch = arch, .api_level = api_level };
- result.insert(type);
+
+ for (int file_offset_bits : { 32, 64 }) {
+ CompilationType type = {
+ .arch = arch, .api_level = api_level, .file_offset_bits = file_offset_bits
+ };
+ result.insert(type);
+ }
}
}
return result;
diff --git a/tools/versioner/tests/.gitignore b/tools/versioner/tests/.gitignore
new file mode 100644
index 0000000..89f9ac0
--- /dev/null
+++ b/tools/versioner/tests/.gitignore
@@ -0,0 +1 @@
+out/
diff --git a/tools/versioner/tests/compilation_error/expected_fail b/tools/versioner/tests/compilation_error/expected_fail
index 62a643f..f18b625 100644
--- a/tools/versioner/tests/compilation_error/expected_fail
+++ b/tools/versioner/tests/compilation_error/expected_fail
@@ -1,2 +1 @@
-versioner: compilation failure for arm-9 in /android/aosp/bionic/tools/versioner/tests/compilation_error/headers/foo.h
versioner: compilation generated warnings or errors
diff --git a/tools/versioner/tests/missing_api/expected_fail b/tools/versioner/tests/missing_api/expected_fail
index 65a25f2..18e7845 100644
--- a/tools/versioner/tests/missing_api/expected_fail
+++ b/tools/versioner/tests/missing_api/expected_fail
@@ -1,4 +1,3 @@
-foo: declaration marked available but symbol missing in [arm-12]
foo: introduced = 9
extern declaration @ headers/foo.h:1:1
introduced = 9
diff --git a/tools/versioner/tests/missing_arch/expected_fail b/tools/versioner/tests/missing_arch/expected_fail
index ed8ab79..82c2b28 100644
--- a/tools/versioner/tests/missing_arch/expected_fail
+++ b/tools/versioner/tests/missing_arch/expected_fail
@@ -1,4 +1,3 @@
-foo: declaration marked available but symbol missing in [x86-9]
foo: no availability
extern declaration @ headers/foo.h:1:1
no availability
diff --git a/tools/versioner/tests/preprocessor/expected/foo.h b/tools/versioner/tests/preprocessor/expected/foo.h
index 3e05a1e..b83dd07 100644
--- a/tools/versioner/tests/preprocessor/expected/foo.h
+++ b/tools/versioner/tests/preprocessor/expected/foo.h
@@ -3,44 +3,64 @@
int also_always_available() __INTRODUCED_IN(9);
-#if __ANDROID_API__ >= 10
-int needs_guard() __INTRODUCED_IN(10);
-#endif /* __ANDROID_API__ >= 10 */
+#if __ANDROID_API__ >= 13
+int needs_guard() __INTRODUCED_IN(13);
+#endif /* __ANDROID_API__ >= 13 */
-#if __ANDROID_API__ >= 10
-int already_guarded() __INTRODUCED_IN(10);
+#if __ANDROID_API__ >= 12
+
+#if __ANDROID_API__ >= 13
+int needs_guard_2() __INTRODUCED_IN(13);
+#endif /* __ANDROID_API__ >= 13 */
+
+#endif
+
+#if __ANDROID_API__ >= 13
+int already_guarded() __INTRODUCED_IN(13);
+#endif
+
+#if __ANDROID_API__ > 13
+int already_guarded_2() __INTRODUCED_IN(13);
#endif
#if defined(__arm__)
-#if __ANDROID_API__ >= 11
-int specific_arch() __INTRODUCED_IN(11);
-#endif /* __ANDROID_API__ >= 11 */
+#if __ANDROID_API__ >= 14
+int specific_arch() __INTRODUCED_IN(14);
+#endif /* __ANDROID_API__ >= 14 */
+
+#if __ANDROID_API__ >= 14
+int specific_arch_already_guarded() __INTRODUCED_IN(14);
+#endif
+
+#if __ANDROID_API__ > 14
+int specific_arch_already_guarded_2() __INTRODUCED_IN(14);
+#endif
#endif
#if defined(__arm__) || defined(__i386__)
-#if __ANDROID_API__ >= 11
-int multiple_archs() __INTRODUCED_IN(11);
-#endif /* __ANDROID_API__ >= 11 */
+#if __ANDROID_API__ >= 14
+int multiple_archs() __INTRODUCED_IN(14);
+#endif /* __ANDROID_API__ >= 14 */
#endif
// __INTRODUCED_IN_64(21) should be ignored.
-#if (defined(__LP64__)) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10)
-int multiple_introduced_1() __INTRODUCED_IN_ARM(10) __INTRODUCED_IN_MIPS(11) __INTRODUCED_IN_X86(10)
+#if (defined(__LP64__)) || (defined(__arm__) && __ANDROID_API__ >= 13) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 14) || (defined(__i386__) && __ANDROID_API__ >= 13)
+int multiple_introduced_1() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(14) __INTRODUCED_IN_X86(13)
__INTRODUCED_IN_64(21);
-#endif /* (defined(__LP64__)) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10) */
+#endif /* (defined(__LP64__)) || (defined(__arm__) && __ANDROID_API__ >= 13) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 14) || (defined(__i386__) && __ANDROID_API__ >= 13) */
-#if (defined(__LP64__) && __ANDROID_API__ >= 22) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10)
-int multiple_introduced_2() __INTRODUCED_IN_ARM(10) __INTRODUCED_IN_MIPS(11) __INTRODUCED_IN_X86(10)
+#if (defined(__LP64__) && __ANDROID_API__ >= 22) || (defined(__arm__) && __ANDROID_API__ >= 13) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 14) || (defined(__i386__) && __ANDROID_API__ >= 13)
+int multiple_introduced_2() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(14) __INTRODUCED_IN_X86(13)
__INTRODUCED_IN_64(22);
-#endif /* (defined(__LP64__) && __ANDROID_API__ >= 22) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10) */
+#endif /* (defined(__LP64__) && __ANDROID_API__ >= 22) || (defined(__arm__) && __ANDROID_API__ >= 13) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 14) || (defined(__i386__) && __ANDROID_API__ >= 13) */
diff --git a/tools/versioner/tests/preprocessor/headers/foo.h b/tools/versioner/tests/preprocessor/headers/foo.h
index ae5b847..7eba47f 100644
--- a/tools/versioner/tests/preprocessor/headers/foo.h
+++ b/tools/versioner/tests/preprocessor/headers/foo.h
@@ -2,25 +2,41 @@
int also_always_available() __INTRODUCED_IN(9);
-int needs_guard() __INTRODUCED_IN(10);
+int needs_guard() __INTRODUCED_IN(13);
-#if __ANDROID_API__ >= 10
-int already_guarded() __INTRODUCED_IN(10);
+#if __ANDROID_API__ >= 12
+int needs_guard_2() __INTRODUCED_IN(13);
+#endif
+
+#if __ANDROID_API__ >= 13
+int already_guarded() __INTRODUCED_IN(13);
+#endif
+
+#if __ANDROID_API__ > 13
+int already_guarded_2() __INTRODUCED_IN(13);
#endif
#if defined(__arm__)
-int specific_arch() __INTRODUCED_IN(11);
+int specific_arch() __INTRODUCED_IN(14);
+
+#if __ANDROID_API__ >= 14
+int specific_arch_already_guarded() __INTRODUCED_IN(14);
+#endif
+
+#if __ANDROID_API__ > 14
+int specific_arch_already_guarded_2() __INTRODUCED_IN(14);
+#endif
#endif
#if defined(__arm__) || defined(__i386__)
-int multiple_archs() __INTRODUCED_IN(11);
+int multiple_archs() __INTRODUCED_IN(14);
#endif
// __INTRODUCED_IN_64(21) should be ignored.
-int multiple_introduced_1() __INTRODUCED_IN_ARM(10) __INTRODUCED_IN_MIPS(11) __INTRODUCED_IN_X86(10)
+int multiple_introduced_1() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(14) __INTRODUCED_IN_X86(13)
__INTRODUCED_IN_64(21);
-int multiple_introduced_2() __INTRODUCED_IN_ARM(10) __INTRODUCED_IN_MIPS(11) __INTRODUCED_IN_X86(10)
+int multiple_introduced_2() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(14) __INTRODUCED_IN_X86(13)
__INTRODUCED_IN_64(22);
int group_lp32() __INTRODUCED_IN_ARM(12) __INTRODUCED_IN_X86(12) __INTRODUCED_IN_MIPS(12);
diff --git a/tools/versioner/tests/preprocessor/out/foo.h b/tools/versioner/tests/preprocessor/out/foo.h
deleted file mode 100644
index 3e05a1e..0000000
--- a/tools/versioner/tests/preprocessor/out/foo.h
+++ /dev/null
@@ -1,50 +0,0 @@
-int always_available();
-
-int also_always_available() __INTRODUCED_IN(9);
-
-
-#if __ANDROID_API__ >= 10
-int needs_guard() __INTRODUCED_IN(10);
-#endif /* __ANDROID_API__ >= 10 */
-
-
-#if __ANDROID_API__ >= 10
-int already_guarded() __INTRODUCED_IN(10);
-#endif
-
-#if defined(__arm__)
-
-#if __ANDROID_API__ >= 11
-int specific_arch() __INTRODUCED_IN(11);
-#endif /* __ANDROID_API__ >= 11 */
-
-#endif
-
-#if defined(__arm__) || defined(__i386__)
-
-#if __ANDROID_API__ >= 11
-int multiple_archs() __INTRODUCED_IN(11);
-#endif /* __ANDROID_API__ >= 11 */
-
-#endif
-
-// __INTRODUCED_IN_64(21) should be ignored.
-
-#if (defined(__LP64__)) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10)
-int multiple_introduced_1() __INTRODUCED_IN_ARM(10) __INTRODUCED_IN_MIPS(11) __INTRODUCED_IN_X86(10)
- __INTRODUCED_IN_64(21);
-#endif /* (defined(__LP64__)) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10) */
-
-
-
-#if (defined(__LP64__) && __ANDROID_API__ >= 22) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10)
-int multiple_introduced_2() __INTRODUCED_IN_ARM(10) __INTRODUCED_IN_MIPS(11) __INTRODUCED_IN_X86(10)
- __INTRODUCED_IN_64(22);
-#endif /* (defined(__LP64__) && __ANDROID_API__ >= 22) || (defined(__arm__) && __ANDROID_API__ >= 10) || (defined(__mips__) && !defined(__LP64__) && __ANDROID_API__ >= 11) || (defined(__i386__) && __ANDROID_API__ >= 10) */
-
-
-
-#if (!defined(__LP64__) && __ANDROID_API__ >= 12) || (defined(__LP64__))
-int group_lp32() __INTRODUCED_IN_ARM(12) __INTRODUCED_IN_X86(12) __INTRODUCED_IN_MIPS(12);
-#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 12) || (defined(__LP64__)) */
-
diff --git a/tools/versioner/tests/preprocessor/run.sh b/tools/versioner/tests/preprocessor/run.sh
index 1b0aae2..60e7024 100644
--- a/tools/versioner/tests/preprocessor/run.sh
+++ b/tools/versioner/tests/preprocessor/run.sh
@@ -1,4 +1,29 @@
-rm -rf out
set -e
-versioner headers -i -o out
-diff -q -w -B out expected
+
+function run_test {
+ SRC=$1
+ DST=$2
+ rm -rf $2
+ versioner $1 -i -o $2
+ diff -q -w -B $2 expected
+}
+
+run_test headers out
+run_test headers/ out
+run_test headers out/
+run_test headers/ out/
+
+run_test `pwd`/headers out
+run_test `pwd`/headers/ out
+run_test `pwd`/headers out/
+run_test `pwd`/headers/ out/
+
+run_test headers `pwd`/out
+run_test headers/ `pwd`/out
+run_test headers `pwd`/out/
+run_test headers/ `pwd`/out/
+
+run_test `pwd`/headers `pwd`/out
+run_test `pwd`/headers/ `pwd`/out
+run_test `pwd`/headers `pwd`/out/
+run_test `pwd`/headers/ `pwd`/out/
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
new file mode 100644
index 0000000..7d31ec3
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
@@ -0,0 +1,34 @@
+typedef int off_t;
+typedef int ssize_t;
+typedef unsigned size_t;
+
+#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
+#if _FILE_OFFSET_BITS == 64
+#define __USE_FILE_OFFSET64 1
+#endif
+#endif
+
+#define __RENAME(x) __asm__(#x)
+
+#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= 21
+int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
+#else
+int truncate(const char* __path, off_t __length);
+#endif
+
+#if defined(__USE_FILE_OFFSET64)
+
+#if __ANDROID_API__ >= 12
+ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset) __RENAME(pread64)
+ __INTRODUCED_IN(12);
+#endif /* __ANDROID_API__ >= 12 */
+
+#else
+ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
+#endif
+
+#if defined(__USE_FILE_OFFSET64)
+off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
+#else
+off_t lseek(int __fd, off_t __offset, int __whence);
+#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
new file mode 100644
index 0000000..868d1fc
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
@@ -0,0 +1,30 @@
+typedef int off_t;
+typedef int ssize_t;
+typedef unsigned size_t;
+
+#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
+#if _FILE_OFFSET_BITS == 64
+#define __USE_FILE_OFFSET64 1
+#endif
+#endif
+
+#define __RENAME(x) __asm__(#x)
+
+#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= 21
+int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
+#else
+int truncate(const char* __path, off_t __length);
+#endif
+
+#if defined(__USE_FILE_OFFSET64)
+ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset) __RENAME(pread64)
+ __INTRODUCED_IN(12);
+#else
+ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
+#endif
+
+#if defined(__USE_FILE_OFFSET64)
+off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
+#else
+off_t lseek(int __fd, off_t __offset, int __whence);
+#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/run.sh b/tools/versioner/tests/preprocessor_file_offset_bits/run.sh
new file mode 100644
index 0000000..c503867
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_file_offset_bits/run.sh
@@ -0,0 +1,5 @@
+set -e
+
+rm -rf out
+versioner headers -i -o out
+diff -q -w -B out expected
diff --git a/tools/versioner/tests/preprocessor_idempotence/expected/foo.h b/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
new file mode 100644
index 0000000..ed31e8b
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
@@ -0,0 +1,12 @@
+#if __ANDROID_API__ >= 10
+int foo() __INTRODUCED_IN(10);
+#endif
+
+#if __ANDROID_API__ >= 21
+int bar(int) __INTRODUCED_IN(21);
+#endif
+
+#if __ANDROID_API__ >= 10
+int multiple_1() __INTRODUCED_IN(10);
+int multiple_2() __INTRODUCED_IN(10);
+#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/headers/foo.h b/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
new file mode 100644
index 0000000..ed31e8b
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
@@ -0,0 +1,12 @@
+#if __ANDROID_API__ >= 10
+int foo() __INTRODUCED_IN(10);
+#endif
+
+#if __ANDROID_API__ >= 21
+int bar(int) __INTRODUCED_IN(21);
+#endif
+
+#if __ANDROID_API__ >= 10
+int multiple_1() __INTRODUCED_IN(10);
+int multiple_2() __INTRODUCED_IN(10);
+#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/run.sh b/tools/versioner/tests/preprocessor_idempotence/run.sh
new file mode 100644
index 0000000..1b0aae2
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_idempotence/run.sh
@@ -0,0 +1,4 @@
+rm -rf out
+set -e
+versioner headers -i -o out
+diff -q -w -B out expected
diff --git a/tools/versioner/tests/slow_preprocessor_idempotence/run.sh b/tools/versioner/tests/slow_preprocessor_idempotence/run.sh
new file mode 100644
index 0000000..6426156
--- /dev/null
+++ b/tools/versioner/tests/slow_preprocessor_idempotence/run.sh
@@ -0,0 +1,6 @@
+rm -rf out
+set -e
+mkdir out
+versioner -o out/initial
+versioner out/initial ../../dependencies -o out/second
+diff -qrwB out/initial out/second