Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86233e53 authored by Yu Shan's avatar Yu Shan
Browse files

Add more debug options to FakeVehicleHardware.

Add more debug options to FakeVehicleHardware that includes save
property values and restore property values. Get property with
arguments. Provide JSON content to fake event generator.

Test: atest FakeVehicleHardwareTest
Bug: 199314530
Change-Id: I467b3aff1b7178f8716831e9c501d8199c35c359
parent bc352866
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@ class JsonFakeValueGenerator : public FakeValueGenerator {
    // Create a new JSON fake value generator using the specified JSON file path. All the events
    // in the JSON file would be generated once.
    explicit JsonFakeValueGenerator(const std::string& path);
    // Create a new JSON fake value generator using the JSON content. The first argument is just
    // used to differentiate this function with the one that takes path as input.
    explicit JsonFakeValueGenerator(bool unused, const std::string& content, int32_t iteration);

    ~JsonFakeValueGenerator() = default;

@@ -63,7 +66,8 @@ class JsonFakeValueGenerator : public FakeValueGenerator {
    int32_t mNumOfIterations = 0;

    void setBit(std::vector<uint8_t>& bytes, size_t idx);
    void init(const std::string& path, int32_t iteration);
    void initWithPath(const std::string& path, int32_t iteration);
    void initWithStream(std::istream& is, int32_t iteration);
};

}  // namespace fake
+16 −8
Original line number Diff line number Diff line
@@ -173,12 +173,11 @@ std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is) {

}  // namespace

JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
    init(path, 1);
}
JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path)
    : JsonFakeValueGenerator(path, /*iteration=*/1) {}

JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t iteration) {
    init(path, iteration);
    initWithPath(path, iteration);
}

JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
@@ -186,16 +185,26 @@ JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request)
    // Iterate infinitely if iteration number is not provided
    int32_t numOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];

    init(v.stringValue, numOfIterations);
    initWithPath(v.stringValue, numOfIterations);
}

JsonFakeValueGenerator::JsonFakeValueGenerator([[maybe_unused]] bool unused,
                                               const std::string& content, int32_t iteration) {
    std::istringstream iss(content);
    initWithStream(iss, iteration);
}

void JsonFakeValueGenerator::init(const std::string& path, int32_t iteration) {
void JsonFakeValueGenerator::initWithPath(const std::string& path, int32_t iteration) {
    std::ifstream ifs(path);
    if (!ifs) {
        ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
        return;
    }
    mEvents = parseFakeValueJson(ifs);
    initWithStream(ifs, iteration);
}

void JsonFakeValueGenerator::initWithStream(std::istream& is, int32_t iteration) {
    mEvents = parseFakeValueJson(is);
    mNumOfIterations = iteration;
}

@@ -235,7 +244,6 @@ std::optional<VehiclePropValue> JsonFakeValueGenerator::nextEvent() {
            mNumOfIterations--;
        }
    }

    generatedValue.timestamp = mLastEventTimestamp;

    return generatedValue;
+11 −1
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ class FakeVehicleHardware : public IVehicleHardware {
    std::unique_ptr<const PropertySetErrorCallback> mOnPropertySetErrorCallback GUARDED_BY(mLock);
    std::unordered_map<PropIdAreaId, std::shared_ptr<RecurrentTimer::Callback>, PropIdAreaIdHash>
            mRecurrentActions GUARDED_BY(mLock);
    std::unordered_map<PropIdAreaId, VehiclePropValuePool::RecyclableType, PropIdAreaIdHash>
            mSavedProps GUARDED_BY(mLock);
    // PendingRequestHandler is thread-safe.
    mutable PendingRequestHandler<GetValuesCallback,
                                  aidl::android::hardware::automotive::vehicle::GetValueRequest>
@@ -160,6 +162,10 @@ class FakeVehicleHardware : public IVehicleHardware {
    void maybeOverrideProperties(const char* overrideDir);
    // Override the properties using config files in 'overrideDir'.
    void overrideProperties(const char* overrideDir);
    // Function to be called when a value change event comes from vehicle bus. In our fake
    // implementation, this function is only called during "--inject-event" dump command.
    void eventFromVehicleBus(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);

    VhalResult<void> maybeSetSpecialValue(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
@@ -188,6 +194,10 @@ class FakeVehicleHardware : public IVehicleHardware {
    std::string dumpListProperties();
    std::string dumpSpecificProperty(const std::vector<std::string>& options);
    std::string dumpSetProperties(const std::vector<std::string>& options);
    std::string dumpGetPropertyWithArg(const std::vector<std::string>& options);
    std::string dumpSaveProperty(const std::vector<std::string>& options);
    std::string dumpRestoreProperty(const std::vector<std::string>& options);
    std::string dumpInjectEvent(const std::vector<std::string>& options);

    template <typename T>
    android::base::Result<T> safelyParseInt(int index, const std::string& s) {
@@ -202,7 +212,7 @@ class FakeVehicleHardware : public IVehicleHardware {
    std::vector<std::string> getOptionValues(const std::vector<std::string>& options,
                                             size_t* index);
    android::base::Result<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
    parseSetPropOptions(const std::vector<std::string>& options);
    parsePropOptions(const std::vector<std::string>& options);
    android::base::Result<std::vector<uint8_t>> parseHexString(const std::string& s);

    android::base::Result<void> checkArgumentsSize(const std::vector<std::string>& options,
+236 −65

File changed.

Preview size limit exceeded, changes collapsed.

+117 −8
Original line number Diff line number Diff line
@@ -1421,6 +1421,85 @@ TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesNoArg) {
    ASSERT_THAT(result.buffer, ContainsRegex("Invalid number of arguments"));
}

TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertyWithArg) {
    auto getValueResult = getValue(VehiclePropValue{.prop = OBD2_FREEZE_FRAME_INFO});
    ASSERT_TRUE(getValueResult.ok());
    auto propValue = getValueResult.value();
    ASSERT_EQ(propValue.value.int64Values.size(), static_cast<size_t>(3))
            << "expect 3 obd2 freeze frames stored";

    std::string propIdStr = StringPrintf("%d", OBD2_FREEZE_FRAME);
    DumpResult result;
    for (int64_t timestamp : propValue.value.int64Values) {
        result = getHardware()->dump(
                {"--getWithArg", propIdStr, "-i64", StringPrintf("%" PRId64, timestamp)});

        ASSERT_FALSE(result.callerShouldDumpState);
        ASSERT_NE(result.buffer, "");
        ASSERT_THAT(result.buffer, ContainsRegex("Get property result:"));
    }

    // Set the timestamp argument to 0.
    result = getHardware()->dump({"--getWithArg", propIdStr, "-i64", "0"});

    ASSERT_FALSE(result.callerShouldDumpState);
    // There is no freeze obd2 frame at timestamp 0.
    ASSERT_THAT(result.buffer, ContainsRegex("failed to read property value"));
}

TEST_F(FakeVehicleHardwareTest, testSaveRestoreProp) {
    int32_t prop = toInt(VehicleProperty::TIRE_PRESSURE);
    std::string propIdStr = std::to_string(prop);
    std::string areaIdStr = std::to_string(WHEEL_FRONT_LEFT);

    DumpResult result = getHardware()->dump({"--save-prop", propIdStr, "-a", areaIdStr});

    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, ContainsRegex("saved"));

    ASSERT_EQ(setValue(VehiclePropValue{
                      .prop = prop,
                      .areaId = WHEEL_FRONT_LEFT,
                      .value =
                              {
                                      .floatValues = {210.0},
                              },
              }),
              StatusCode::OK);

    result = getHardware()->dump({"--restore-prop", propIdStr, "-a", areaIdStr});

    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, ContainsRegex("restored"));

    auto getResult = getValue(VehiclePropValue{.prop = prop, .areaId = WHEEL_FRONT_LEFT});

    ASSERT_TRUE(getResult.ok());
    // The default value is 200.0.
    ASSERT_EQ(getResult.value().value.floatValues, std::vector<float>{200.0});
}

TEST_F(FakeVehicleHardwareTest, testDumpInjectEvent) {
    int32_t prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
    std::string propIdStr = std::to_string(prop);

    int64_t timestamp = elapsedRealtimeNano();
    // Inject an event with float value 123.4 and timestamp.
    DumpResult result = getHardware()->dump(
            {"--inject-event", propIdStr, "-f", "123.4", "-t", std::to_string(timestamp)});

    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer,
                ContainsRegex(StringPrintf("Event for property: %d injected", prop)));
    ASSERT_TRUE(waitForChangedProperties(prop, 0, /*count=*/1, milliseconds(1000)))
            << "No changed event received for injected event from vehicle bus";
    auto events = getChangedProperties();
    ASSERT_EQ(events.size(), 1u);
    auto event = events[0];
    ASSERT_EQ(event.timestamp, timestamp);
    ASSERT_EQ(event.value.floatValues, std::vector<float>({123.4}));
}

TEST_F(FakeVehicleHardwareTest, testDumpInvalidOptions) {
    std::vector<std::string> options;
    options.push_back("--invalid");
@@ -1681,10 +1760,10 @@ std::vector<OptionsTestCase> GenInvalidOptions() {
             {"--genfakedata", "--startjson"},
             "incorrect argument count"},
            {"genfakedata_startjson_invalid_repetition",
             {"--genfakedata", "--startjson", "file", "0.1"},
             {"--genfakedata", "--startjson", "--path", "file", "0.1"},
             "failed to parse repetition as int: \"0.1\""},
            {"genfakedata_startjson_invalid_json_file",
             {"--genfakedata", "--startjson", "file", "1"},
             {"--genfakedata", "--startjson", "--path", "file", "1"},
             "invalid JSON file"},
            {"genfakedata_stopjson_no_args",
             {"--genfakedata", "--stopjson"},
@@ -1765,7 +1844,7 @@ std::string getTestFilePath(const char* filename) {
}

TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJson) {
    std::vector<std::string> options = {"--genfakedata", "--startjson",
    std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
                                        getTestFilePath("prop.json"), "2"};

    DumpResult result = getHardware()->dump(options);
@@ -1790,8 +1869,36 @@ TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJson) {
    EXPECT_EQ(10, events[7].value.int32Values[0]);
}

TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonByContent) {
    std::vector<std::string> options = {
            "--genfakedata", "--startjson", "--content",
            "[{\"timestamp\":1000000,\"areaId\":0,\"value\":8,\"prop\":289408000}]", "1"};

    DumpResult result = getHardware()->dump(options);

    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, HasSubstr("successfully"));

    ASSERT_TRUE(waitForChangedProperties(/*count=*/1, milliseconds(1000)))
            << "not enough events generated for JSON data generator";

    auto events = getChangedProperties();
    ASSERT_EQ(1u, events.size());
    EXPECT_EQ(1u, events[0].value.int32Values.size());
    EXPECT_EQ(8, events[0].value.int32Values[0]);
}

TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidContent) {
    std::vector<std::string> options = {"--genfakedata", "--startjson", "--content", "[{", "2"};

    DumpResult result = getHardware()->dump(options);

    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, HasSubstr("invalid JSON content"));
}

TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidFile) {
    std::vector<std::string> options = {"--genfakedata", "--startjson",
    std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
                                        getTestFilePath("blahblah.json"), "2"};

    DumpResult result = getHardware()->dump(options);
@@ -1802,7 +1909,7 @@ TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonInvalidFile) {

TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStop) {
    // No iteration number provided, would loop indefinitely.
    std::vector<std::string> options = {"--genfakedata", "--startjson",
    std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
                                        getTestFilePath("prop.json")};

    DumpResult result = getHardware()->dump(options);
@@ -1810,7 +1917,9 @@ TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStop) {
    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, HasSubstr("successfully"));

    result = getHardware()->dump({"--genfakedata", "--stopjson", getTestFilePath("prop.json")});
    std::string id = result.buffer.substr(result.buffer.find("ID: ") + 4);

    result = getHardware()->dump({"--genfakedata", "--stopjson", id});

    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, HasSubstr("successfully"));
@@ -1818,7 +1927,7 @@ TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStop) {

TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStopInvalidFile) {
    // No iteration number provided, would loop indefinitely.
    std::vector<std::string> options = {"--genfakedata", "--startjson",
    std::vector<std::string> options = {"--genfakedata", "--startjson", "--path",
                                        getTestFilePath("prop.json")};

    DumpResult result = getHardware()->dump(options);
@@ -1826,7 +1935,7 @@ TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJsonStopInvalidFile) {
    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, HasSubstr("successfully"));

    result = getHardware()->dump({"--genfakedata", "--stopjson", getTestFilePath("prop1.json")});
    result = getHardware()->dump({"--genfakedata", "--stopjson", "1234"});

    ASSERT_FALSE(result.callerShouldDumpState);
    ASSERT_THAT(result.buffer, HasSubstr("No JSON event generator found"));