--checkapi=equal checks the equality of two dumps
Switched from diff-based test, which often breaks for trivial changes.
For example, changing '/* @hide */' to '/** @hide */' shouldn't break
the equality of two dumps.
Similarly, adding license/copyright headers to dumped .aidl files
shouldn't break the equality.
Bug: 172476424
Test: m (triggers checks)
Change-Id: Iea2d3b9f8597977ab276828e943dd6e84debc8ce
diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp
index 2b5664a..6337f8e 100644
--- a/aidl_checkapi.cpp
+++ b/aidl_checkapi.cpp
@@ -26,6 +26,7 @@
#include <android-base/result.h>
#include <android-base/strings.h>
+#include <gtest/gtest.h>
namespace android {
namespace aidl {
@@ -38,6 +39,24 @@
using std::string;
using std::vector;
+static std::string Dump(const AidlDefinedType& type) {
+ std::string dump;
+ type.Dump(CodeWriter::ForString(&dump).get());
+ return dump;
+}
+
+// Uses each type's Dump() and GTest utility(EqHelper).
+static bool CheckEquality(const AidlDefinedType& older, const AidlDefinedType& newer) {
+ using testing::internal::EqHelper;
+ auto older_file = older.GetLocation().GetFile();
+ auto newer_file = newer.GetLocation().GetFile();
+ auto result = EqHelper::Compare(older_file.data(), newer_file.data(), Dump(older), Dump(newer));
+ if (!result) {
+ AIDL_ERROR(newer) << result.failure_message();
+ }
+ return result;
+}
+
static vector<string> get_strict_annotations(const AidlAnnotatable& node) {
// This must be symmetrical (if you can add something, you must be able to
// remove it). The reason is that we have no way of knowing which interface a
@@ -367,15 +386,33 @@
return false;
}
+ const Options::CheckApiLevel level = options.GetCheckApiLevel();
+
std::vector<AidlDefinedType*> old_types = old_tns->AllDefinedTypes();
std::vector<AidlDefinedType*> new_types = new_tns->AllDefinedTypes();
+ bool compatible = true;
+
+ if (level == Options::CheckApiLevel::EQUAL) {
+ std::set<string> old_type_names;
+ for (const auto t : old_types) {
+ old_type_names.insert(t->GetCanonicalName());
+ }
+ for (const auto new_type : new_types) {
+ const auto found = old_type_names.find(new_type->GetCanonicalName());
+ if (found == old_type_names.end()) {
+ AIDL_ERROR(new_type) << "Added type: " << new_type->GetCanonicalName();
+ compatible = false;
+ continue;
+ }
+ }
+ }
+
map<string, AidlDefinedType*> new_map;
for (const auto t : new_types) {
new_map.emplace(t->GetCanonicalName(), t);
}
- bool compatible = true;
for (const auto old_type : old_types) {
const auto found = new_map.find(old_type->GetCanonicalName());
if (found == new_map.end()) {
@@ -385,6 +422,13 @@
}
const auto new_type = found->second;
+ if (level == Options::CheckApiLevel::EQUAL) {
+ if (!CheckEquality(*old_type, *new_type)) {
+ compatible = false;
+ }
+ continue;
+ }
+
if (!have_compatible_annotations(*old_type, *new_type)) {
compatible = false;
}