blob: d9d7aa6d9a9186e7fed690326961281a365672bc [file] [log] [blame]
/* Copyright (C) 2016 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
#include "android/telephony/TagLengthValue.h"
#include <gtest/gtest.h>
namespace android {
TEST(TagLengthValue, ConstructDeviceAppIdRefDo) {
DeviceAppIdRefDo deviceAppIdRefDo("C0FFEE");
// Ensure the correct tag is used and that the length and data are correct
ASSERT_STREQ(/*tag*/ "C1" /*length*/ "03" /*payload*/ "C0FFEE",
deviceAppIdRefDo.c_str());
}
TEST(TagLengthValue, ConstructPkgRefDo) {
PkgRefDo pkgRefDo("com.android.foo");
ASSERT_STREQ(/*tag*/ "CA" /*length*/ "0f"
/*payload*/ "636f6d2e616e64726f69642e666f6f",
pkgRefDo.c_str());
}
TEST(TagLengthValue, ConstructRefDo) {
RefDo refDo{DeviceAppIdRefDo("C0FFEE")};
ASSERT_STREQ(/*tag*/ "E1" /*length*/ "05" /*payload*/ "C103C0FFEE",
refDo.c_str());
}
TEST(TagLengthValue, ConstructRefDoWithAidRefDo) {
RefDo refDo{AidRefDo(), DeviceAppIdRefDo("C0FFEE")};
// Note that the AID-REF-DO does not end up in the payload because we
// construct an empty object.
ASSERT_STREQ(/*tag*/ "E1" /*length*/ "05" /*payload*/ "C103C0FFEE",
refDo.c_str());
}
TEST(TagLengthValue, ConstructRefDoWithPkgRefDo) {
RefDo refDo{DeviceAppIdRefDo("C0FFEE"), PkgRefDo("foo")};
ASSERT_STREQ(/*tag*/ "E1" /*length*/ "0a"
/*payload*/ "C103C0FFEECA03666f6f",
refDo.c_str());
}
TEST(TagLengthValue, ConstructApduArDo) {
ApduArDo globalDenyRule(ApduArDo::Allow::Never);
ASSERT_STREQ(/*tag*/ "D0" /*length*/ "01" /*payload*/ "00",
globalDenyRule.c_str());
ApduArDo globalAllowRule(ApduArDo::Allow::Always);
ASSERT_STREQ(/*tag*/ "D0" /*length*/ "01" /*payload*/ "01",
globalAllowRule.c_str());
// These rules are actually supposed to have a better format than this
// but this will work for testing.
ApduArDo specificRule( {"C0FFEE", "BEEF"} );
ASSERT_STREQ(/*tag*/ "D0" /*length*/ "05" /*payload*/ "C0FFEEBEEF",
specificRule.c_str());
}
TEST(TagLengthValue, ConstructNfcArDo) {
NfcArDo never(NfcArDo::Allow::Never);
ASSERT_STREQ(/*tag*/ "D1" /*length*/ "01" /*payload*/ "00", never.c_str());
NfcArDo always(NfcArDo::Allow::Always);
ASSERT_STREQ(/*tag*/ "D1" /*length*/ "01" /*payload*/ "01", always.c_str());
}
TEST(TagLengthValue, ConstructPermArDo) {
PermArDo permArDo("C0FFEE");
ASSERT_STREQ(/*tag*/ "DB" /*length*/ "03" /*payload*/ "C0FFEE",
permArDo.c_str());
}
TEST(TagLengthValue, ConstructArDo) {
const ApduArDo apduArDo( {"C0FFEE", "BEEF"} );
const NfcArDo nfcArDo(NfcArDo::Allow::Always);
const PermArDo permArDo("DECADE");
ArDo arDoWithApdu(apduArDo);
ASSERT_STREQ(/*tag*/ "E3" /*length*/ "07" /*payload*/ "D005C0FFEEBEEF",
arDoWithApdu.c_str());
ArDo arDoWithNfc(nfcArDo);
ASSERT_STREQ(/*tag*/ "E3" /*length*/ "03" /*payload*/ "D10101",
arDoWithNfc.c_str());
ArDo arDoWithPerm(permArDo);
ASSERT_STREQ(/*tag*/ "E3" /*length*/ "05" /*payload*/ "DB03DECADE",
arDoWithPerm.c_str());
ArDo arDoWithApduAndNfc(apduArDo, nfcArDo);
ASSERT_STREQ(/*tag*/ "E3" /*length*/ "0a"
/*payload*/ "D005C0FFEEBEEFD10101",
arDoWithApduAndNfc.c_str());
}
TEST(TagLengthValue, ConstructRefArDo) {
RefDo refDo(AidRefDo(), DeviceAppIdRefDo("C0FFEE"));
ArDo arDo{NfcArDo{NfcArDo::Allow::Always}};
RefArDo refArDo(refDo, arDo);
ASSERT_STREQ(/*tag*/ "E2" /*length*/ "0c"
/*payload*/ "E105C103C0FFEEE303D10101", refArDo.c_str());
}
TEST(TagLengthValue, ConstructAllRefArDo) {
// Create an ALL-REF-AR-DO with two REF-AR-DOs in it
AllRefArDo allRefArDo {
RefArDo {
RefDo {
AidRefDo(),
DeviceAppIdRefDo { "C0FFEE" }
},
ArDo {
ApduArDo { ApduArDo::Allow::Never }
}
},
RefArDo {
RefDo {
AidRefDo { },
DeviceAppIdRefDo { "BEEF" }
},
ArDo {
ApduArDo { ApduArDo::Allow::Always },
NfcArDo { NfcArDo::Allow::Never }
}
}
};
ASSERT_STREQ(/*tag*/ "FF40" /*length*/ "1e"
/*1st REF-AR-DO*/ "E20cE105C103C0FFEEE303D00100"
/*2nd REF-AR-DO*/ "E20eE104C102BEEFE306D00101D10100",
allRefArDo.c_str());
}
TEST(TagLengthValue, TestLongLenths) {
// Create a string that's longer than 128 bytes, this will force the length
// part of the resulting string to span two bytes, see implementation for
// details on why this is. Lengths are multiplied by two because each byte
// is represented by two characters.
std::string twoByteString(2 * 0xa0, 'x');
DeviceAppIdRefDo twoByteTlv(twoByteString);
ASSERT_EQ(twoByteTlv.c_str(), strstr(twoByteTlv.c_str(), "C181a0x"));
// Longer than 255 bytes requires three byte length
std::string threeByteString(2 * 0x123, 'x');
DeviceAppIdRefDo threeByteTlv(threeByteString);
ASSERT_EQ(threeByteTlv.c_str(), strstr(threeByteTlv.c_str(), "C1820123x"));
// Longer than 65535 bytes requires four byte length
std::string fourByteString(2 * 0x10312, 'x');
DeviceAppIdRefDo fourByteTlv(fourByteString);
ASSERT_EQ(fourByteTlv.c_str(), strstr(fourByteTlv.c_str(), "C183010312x"));
/*
This test is disabled because of excessive memory usage and slow
performance. At the time of writing it works but since it's unlikely
we will ever be returning data larger than 16 MB skipping this should
be OK
// Longer than 16 * 65535 requires five byte length
std::string fiveByteString(2 * 0x1001002, 'x');
DeviceAppIdRefDo fiveByteTlv(fiveByteString);
ASSERT_EQ(fiveByteTlv.c_str(),
strstr(fiveByteTlv.c_str(), "C18401001002x"));
*/
}
} // namespace android