Refactor existing tests to use gtest
Bug: 26962907 Change-Id: I5f80636af1740badeff7d08193f08e23f4e4fee1
This commit is contained in:
parent
e3434279c8
commit
432918603f
25 changed files with 147 additions and 217 deletions
20
Android.mk
20
Android.mk
|
@ -104,28 +104,10 @@ LOCAL_CLANG := true
|
|||
LOCAL_MODULE := libverifier
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_SRC_FILES := \
|
||||
asn1_decoder.cpp
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CLANG := true
|
||||
LOCAL_MODULE := verifier_test
|
||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_CFLAGS += -Wno-unused-parameter
|
||||
LOCAL_SRC_FILES := \
|
||||
verifier_test.cpp \
|
||||
asn1_decoder.cpp \
|
||||
verifier.cpp \
|
||||
ui.cpp
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libmincrypt \
|
||||
libminui \
|
||||
libminzip \
|
||||
libcutils \
|
||||
libc
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(LOCAL_PATH)/minui/Android.mk \
|
||||
$(LOCAL_PATH)/minzip/Android.mk \
|
||||
|
|
17
README.md
17
README.md
|
@ -10,3 +10,20 @@ Quick turn-around testing
|
|||
# without flashing the recovery partition:
|
||||
adb reboot bootloader
|
||||
fastboot boot $ANDROID_PRODUCT_OUT/recovery.img
|
||||
|
||||
Running the tests
|
||||
-----------------
|
||||
# After setting up environment and lunch.
|
||||
mmma -j bootable/recovery
|
||||
|
||||
# Running the tests on device.
|
||||
adb root
|
||||
adb sync data
|
||||
|
||||
# 32-bit device
|
||||
adb shell /data/nativetest/recovery_unit_test/recovery_unit_test
|
||||
adb shell /data/nativetest/recovery_component_test/recovery_component_test
|
||||
|
||||
# Or 64-bit device
|
||||
adb shell /data/nativetest64/recovery_unit_test/recovery_unit_test
|
||||
adb shell /data/nativetest64/recovery_component_test/recovery_component_test
|
||||
|
|
|
@ -16,11 +16,40 @@
|
|||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# Unit tests
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CLANG := true
|
||||
LOCAL_MODULE := recovery_unit_test
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
LOCAL_STATIC_LIBRARIES := libverifier
|
||||
LOCAL_SRC_FILES := unit/asn1_decoder_test.cpp
|
||||
LOCAL_C_INCLUDES := bootable/recovery
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
||||
# Component tests
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CLANG := true
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
LOCAL_STATIC_LIBRARIES := libverifier
|
||||
LOCAL_SRC_FILES := asn1_decoder_test.cpp
|
||||
LOCAL_MODULE := asn1_decoder_test
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
|
||||
LOCAL_MODULE := recovery_component_test
|
||||
LOCAL_C_INCLUDES := bootable/recovery
|
||||
LOCAL_SRC_FILES := component/verifier_test.cpp
|
||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libbase \
|
||||
libverifier \
|
||||
libmincrypt \
|
||||
libminui \
|
||||
libminzip \
|
||||
libcutils \
|
||||
libc
|
||||
|
||||
testdata_out_path := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
|
||||
testdata_files := $(call find-subdir-files, testdata/*)
|
||||
|
||||
GEN := $(addprefix $(testdata_out_path)/, $(testdata_files))
|
||||
$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
|
||||
$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@
|
||||
$(GEN): $(testdata_out_path)/% : $(LOCAL_PATH)/%
|
||||
$(transform-generated-source)
|
||||
LOCAL_GENERATED_SOURCES += $(GEN)
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* 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
|
||||
* Unless required by applicable law or agree 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
|
||||
|
@ -16,22 +16,33 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "verifier.h"
|
||||
#include "ui.h"
|
||||
#include "mincrypt/sha.h"
|
||||
#include "mincrypt/sha256.h"
|
||||
#include "minzip/SysUtil.h"
|
||||
#include "ui.h"
|
||||
#include "verifier.h"
|
||||
|
||||
#if defined(__LP64__)
|
||||
#define NATIVE_TEST_PATH "/nativetest64"
|
||||
#else
|
||||
#define NATIVE_TEST_PATH "/nativetest"
|
||||
#endif
|
||||
|
||||
static const char* DATA_PATH = getenv("ANDROID_DATA");
|
||||
static const char* TESTDATA_PATH = "/recovery_component_test/testdata/";
|
||||
|
||||
// This is build/target/product/security/testkey.x509.pem after being
|
||||
// dumped out by dumpkey.jar.
|
||||
|
@ -123,9 +134,7 @@ ECPublicKey test_ec_key =
|
|||
|
||||
RecoveryUI* ui = NULL;
|
||||
|
||||
// verifier expects to find a UI object; we provide one that does
|
||||
// nothing but print.
|
||||
class FakeUI : public RecoveryUI {
|
||||
class MockUI : public RecoveryUI {
|
||||
void Init() { }
|
||||
void SetStage(int, int) { }
|
||||
void SetLocale(const char*) { }
|
||||
|
@ -166,79 +175,93 @@ ui_print(const char* format, ...) {
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s [-sha256] [-ec | -f4 | -file <keys>] <package>\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
class VerifierTest : public testing::TestWithParam<std::vector<std::string>> {
|
||||
public:
|
||||
MemMapping memmap;
|
||||
std::vector<Certificate> certs;
|
||||
int argn = 1;
|
||||
while (argn < argc) {
|
||||
if (strcmp(argv[argn], "-sha256") == 0) {
|
||||
if (certs.empty()) {
|
||||
fprintf(stderr, "May only specify -sha256 after key type\n");
|
||||
return 2;
|
||||
|
||||
virtual void SetUp() {
|
||||
std::vector<std::string> args = GetParam();
|
||||
std::string package = android::base::StringPrintf("%s%s%s%s", DATA_PATH, NATIVE_TEST_PATH,
|
||||
TESTDATA_PATH, args[0].c_str());
|
||||
for (auto it = ++(args.cbegin()); it != args.cend(); ++it) {
|
||||
if (it->substr(it->length() - 3, it->length()) == "256") {
|
||||
if (certs.empty()) {
|
||||
FAIL() << "May only specify -sha256 after key type\n";
|
||||
}
|
||||
certs.back().hash_len = SHA256_DIGEST_SIZE;
|
||||
} else if (*it == "ec") {
|
||||
certs.emplace_back(SHA_DIGEST_SIZE, Certificate::EC,
|
||||
nullptr, std::unique_ptr<ECPublicKey>(new ECPublicKey(test_ec_key)));
|
||||
} else if (*it == "e3") {
|
||||
certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
|
||||
std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
|
||||
} else if (*it == "f4") {
|
||||
certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
|
||||
std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_f4_key)), nullptr);
|
||||
}
|
||||
++argn;
|
||||
certs.back().hash_len = SHA256_DIGEST_SIZE;
|
||||
} else if (strcmp(argv[argn], "-ec") == 0) {
|
||||
++argn;
|
||||
certs.emplace_back(SHA_DIGEST_SIZE, Certificate::EC,
|
||||
nullptr, std::unique_ptr<ECPublicKey>(new ECPublicKey(test_ec_key)));
|
||||
} else if (strcmp(argv[argn], "-e3") == 0) {
|
||||
++argn;
|
||||
}
|
||||
if (certs.empty()) {
|
||||
certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
|
||||
std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
|
||||
} else if (strcmp(argv[argn], "-f4") == 0) {
|
||||
++argn;
|
||||
certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
|
||||
std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_f4_key)), nullptr);
|
||||
} else if (strcmp(argv[argn], "-file") == 0) {
|
||||
if (!certs.empty()) {
|
||||
fprintf(stderr, "Cannot specify -file with other certs specified\n");
|
||||
return 2;
|
||||
}
|
||||
++argn;
|
||||
if (!load_keys(argv[argn], certs)) {
|
||||
fprintf(stderr, "Cannot load keys from %s\n", argv[argn]);
|
||||
}
|
||||
++argn;
|
||||
} else if (argv[argn][0] == '-') {
|
||||
fprintf(stderr, "Unknown argument %s\n", argv[argn]);
|
||||
return 2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (sysMapFile(package.c_str(), &memmap) != 0) {
|
||||
FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (argn == argc) {
|
||||
fprintf(stderr, "Must specify package to verify\n");
|
||||
return 2;
|
||||
static void SetUpTestCase() {
|
||||
ui = new MockUI();
|
||||
}
|
||||
};
|
||||
|
||||
if (certs.empty()) {
|
||||
certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
|
||||
std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
|
||||
}
|
||||
class VerifierSuccessTest : public VerifierTest {
|
||||
};
|
||||
|
||||
ui = new FakeUI();
|
||||
class VerifierFailureTest : public VerifierTest {
|
||||
};
|
||||
|
||||
MemMapping map;
|
||||
if (sysMapFile(argv[argn], &map) != 0) {
|
||||
fprintf(stderr, "failed to mmap %s: %s\n", argv[argn], strerror(errno));
|
||||
return 4;
|
||||
}
|
||||
|
||||
int result = verify_file(map.addr, map.length, certs);
|
||||
if (result == VERIFY_SUCCESS) {
|
||||
printf("VERIFIED\n");
|
||||
return 0;
|
||||
} else if (result == VERIFY_FAILURE) {
|
||||
printf("NOT VERIFIED\n");
|
||||
return 1;
|
||||
} else {
|
||||
printf("bad return value\n");
|
||||
return 3;
|
||||
}
|
||||
TEST_P(VerifierSuccessTest, VerifySucceed) {
|
||||
ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS);
|
||||
}
|
||||
|
||||
TEST_P(VerifierFailureTest, VerifyFailure) {
|
||||
ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_FAILURE);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest,
|
||||
::testing::Values(
|
||||
std::vector<std::string>({"otasigned.zip", "e3"}),
|
||||
std::vector<std::string>({"otasigned_f4.zip", "f4"}),
|
||||
std::vector<std::string>({"otasigned_sha256.zip", "e3", "sha256"}),
|
||||
std::vector<std::string>({"otasigned_f4_sha256.zip", "f4", "sha256"}),
|
||||
std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "ec", "sha256"})));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MultiKeySuccess, VerifierSuccessTest,
|
||||
::testing::Values(
|
||||
std::vector<std::string>({"otasigned.zip", "f4", "e3"}),
|
||||
std::vector<std::string>({"otasigned_f4.zip", "ec", "f4"}),
|
||||
std::vector<std::string>({"otasigned_sha256.zip", "ec", "e3", "e3", "sha256"}),
|
||||
std::vector<std::string>({"otasigned_f4_sha256.zip", "ec", "sha256", "e3", "f4", "sha256"}),
|
||||
std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "f4", "sha256", "e3", "ec", "sha256"})));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(WrongKey, VerifierFailureTest,
|
||||
::testing::Values(
|
||||
std::vector<std::string>({"otasigned.zip", "f4"}),
|
||||
std::vector<std::string>({"otasigned_f4.zip", "e3"}),
|
||||
std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "e3", "sha256"})));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest,
|
||||
::testing::Values(
|
||||
std::vector<std::string>({"otasigned.zip", "e3", "sha256"}),
|
||||
std::vector<std::string>({"otasigned_f4.zip", "f4", "sha256"}),
|
||||
std::vector<std::string>({"otasigned_sha256.zip"}),
|
||||
std::vector<std::string>({"otasigned_f4_sha256.zip", "f4"}),
|
||||
std::vector<std::string>({"otasigned_ecdsa_sha256.zip"})));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest,
|
||||
::testing::Values(
|
||||
std::vector<std::string>({"random.zip"}),
|
||||
std::vector<std::string>({"fake-eocd.zip"}),
|
||||
std::vector<std::string>({"alter-metadata.zip"}),
|
||||
std::vector<std::string>({"alter-footer.zip"})));
|
121
verifier_test.sh
121
verifier_test.sh
|
@ -1,121 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# A test suite for recovery's package signature verifier. Run in a
|
||||
# client where you have done envsetup, lunch, etc.
|
||||
#
|
||||
# TODO: find some way to get this run regularly along with the rest of
|
||||
# the tests.
|
||||
|
||||
EMULATOR_PORT=5580
|
||||
DATA_DIR=$ANDROID_BUILD_TOP/bootable/recovery/testdata
|
||||
|
||||
WORK_DIR=/data/local/tmp
|
||||
|
||||
# set to 0 to use a device instead
|
||||
USE_EMULATOR=0
|
||||
|
||||
# ------------------------
|
||||
|
||||
if [ "$USE_EMULATOR" == 1 ]; then
|
||||
emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT &
|
||||
pid_emulator=$!
|
||||
ADB="adb -s emulator-$EMULATOR_PORT "
|
||||
else
|
||||
ADB="adb -d "
|
||||
fi
|
||||
|
||||
echo "waiting to connect to device"
|
||||
$ADB wait-for-device
|
||||
|
||||
# run a command on the device; exit with the exit status of the device
|
||||
# command.
|
||||
run_command() {
|
||||
$ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}'
|
||||
}
|
||||
|
||||
testname() {
|
||||
echo
|
||||
echo "::: testing $1 :::"
|
||||
testname="$1"
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo
|
||||
echo FAIL: $testname
|
||||
echo
|
||||
[ "$open_pid" == "" ] || kill $open_pid
|
||||
[ "$pid_emulator" == "" ] || kill $pid_emulator
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
cleanup() {
|
||||
# not necessary if we're about to kill the emulator, but nice for
|
||||
# running on real devices or already-running emulators.
|
||||
run_command rm $WORK_DIR/verifier_test
|
||||
run_command rm $WORK_DIR/package.zip
|
||||
|
||||
[ "$pid_emulator" == "" ] || kill $pid_emulator
|
||||
}
|
||||
|
||||
$ADB push $ANDROID_PRODUCT_OUT/system/bin/verifier_test \
|
||||
$WORK_DIR/verifier_test
|
||||
|
||||
expect_succeed() {
|
||||
testname "$1 (should succeed)"
|
||||
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
|
||||
shift
|
||||
run_command $WORK_DIR/verifier_test "$@" $WORK_DIR/package.zip || fail
|
||||
}
|
||||
|
||||
expect_fail() {
|
||||
testname "$1 (should fail)"
|
||||
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
|
||||
shift
|
||||
run_command $WORK_DIR/verifier_test "$@" $WORK_DIR/package.zip && fail
|
||||
}
|
||||
|
||||
# not signed at all
|
||||
expect_fail unsigned.zip
|
||||
# signed in the pre-donut way
|
||||
expect_fail jarsigned.zip
|
||||
|
||||
# success cases
|
||||
expect_succeed otasigned.zip -e3
|
||||
expect_succeed otasigned_f4.zip -f4
|
||||
expect_succeed otasigned_sha256.zip -e3 -sha256
|
||||
expect_succeed otasigned_f4_sha256.zip -f4 -sha256
|
||||
expect_succeed otasigned_ecdsa_sha256.zip -ec -sha256
|
||||
|
||||
# success with multiple keys
|
||||
expect_succeed otasigned.zip -f4 -e3
|
||||
expect_succeed otasigned_f4.zip -ec -f4
|
||||
expect_succeed otasigned_sha256.zip -ec -e3 -e3 -sha256
|
||||
expect_succeed otasigned_f4_sha256.zip -ec -sha256 -e3 -f4 -sha256
|
||||
expect_succeed otasigned_ecdsa_sha256.zip -f4 -sha256 -e3 -ec -sha256
|
||||
|
||||
# verified against different key
|
||||
expect_fail otasigned.zip -f4
|
||||
expect_fail otasigned_f4.zip -e3
|
||||
expect_fail otasigned_ecdsa_sha256.zip -e3 -sha256
|
||||
|
||||
# verified against right key but wrong hash algorithm
|
||||
expect_fail otasigned.zip -e3 -sha256
|
||||
expect_fail otasigned_f4.zip -f4 -sha256
|
||||
expect_fail otasigned_sha256.zip
|
||||
expect_fail otasigned_f4_sha256.zip -f4
|
||||
expect_fail otasigned_ecdsa_sha256.zip
|
||||
|
||||
# various other cases
|
||||
expect_fail random.zip
|
||||
expect_fail fake-eocd.zip
|
||||
expect_fail alter-metadata.zip
|
||||
expect_fail alter-footer.zip
|
||||
|
||||
# --------------- cleanup ----------------------
|
||||
|
||||
cleanup
|
||||
|
||||
echo
|
||||
echo PASS
|
||||
echo
|
Loading…
Reference in a new issue