blob: e8bb667ec678b5ee7d2ac3ec6a9252d104bb9fa4 [file] [log] [blame]
/*
* 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 <google/protobuf/compiler/importer.h>
#include <gtest/gtest.h>
#include <stdio.h>
#include <filesystem>
#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<java_type_t> v(count);
va_start(args, count);
for (int i = 0; i < count; i++) {
v[i] = static_cast<java_type_t>(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<AtomField>::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<AtomField>::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<bool> {
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<int, string> 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<java_type_t>* 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<java_type_t>* 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