/*
 * 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 "frameworks/base/tools/stats_log_api_gen/test.pb.h"
#include "Collation.h"

#include <stdio.h>

namespace android {
namespace stats_log_api_gen {

using std::map;
using std::set;
using std::vector;

/**
 * Return whether the set contains a vector of the elements provided.
 */
static bool
set_contains_vector(const set<vector<java_type_t>>& 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 set contains the elements provided.
 */
#define EXPECT_SET_CONTAINS_SIGNATURE(s, ...) \
    do { \
        int count = sizeof((int[]){__VA_ARGS__})/sizeof(int); \
        EXPECT_TRUE(set_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(), &atoms);

    EXPECT_EQ(0, errorCount);
    EXPECT_EQ(3ul, atoms.signatures.size());

    // IntAtom, AnotherIntAtom
    EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures, JAVA_TYPE_INT);

    // OutOfOrderAtom
    EXPECT_SET_CONTAINS_SIGNATURE(atoms.signatures, JAVA_TYPE_INT, JAVA_TYPE_INT);

    // AllTypesAtom
    EXPECT_SET_CONTAINS_SIGNATURE(
        atoms.signatures,
        JAVA_TYPE_ATTRIBUTION_CHAIN, // AttributionChain
        JAVA_TYPE_DOUBLE,            // double
        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
    );

    set<AtomDecl>::const_iterator atom = atoms.decls.begin();
    EXPECT_EQ(1, atom->code);
    EXPECT_EQ("int_atom", atom->name);
    EXPECT_EQ("IntAtom", atom->message);
    EXPECT_NO_ENUM_FIELD(atom);
    atom++;

    EXPECT_EQ(2, atom->code);
    EXPECT_EQ("out_of_order_atom", atom->name);
    EXPECT_EQ("OutOfOrderAtom", atom->message);
    EXPECT_NO_ENUM_FIELD(atom);
    atom++;

    EXPECT_EQ(3, atom->code);
    EXPECT_EQ("another_int_atom", atom->name);
    EXPECT_EQ("AnotherIntAtom", atom->message);
    EXPECT_NO_ENUM_FIELD(atom);
    atom++;

    EXPECT_EQ(4, atom->code);
    EXPECT_EQ("all_types_atom", atom->name);
    EXPECT_EQ("AllTypesAtom", atom->message);
    map<int, string> enumValues;
    enumValues[0] = "VALUE0";
    enumValues[1] = "VALUE1";
    EXPECT_HAS_ENUM_FIELD(atom, "enum_field", enumValues);
    atom++;

    EXPECT_TRUE(atom == atoms.decls.end());
}

/**
 * Test that event class that contains stuff other than the atoms is rejected.
 */
TEST(CollationTest, NonMessageTypeFails) {
    Atoms atoms;
    int errorCount = collate_atoms(IntAtom::descriptor(), &atoms);

    EXPECT_EQ(1, errorCount);
}

/**
 * Test that atoms that have non-primitive types are rejected.
 */
TEST(CollationTest, FailOnBadTypes) {
    Atoms atoms;
    int errorCount = collate_atoms(BadTypesEvent::descriptor(), &atoms);

    EXPECT_EQ(2, 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(), &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(), &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(), &atoms);

  EXPECT_EQ(1, errorCount);
}

TEST(CollationTest, FailOnBadStateAtomOptions) {
    Atoms atoms;
    int errorCount = collate_atoms(BadStateAtoms::descriptor(), &atoms);

    EXPECT_EQ(3, errorCount);
}

TEST(CollationTest, PassOnGoodStateAtomOptions) {
    Atoms atoms;
    int errorCount = collate_atoms(GoodStateAtoms::descriptor(), &atoms);
    EXPECT_EQ(0, errorCount);
}

}  // namespace stats_log_api_gen
}  // namespace android