/* * Copyright (C) 2017, 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 #include #include #include #include "Collation.h" #include "frameworks/proto_logging/stats/stats_log_api_gen/test.pb.h" namespace android { namespace stats_log_api_gen { using std::map; using std::vector; namespace fs = std::filesystem; /** * Return whether the map contains a vector of the elements provided. */ static bool map_contains_vector(const SignatureInfoMap& s, int count, ...) { va_list args; vector v(count); va_start(args, count); for (int i = 0; i < count; i++) { v[i] = static_cast(va_arg(args, int)); } va_end(args); return s.find(v) != s.end(); } /** * Expect that the provided map contains the elements provided. */ #define EXPECT_MAP_CONTAINS_SIGNATURE(s, ...) \ do { \ int count = sizeof((int[]){__VA_ARGS__}) / sizeof(int); \ EXPECT_TRUE(map_contains_vector(s, count, __VA_ARGS__)); \ } while (0) /** Expects that the provided atom has no enum values for any field. */ #define EXPECT_NO_ENUM_FIELD(atom) \ do { \ for (vector::const_iterator field = atom->fields.begin(); \ field != atom->fields.end(); field++) { \ EXPECT_TRUE(field->enumValues.empty()); \ } \ } while (0) /** Expects that exactly one specific field has expected enum values. */ #define EXPECT_HAS_ENUM_FIELD(atom, field_name, values) \ do { \ for (vector::const_iterator field = atom->fields.begin(); \ field != atom->fields.end(); field++) { \ if (field->name == field_name) { \ EXPECT_EQ(field->enumValues, values); \ } else { \ EXPECT_TRUE(field->enumValues.empty()); \ } \ } \ } while (0) // Setup for test fixture. class CollationTest : public testing::TestWithParam { class MFErrorCollector : public google::protobuf::compiler::MultiFileErrorCollector { public: void AddError(const std::string& filename, int line, int column, const std::string& message) override { fprintf(stdout, "[Error] %s:%d:%d - %s", filename.c_str(), line, column, message.c_str()); } }; public: CollationTest() : mImporter(&mSourceTree, &mErrorCollector) { mSourceTree.MapPath("", fs::current_path().c_str()); mFileDescriptor = mImporter.Import("test_external.proto"); } protected: void SetUp() override { if (GetParam()) { mEvent = Event::descriptor(); mIntAtom = IntAtom::descriptor(); mBadTypesEvent = BadTypesEvent::descriptor(); mBadSkippedFieldSingle = BadSkippedFieldSingle::descriptor(); mBadSkippedFieldMultiple = BadSkippedFieldMultiple::descriptor(); mBadAttributionNodePosition = BadAttributionNodePosition::descriptor(); mBadStateAtoms = BadStateAtoms::descriptor(); mGoodStateAtoms = GoodStateAtoms::descriptor(); mBadUidAtoms = BadUidAtoms::descriptor(); mGoodUidAtoms = GoodUidAtoms::descriptor(); mGoodEventWithBinaryFieldAtom = GoodEventWithBinaryFieldAtom::descriptor(); mBadEventWithBinaryFieldAtom = BadEventWithBinaryFieldAtom::descriptor(); mModuleAtoms = ModuleAtoms::descriptor(); mPushedAndPulledAtoms = PushedAndPulledAtoms::descriptor(); mVendorAtoms = VendorAtoms::descriptor(); mGoodRestrictedAtoms = GoodRestrictedAtoms::descriptor(); mBadRestrictedAtoms1 = BadRestrictedAtoms1::descriptor(); mBadRestrictedAtoms2 = BadRestrictedAtoms2::descriptor(); mBadRestrictedAtoms3 = BadRestrictedAtoms3::descriptor(); mBadRestrictedAtoms4 = BadRestrictedAtoms4::descriptor(); mBadRestrictedAtoms5 = BadRestrictedAtoms5::descriptor(); mGoodUintAtoms = GoodUintAtoms::descriptor(); } else { mEvent = mFileDescriptor->FindMessageTypeByName("Event"); mIntAtom = mFileDescriptor->FindMessageTypeByName("IntAtom"); mBadTypesEvent = mFileDescriptor->FindMessageTypeByName("BadTypesEvent"); mBadSkippedFieldSingle = mFileDescriptor->FindMessageTypeByName("BadSkippedFieldSingle"); mBadSkippedFieldMultiple = mFileDescriptor->FindMessageTypeByName("BadSkippedFieldMultiple"); mBadAttributionNodePosition = mFileDescriptor->FindMessageTypeByName("BadAttributionNodePosition"); mBadStateAtoms = mFileDescriptor->FindMessageTypeByName("BadStateAtoms"); mGoodStateAtoms = mFileDescriptor->FindMessageTypeByName("GoodStateAtoms"); mBadUidAtoms = mFileDescriptor->FindMessageTypeByName("BadUidAtoms"); mGoodUidAtoms = mFileDescriptor->FindMessageTypeByName("GoodUidAtoms"); mGoodEventWithBinaryFieldAtom = mFileDescriptor->FindMessageTypeByName("GoodEventWithBinaryFieldAtom"); mBadEventWithBinaryFieldAtom = mFileDescriptor->FindMessageTypeByName("BadEventWithBinaryFieldAtom"); mModuleAtoms = mFileDescriptor->FindMessageTypeByName("ModuleAtoms"); mPushedAndPulledAtoms = mFileDescriptor->FindMessageTypeByName("PushedAndPulledAtoms"); mVendorAtoms = mFileDescriptor->FindMessageTypeByName("VendorAtoms"); mGoodRestrictedAtoms = mFileDescriptor->FindMessageTypeByName("GoodRestrictedAtoms"); mBadRestrictedAtoms1 = mFileDescriptor->FindMessageTypeByName("BadRestrictedAtoms1"); mBadRestrictedAtoms2 = mFileDescriptor->FindMessageTypeByName("BadRestrictedAtoms2"); mBadRestrictedAtoms3 = mFileDescriptor->FindMessageTypeByName("BadRestrictedAtoms3"); mBadRestrictedAtoms4 = mFileDescriptor->FindMessageTypeByName("BadRestrictedAtoms4"); mBadRestrictedAtoms5 = mFileDescriptor->FindMessageTypeByName("BadRestrictedAtoms5"); mGoodUintAtoms = mFileDescriptor->FindMessageTypeByName("GoodUintAtoms"); } } MFErrorCollector mErrorCollector; google::protobuf::compiler::DiskSourceTree mSourceTree; google::protobuf::compiler::Importer mImporter; const google::protobuf::FileDescriptor* mFileDescriptor; const Descriptor* mEvent; const Descriptor* mIntAtom; const Descriptor* mBadTypesEvent; const Descriptor* mBadSkippedFieldSingle; const Descriptor* mBadSkippedFieldMultiple; const Descriptor* mBadAttributionNodePosition; const Descriptor* mBadStateAtoms; const Descriptor* mGoodStateAtoms; const Descriptor* mBadUidAtoms; const Descriptor* mGoodUidAtoms; const Descriptor* mGoodEventWithBinaryFieldAtom; const Descriptor* mBadEventWithBinaryFieldAtom; const Descriptor* mModuleAtoms; const Descriptor* mPushedAndPulledAtoms; const Descriptor* mVendorAtoms; const Descriptor* mGoodRestrictedAtoms; const Descriptor* mBadRestrictedAtoms1; const Descriptor* mBadRestrictedAtoms2; const Descriptor* mBadRestrictedAtoms3; const Descriptor* mBadRestrictedAtoms4; const Descriptor* mBadRestrictedAtoms5; const Descriptor* mGoodUintAtoms; }; INSTANTIATE_TEST_SUITE_P(ProtoProvider, CollationTest, testing::Values(true, false)); /** * Test a correct collation, with all the types. */ TEST_P(CollationTest, CollateStats) { Atoms atoms; const int errorCount = collate_atoms(*mEvent, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); EXPECT_EQ(4ul, atoms.signatureInfoMap.size()); // IntAtom, AnotherIntAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); // OutOfOrderAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT); // AllTypesAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_ATTRIBUTION_CHAIN, // AttributionChain JAVA_TYPE_FLOAT, // float JAVA_TYPE_LONG, // int64 JAVA_TYPE_INT, // int32 JAVA_TYPE_BOOLEAN, // bool JAVA_TYPE_STRING, // string JAVA_TYPE_INT, // AnEnum JAVA_TYPE_FLOAT_ARRAY, // repeated float JAVA_TYPE_LONG_ARRAY, // repeated int64 JAVA_TYPE_INT_ARRAY, // repeated int32 JAVA_TYPE_BOOLEAN_ARRAY, // repeated bool JAVA_TYPE_STRING_ARRAY, // repeated string JAVA_TYPE_BYTE_ARRAY // SubMessageWithUint (mode bytes) ); // RepeatedEnumAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT_ARRAY); EXPECT_EQ(5ul, atoms.decls.size()); AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); EXPECT_EQ(1, (*atomIt)->code); EXPECT_EQ("int_atom", (*atomIt)->name); EXPECT_EQ("IntAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(2, (*atomIt)->code); EXPECT_EQ("out_of_order_atom", (*atomIt)->name); EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(3, (*atomIt)->code); EXPECT_EQ("another_int_atom", (*atomIt)->name); EXPECT_EQ("AnotherIntAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(4, (*atomIt)->code); EXPECT_EQ("all_types_atom", (*atomIt)->name); EXPECT_EQ("AllTypesAtom", (*atomIt)->message); map enumValues; enumValues[0] = "VALUE0"; enumValues[1] = "VALUE1"; EXPECT_HAS_ENUM_FIELD((*atomIt), "enum_field", enumValues); atomIt++; EXPECT_EQ(5, (*atomIt)->code); EXPECT_EQ("repeated_enum_atom", (*atomIt)->name); EXPECT_EQ("RepeatedEnumAtom", (*atomIt)->message); enumValues[0] = "VALUE0"; enumValues[1] = "VALUE1"; EXPECT_HAS_ENUM_FIELD((*atomIt), "repeated_enum_field", enumValues); atomIt++; EXPECT_EQ(atoms.decls.end(), atomIt); } /** * Test that event class that contains stuff other than the atoms is rejected. */ TEST_P(CollationTest, NonMessageTypeFails) { Atoms atoms; const int errorCount = collate_atoms(*mIntAtom, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(1, errorCount); } /** * Test that atoms that have unsupported field types are rejected. */ TEST_P(CollationTest, FailOnBadTypes) { Atoms atoms; const int errorCount = collate_atoms(*mBadTypesEvent, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(22, errorCount); } /** * Test that atoms that skip field numbers (in the first position) are rejected. */ TEST_P(CollationTest, FailOnSkippedFieldsSingle) { Atoms atoms; const int errorCount = collate_atoms(*mBadSkippedFieldSingle, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(1, errorCount); } /** * Test that atoms that skip field numbers (not in the first position, and * multiple times) are rejected. */ TEST_P(CollationTest, FailOnSkippedFieldsMultiple) { Atoms atoms; const int errorCount = collate_atoms(*mBadSkippedFieldMultiple, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(2, errorCount); } /** * Test that atoms that have an attribution chain not in the first position are * rejected. */ TEST_P(CollationTest, FailBadAttributionNodePosition) { Atoms atoms; const int errorCount = collate_atoms(*mBadAttributionNodePosition, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(1, errorCount); } TEST_P(CollationTest, FailOnBadStateAtomOptions) { Atoms atoms; const int errorCount = collate_atoms(*mBadStateAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(4, errorCount); } TEST_P(CollationTest, PassOnGoodStateAtomOptions) { Atoms atoms; const int errorCount = collate_atoms(*mGoodStateAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); } TEST_P(CollationTest, FailOnBadUidAtomOptions) { Atoms atoms; const int errorCount = collate_atoms(*mBadUidAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(2, errorCount); } TEST_P(CollationTest, PassOnGoodUidAtomOptions) { Atoms atoms; const int errorCount = collate_atoms(*mGoodUidAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); } TEST_P(CollationTest, PassOnGoodBinaryFieldAtom) { Atoms atoms; const int errorCount = collate_atoms(*mGoodEventWithBinaryFieldAtom, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); } TEST_P(CollationTest, FailOnBadBinaryFieldAtom) { Atoms atoms; const int errorCount = collate_atoms(*mBadEventWithBinaryFieldAtom, DEFAULT_MODULE_NAME, atoms); EXPECT_GT(errorCount, 0); } TEST_P(CollationTest, PassOnLogFromModuleAtom) { Atoms atoms; const int errorCount = collate_atoms(*mModuleAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(errorCount, 0); EXPECT_EQ(atoms.decls.size(), 4ul); } TEST_P(CollationTest, RecognizeModuleAtom) { Atoms atoms; const int errorCount = collate_atoms(*mModuleAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(errorCount, 0); EXPECT_EQ(atoms.decls.size(), 4ul); EXPECT_EQ(atoms.signatureInfoMap.size(), 2u); EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_STRING); SignatureInfoMap::const_iterator signatureInfoMapIt; const vector* signature; const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet; FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt; const AtomDeclSet* atomDeclSet; AtomDeclSet::const_iterator atomDeclSetIt; AtomDecl* atomDecl; FieldNumberToAnnotations* fieldNumberToAnnotations; FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt; const AnnotationSet* annotationSet; AnnotationSet::const_iterator annotationSetIt; Annotation* annotation; signatureInfoMapIt = atoms.signatureInfoMap.begin(); signature = &(signatureInfoMapIt->first); fieldNumberToAtomDeclSet = &signatureInfoMapIt->second; EXPECT_EQ(1ul, signature->size()); EXPECT_EQ(JAVA_TYPE_INT, signature->at(0)); EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size()); fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin(); EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first); atomDeclSet = &fieldNumberToAtomDeclSetIt->second; EXPECT_EQ(2ul, atomDeclSet->size()); atomDeclSetIt = atomDeclSet->begin(); atomDecl = atomDeclSetIt->get(); EXPECT_EQ(1, atomDecl->code); fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); annotationSet = &fieldNumberToAnnotationsIt->second; EXPECT_EQ(1ul, annotationSet->size()); annotationSetIt = annotationSet->begin(); annotation = annotationSetIt->get(); EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId); EXPECT_EQ(1, annotation->atomId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); atomDeclSetIt++; atomDecl = atomDeclSetIt->get(); EXPECT_EQ(3, atomDecl->code); fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); annotationSet = &fieldNumberToAnnotationsIt->second; EXPECT_EQ(1ul, annotationSet->size()); annotationSetIt = annotationSet->begin(); annotation = annotationSetIt->get(); EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId); EXPECT_EQ(3, annotation->atomId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); signatureInfoMapIt++; signature = &signatureInfoMapIt->first; fieldNumberToAtomDeclSet = &signatureInfoMapIt->second; EXPECT_EQ(1ul, signature->size()); EXPECT_EQ(JAVA_TYPE_STRING, signature->at(0)); EXPECT_EQ(0ul, fieldNumberToAtomDeclSet->size()); } TEST_P(CollationTest, RecognizeModule1Atom) { Atoms atoms; const string moduleName = "module1"; const int errorCount = collate_atoms(*mModuleAtoms, moduleName, atoms); EXPECT_EQ(errorCount, 0); EXPECT_EQ(atoms.decls.size(), 2ul); EXPECT_EQ(atoms.signatureInfoMap.size(), 1u); EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); SignatureInfoMap::const_iterator signatureInfoMapIt; const vector* signature; const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet; FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt; const AtomDeclSet* atomDeclSet; AtomDeclSet::const_iterator atomDeclSetIt; AtomDecl* atomDecl; FieldNumberToAnnotations* fieldNumberToAnnotations; FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt; const AnnotationSet* annotationSet; AnnotationSet::const_iterator annotationSetIt; Annotation* annotation; signatureInfoMapIt = atoms.signatureInfoMap.begin(); signature = &(signatureInfoMapIt->first); fieldNumberToAtomDeclSet = &signatureInfoMapIt->second; EXPECT_EQ(1ul, signature->size()); EXPECT_EQ(JAVA_TYPE_INT, signature->at(0)); EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size()); fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin(); EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first); atomDeclSet = &fieldNumberToAtomDeclSetIt->second; EXPECT_EQ(2ul, atomDeclSet->size()); atomDeclSetIt = atomDeclSet->begin(); atomDecl = atomDeclSetIt->get(); EXPECT_EQ(1, atomDecl->code); fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); annotationSet = &fieldNumberToAnnotationsIt->second; EXPECT_EQ(1ul, annotationSet->size()); annotationSetIt = annotationSet->begin(); annotation = annotationSetIt->get(); EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId); EXPECT_EQ(1, annotation->atomId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); atomDeclSetIt++; atomDecl = atomDeclSetIt->get(); EXPECT_EQ(3, atomDecl->code); fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); annotationSet = &fieldNumberToAnnotationsIt->second; EXPECT_EQ(1ul, annotationSet->size()); annotationSetIt = annotationSet->begin(); annotation = annotationSetIt->get(); EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId); EXPECT_EQ(3, annotation->atomId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); } /** * Test a correct collation with pushed and pulled atoms. */ TEST_P(CollationTest, CollatePushedAndPulledAtoms) { Atoms atoms; const int errorCount = collate_atoms(*mPushedAndPulledAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); EXPECT_EQ(1ul, atoms.signatureInfoMap.size()); EXPECT_EQ(2ul, atoms.pulledAtomsSignatureInfoMap.size()); // IntAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); // AnotherIntAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT); // OutOfOrderAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT); EXPECT_EQ(3ul, atoms.decls.size()); AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); EXPECT_EQ(1, (*atomIt)->code); EXPECT_EQ("int_atom_1", (*atomIt)->name); EXPECT_EQ("IntAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(10000, (*atomIt)->code); EXPECT_EQ("another_int_atom", (*atomIt)->name); EXPECT_EQ("AnotherIntAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(99999, (*atomIt)->code); EXPECT_EQ("out_of_order_atom", (*atomIt)->name); EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(atoms.decls.end(), atomIt); } TEST_P(CollationTest, CollateVendorAtoms) { Atoms atoms; const int errorCount = collate_atoms(*mVendorAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); EXPECT_EQ(1ul, atoms.signatureInfoMap.size()); EXPECT_EQ(1ul, atoms.pulledAtomsSignatureInfoMap.size()); // IntAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); // AnotherIntAtom EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT); EXPECT_EQ(2ul, atoms.decls.size()); AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); EXPECT_EQ(100000, (*atomIt)->code); EXPECT_EQ("pushed_atom_100000", (*atomIt)->name); EXPECT_EQ("IntAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(199999, (*atomIt)->code); EXPECT_EQ("pulled_atom_199999", (*atomIt)->name); EXPECT_EQ("AnotherIntAtom", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(atoms.decls.end(), atomIt); } TEST(CollationTest, CollateExtensionAtoms) { Atoms atoms; const int errorCount = collate_atoms(*ExtensionAtoms::descriptor(), "test_feature", atoms); EXPECT_EQ(0, errorCount); EXPECT_EQ(1ul, atoms.signatureInfoMap.size()); EXPECT_EQ(1ul, atoms.pulledAtomsSignatureInfoMap.size()); // ExtensionAtomPushed EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_LONG); // ExtensionAtomPulled EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_LONG); EXPECT_EQ(2ul, atoms.decls.size()); AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); EXPECT_EQ(9999, (*atomIt)->code); EXPECT_EQ("extension_atom_pushed", (*atomIt)->name); EXPECT_EQ("ExtensionAtomPushed", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); FieldNumberToAnnotations* fieldNumberToAnnotations = &(*atomIt)->fieldNumberToAnnotations; FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); const AnnotationSet* annotationSet = &fieldNumberToAnnotationsIt->second; EXPECT_EQ(1ul, annotationSet->size()); Annotation* annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId); EXPECT_EQ(9999, annotation->atomId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); atomIt++; EXPECT_EQ(99999, (*atomIt)->code); EXPECT_EQ("extension_atom_pulled", (*atomIt)->name); EXPECT_EQ("ExtensionAtomPulled", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(atoms.decls.end(), atomIt); } TEST_P(CollationTest, CollateGoodRestrictedAtoms) { Atoms atoms; const int errorCount = collate_atoms(*mGoodRestrictedAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); ASSERT_EQ(1ul, atoms.signatureInfoMap.size()); ASSERT_EQ(0ul, atoms.pulledAtomsSignatureInfoMap.size()); EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_LONG, JAVA_TYPE_INT, JAVA_TYPE_BOOLEAN, JAVA_TYPE_STRING, JAVA_TYPE_INT, JAVA_TYPE_FLOAT, JAVA_TYPE_INT); // Validate signatureInfoMap FieldNumberToAtomDeclSet fieldNumberToAtomDeclSet = atoms.signatureInfoMap.begin()->second; ASSERT_EQ(8ul, fieldNumberToAtomDeclSet.size()); const AtomDeclSet* atomDeclSet = &fieldNumberToAtomDeclSet[ATOM_ID_FIELD_NUMBER]; ASSERT_EQ(2ul, atomDeclSet->size()); AtomDeclSet::const_iterator atomDeclSetIt = atomDeclSet->begin(); const AtomDecl* atomDecl = atomDeclSetIt->get(); EXPECT_EQ(1, atomDecl->code); EXPECT_EQ("pushed_atom_1", atomDecl->name); EXPECT_EQ("GoodRestrictedAtom", atomDecl->message); FieldNumberToAnnotations fieldNumberToAnnotations = atomDecl->fieldNumberToAnnotations; ASSERT_EQ(8ul, fieldNumberToAnnotations.size()); const AnnotationSet* annotationSet = &fieldNumberToAnnotations[ATOM_ID_FIELD_NUMBER]; ASSERT_EQ(1ul, annotationSet->size()); Annotation* annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_RESTRICTION_CATEGORY, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type); EXPECT_EQ(os::statsd::RESTRICTION_DIAGNOSTIC, annotation->value.intValue); annotationSet = &fieldNumberToAnnotations[1]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); annotationSet = &fieldNumberToAnnotations[2]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); annotationSet = &fieldNumberToAnnotations[3]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); annotationSet = &fieldNumberToAnnotations[4]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); annotationSet = &fieldNumberToAnnotations[5]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); annotationSet = &fieldNumberToAnnotations[6]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); annotationSet = &fieldNumberToAnnotations[7]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); EXPECT_TRUE(annotation->value.boolValue); atomDeclSetIt++; atomDecl = atomDeclSetIt->get(); EXPECT_EQ(2, atomDecl->code); EXPECT_EQ("pushed_atom_2", atomDecl->name); EXPECT_EQ("GoodRestrictedAtom", atomDecl->message); fieldNumberToAnnotations = atomDecl->fieldNumberToAnnotations; ASSERT_EQ(8ul, fieldNumberToAnnotations.size()); annotationSet = &fieldNumberToAnnotations[ATOM_ID_FIELD_NUMBER]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_RESTRICTION_CATEGORY, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type); EXPECT_EQ(os::statsd::RESTRICTION_SYSTEM_INTELLIGENCE, annotation->value.intValue); atomDeclSetIt++; EXPECT_EQ(atomDeclSet->end(), atomDeclSetIt); // Validate decls ASSERT_EQ(2ul, atoms.decls.size()); AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); EXPECT_EQ(1, (*atomIt)->code); EXPECT_EQ("pushed_atom_1", (*atomIt)->name); EXPECT_EQ("GoodRestrictedAtom", (*atomIt)->message); fieldNumberToAnnotations = (*atomIt)->fieldNumberToAnnotations; ASSERT_EQ(8ul, fieldNumberToAnnotations.size()); annotationSet = &fieldNumberToAnnotations[ATOM_ID_FIELD_NUMBER]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_RESTRICTION_CATEGORY, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type); EXPECT_EQ(os::statsd::RESTRICTION_DIAGNOSTIC, annotation->value.intValue); atomIt++; EXPECT_EQ(2, (*atomIt)->code); EXPECT_EQ("pushed_atom_2", (*atomIt)->name); EXPECT_EQ("GoodRestrictedAtom", (*atomIt)->message); fieldNumberToAnnotations = (*atomIt)->fieldNumberToAnnotations; ASSERT_EQ(8ul, fieldNumberToAnnotations.size()); annotationSet = &fieldNumberToAnnotations[ATOM_ID_FIELD_NUMBER]; ASSERT_EQ(1ul, annotationSet->size()); annotation = annotationSet->begin()->get(); EXPECT_EQ(ANNOTATION_ID_RESTRICTION_CATEGORY, annotation->annotationId); EXPECT_EQ(ANNOTATION_TYPE_INT, annotation->type); EXPECT_EQ(os::statsd::RESTRICTION_SYSTEM_INTELLIGENCE, annotation->value.intValue); atomIt++; EXPECT_EQ(atoms.decls.end(), atomIt); // Validate non_chained_decls ASSERT_EQ(0ul, atoms.non_chained_decls.size()); // Validate nonChainedSignatureInfoMap ASSERT_EQ(0ul, atoms.nonChainedSignatureInfoMap.size()); } TEST_P(CollationTest, CollateBadRestrictedAtoms) { Atoms atoms; // Nonprimitive fields int errorCount = collate_atoms(*mBadRestrictedAtoms1, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(6, errorCount); // Restriction category on atom field errorCount = collate_atoms(*mBadRestrictedAtoms2, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(1, errorCount); // Field restriction without restriction category errorCount = collate_atoms(*mBadRestrictedAtoms3, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(7, errorCount); // Field restriction option on top level atom field errorCount = collate_atoms(*mBadRestrictedAtoms4, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(1, errorCount); // Pulled restricted atoms errorCount = collate_atoms(*mBadRestrictedAtoms5, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(2, errorCount); } TEST_P(CollationTest, CollateGoodUintAtoms) { Atoms atoms; int errorCount = collate_atoms(*mGoodUintAtoms, DEFAULT_MODULE_NAME, atoms); EXPECT_EQ(0, errorCount); EXPECT_EQ(2ul, atoms.signatureInfoMap.size()); // AppDied EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); // SystemUptime EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_LONG); EXPECT_EQ(2ul, atoms.decls.size()); AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); EXPECT_EQ(1, (*atomIt)->code); EXPECT_EQ("app_died", (*atomIt)->name); EXPECT_EQ("AppDied", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(2, (*atomIt)->code); EXPECT_EQ("system_uptime", (*atomIt)->name); EXPECT_EQ("SystemUptime", (*atomIt)->message); EXPECT_NO_ENUM_FIELD((*atomIt)); atomIt++; EXPECT_EQ(atoms.decls.end(), atomIt); } } // namespace stats_log_api_gen } // namespace android