blob: dbae58889333bd12f09a6eeb4188bb09a98948ad [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 <gtest/gtest.h>
#include <stdio.h>
#include "Collation.h"
#include "frameworks/base/tools/stats_log_api_gen/test.pb.h"
namespace android {
namespace stats_log_api_gen {
using std::map;
using std::set;
using std::vector;
/**
* 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;
va_start(args, count);
for (int i = 0; i < count; i++) {
v.push_back((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)
/**
* Test a correct collation, with all the types.
*/
TEST(CollationTest, CollateStats) {
Atoms atoms;
int errorCount = collate_atoms(Event::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(0, errorCount);
EXPECT_EQ(3ul, 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_LONG, // uint64
JAVA_TYPE_INT, // int32
JAVA_TYPE_LONG, // fixed64
JAVA_TYPE_INT, // fixed32
JAVA_TYPE_BOOLEAN, // bool
JAVA_TYPE_STRING, // string
JAVA_TYPE_INT, // uint32
JAVA_TYPE_INT, // AnEnum
JAVA_TYPE_INT, // sfixed32
JAVA_TYPE_LONG, // sfixed64
JAVA_TYPE_INT, // sint32
JAVA_TYPE_LONG // sint64
);
EXPECT_EQ(4ul, 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(atoms.decls.end(), atomIt);
}
/**
* Test that event class that contains stuff other than the atoms is rejected.
*/
TEST(CollationTest, NonMessageTypeFails) {
Atoms atoms;
int errorCount = collate_atoms(IntAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(1, errorCount);
}
/**
* Test that atoms that have non-primitive types or repeated fields are
* rejected.
*/
TEST(CollationTest, FailOnBadTypes) {
Atoms atoms;
int errorCount = collate_atoms(BadTypesEvent::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(4, errorCount);
}
/**
* Test that atoms that skip field numbers (in the first position) are rejected.
*/
TEST(CollationTest, FailOnSkippedFieldsSingle) {
Atoms atoms;
int errorCount =
collate_atoms(BadSkippedFieldSingle::descriptor(), 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(CollationTest, FailOnSkippedFieldsMultiple) {
Atoms atoms;
int errorCount =
collate_atoms(BadSkippedFieldMultiple::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(2, errorCount);
}
/**
* Test that atoms that have an attribution chain not in the first position are
* rejected.
*/
TEST(CollationTest, FailBadAttributionNodePosition) {
Atoms atoms;
int errorCount =
collate_atoms(BadAttributionNodePosition::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(1, errorCount);
}
TEST(CollationTest, FailOnBadStateAtomOptions) {
Atoms atoms;
int errorCount = collate_atoms(BadStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(3, errorCount);
}
TEST(CollationTest, PassOnGoodStateAtomOptions) {
Atoms atoms;
int errorCount = collate_atoms(GoodStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(0, errorCount);
}
TEST(CollationTest, PassOnGoodBinaryFieldAtom) {
Atoms atoms;
int errorCount =
collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(0, errorCount);
}
TEST(CollationTest, FailOnBadBinaryFieldAtom) {
Atoms atoms;
int errorCount =
collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_TRUE(errorCount > 0);
}
TEST(CollationTest, PassOnLogFromModuleAtom) {
Atoms atoms;
int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
EXPECT_EQ(errorCount, 0);
EXPECT_EQ(atoms.decls.size(), 4ul);
}
TEST(CollationTest, RecognizeModuleAtom) {
Atoms atoms;
int errorCount = collate_atoms(ModuleAtoms::descriptor(), 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(CollationTest, RecognizeModule1Atom) {
Atoms atoms;
const string moduleName = "module1";
int errorCount = collate_atoms(ModuleAtoms::descriptor(), 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);
}
} // namespace stats_log_api_gen
} // namespace android