Reorganization directory structure [4/n]

Change-Id: Ib868ed62d12ea8f9f123644219ba299e86a658ac
This commit is contained in:
kamdiedrich
2020-02-24 00:22:25 +01:00
parent 7df9945ebe
commit 9e97b42ee6
175 changed files with 28 additions and 22 deletions

View File

@@ -0,0 +1,426 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/device_binary_format/ar/ar_decoder.h"
#include "test.h"
using namespace NEO::Ar;
TEST(ArDecoderIsAr, WhenNotArThenReturnsFalse) {
ArrayRef<const uint8_t> empty;
EXPECT_FALSE(isAr(empty));
const uint8_t notAr[] = "aaaaa";
EXPECT_FALSE(isAr(notAr));
}
TEST(ArDecoderIsAr, WhenValidArThenReturnsTrue) {
auto emptyAr = ArrayRef<const uint8_t>::fromAny(arMagic.begin(), arMagic.size());
EXPECT_TRUE(isAr(emptyAr));
}
TEST(ArDecoderReadDecimal, WhenNullOrSpaceIsEncounteredThenParsingStops) {
const char spaceDelimited[] = "213 123";
const char nullTerminateDelimited[] = {'4', '5', '6', '\0', '7', '8', '9'};
EXPECT_EQ(213U, readDecimal<sizeof(spaceDelimited)>(spaceDelimited));
EXPECT_EQ(456U, readDecimal<sizeof(nullTerminateDelimited)>(nullTerminateDelimited));
}
TEST(ArDecoderReadDecimal, WhenNullOrSpaceIsNotEncounteredThenParsesTillTheEnd) {
const char noteDelimited[] = "213123";
EXPECT_EQ(2131U, readDecimal<4>(noteDelimited));
}
TEST(ArDecoderIsStringPadding, GivenCharacterThenReturnsTrueOnlyIfArStringPaddingCharacter) {
EXPECT_TRUE(isStringPadding(' '));
EXPECT_TRUE(isStringPadding('/'));
EXPECT_TRUE(isStringPadding('\0'));
EXPECT_FALSE(isStringPadding('\t'));
EXPECT_FALSE(isStringPadding('\r'));
EXPECT_FALSE(isStringPadding('\n'));
EXPECT_FALSE(isStringPadding('0'));
EXPECT_FALSE(isStringPadding('a'));
}
TEST(ArDecoderReadUnpaddedString, GivenPaddedStringTheReturnsUnpaddedStringPart) {
const char paddedString[] = "abcd/ \0";
auto unpadded = readUnpaddedString<sizeof(paddedString)>(paddedString);
EXPECT_EQ(paddedString, unpadded.begin());
EXPECT_EQ(4U, unpadded.size());
}
TEST(ArDecoderReadUnpaddedString, GivenEmptyPaddedStringTheReturnsEmptyString) {
const char paddedString[] = "// \0";
auto unpadded = readUnpaddedString<sizeof(paddedString)>(paddedString);
EXPECT_TRUE(unpadded.empty());
}
TEST(ArDecoderReadUnpaddedString, GivenUnpaddedStringTheReturnsDataInBounds) {
const char paddedString[] = "abcdefgh";
auto unpadded = readUnpaddedString<3>(paddedString);
EXPECT_EQ(paddedString, unpadded.begin());
EXPECT_EQ(3U, unpadded.size());
}
TEST(ArDecoderReadLongFileName, GivenOffsetThenParsesCorrectString) {
const char names[] = "abcde/fgh/ij";
auto name0 = readLongFileName(names, 0U);
auto name1 = readLongFileName(names, 6U);
auto name2 = readLongFileName(names, 10U);
auto name3 = readLongFileName(names, 40U);
EXPECT_EQ(names, name0.begin());
EXPECT_EQ(5U, name0.size());
EXPECT_EQ(names + 6U, name1.begin());
EXPECT_EQ(3U, name1.size());
EXPECT_EQ(names + 10U, name2.begin());
EXPECT_EQ(2U, name2.size());
EXPECT_TRUE(name3.empty());
}
TEST(ArDecoderDecodeAr, GivenNotArThenFailDecoding) {
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr({}, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, ar.magic);
EXPECT_EQ(0U, ar.files.size());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Not an AR archive - mismatched file signature", decodeErrors.c_str());
}
TEST(ArDecoderDecodeAr, GivenValidArThenDecodingSucceeds) {
const uint8_t data[8] = "1234567";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = 'a';
fileEntry0.identifier[1] = '/';
fileEntry0.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data, data + sizeof(data));
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
ASSERT_EQ(1U, ar.files.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
EXPECT_EQ("a", ar.files[0].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
EXPECT_EQ(8U, ar.files[0].fileData.size());
}
TEST(ArDecoderDecodeAr, GivenArWhenFileEntryHeaderHasEmptyIdentifierThenDecodingFails) {
const uint8_t data[8] = "1234567";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntry0;
fileEntry0.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data, data + sizeof(data));
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, ar.magic);
EXPECT_EQ(0U, ar.files.size());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Corrupt AR archive - file entry does not have identifier : '/ '", decodeErrors.c_str());
}
TEST(ArDecoderDecodeAr, GivenInvalidFileEntryHeaderTrailingMagicThenDecodingSucceedsButWarningIsEmitted) {
const uint8_t data[8] = "1234567";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = 'a';
fileEntry0.identifier[1] = '/';
fileEntry0.fileSizeInBytes[0] = '8';
fileEntry0.trailingMagic[0] = 'a';
fileEntry0.trailingMagic[1] = 'a';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data, data + sizeof(data));
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
EXPECT_TRUE(decodeErrors.empty());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
ASSERT_EQ(1U, ar.files.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
EXPECT_EQ("a", ar.files[0].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
EXPECT_EQ(8U, ar.files[0].fileData.size());
EXPECT_FALSE(decodeWarnings.empty());
EXPECT_STREQ("File entry header with identifier 'a/ ' has invalid header trailing string", decodeWarnings.c_str());
}
TEST(ArDecoderDecodeAr, GivenOutOfBoundsFileEntryDataThenFailDecoding) {
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = 'a';
fileEntry0.identifier[1] = '/';
fileEntry0.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, ar.magic);
EXPECT_EQ(0U, ar.files.size());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Corrupt AR archive - out of bounds data of file entry with idenfitier 'a/ '", decodeErrors.c_str());
}
TEST(ArDecoderDecodeAr, GivenValidTwoFilesEntriesWith2byteAlignedDataThenDecodingSucceeds) {
const uint8_t data0[8] = "1234567";
const uint8_t data1[16] = "9ABCDEFGHIJKLMN";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = 'a';
fileEntry0.identifier[1] = '/';
fileEntry0.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
ArFileEntryHeader fileEntry1;
fileEntry1.identifier[0] = 'b';
fileEntry1.identifier[1] = '/';
fileEntry1.fileSizeInBytes[0] = '1';
fileEntry1.fileSizeInBytes[1] = '6';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry1), reinterpret_cast<const uint8_t *>(&fileEntry1 + 1));
arStorage.insert(arStorage.end(), data1, data1 + sizeof(data1));
ASSERT_EQ(arMagic.size() + 2 * sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(data1), arStorage.size());
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
ASSERT_EQ(2U, ar.files.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
EXPECT_EQ("a", ar.files[0].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
EXPECT_EQ(8U, ar.files[0].fileData.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0)), ar.files[1].fullHeader);
EXPECT_EQ("b", ar.files[1].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(ArFileEntryHeader), ar.files[1].fileData.begin());
EXPECT_EQ(16U, ar.files[1].fileData.size());
}
TEST(ArDecoderDecodeAr, GivenValidTwoFileEntriesWith2byteUnalignedDataAndPaddingThenImplicitPaddingIsTakenIntoAccount) {
const uint8_t data0[7] = "123456";
const uint8_t data1[15] = "9ABCDEFGHIJKLM";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = 'a';
fileEntry0.identifier[1] = '/';
fileEntry0.fileSizeInBytes[0] = '7';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
arStorage.push_back('\0'); // implicit 2-byte alignment padding
ArFileEntryHeader fileEntry1;
fileEntry1.identifier[0] = 'b';
fileEntry1.identifier[1] = '/';
fileEntry1.fileSizeInBytes[0] = '1';
fileEntry1.fileSizeInBytes[1] = '5';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry1), reinterpret_cast<const uint8_t *>(&fileEntry1 + 1));
arStorage.insert(arStorage.end(), data1, data1 + sizeof(data1));
arStorage.push_back('\0'); // implicit 2-byte alignment padding
ASSERT_EQ(arMagic.size() + 2 * sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(data1) + 2, arStorage.size());
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(ar.longFileNamesEntry.fileData.empty());
EXPECT_TRUE(ar.longFileNamesEntry.fileName.empty());
ASSERT_EQ(2U, ar.files.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.files[0].fullHeader);
EXPECT_EQ("a", ar.files[0].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
EXPECT_EQ(7U, ar.files[0].fileData.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0) + 1), ar.files[1].fullHeader);
EXPECT_EQ("b", ar.files[1].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + sizeof(data0) + 1 + sizeof(ArFileEntryHeader), ar.files[1].fileData.begin());
EXPECT_EQ(15U, ar.files[1].fileData.size());
}
TEST(ArDecoderDecodeAr, GivenSpecialFileWithLongFilenamesThenSpecialFileIsProperlyRecognized) {
const uint8_t names[8] = "123456/";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntrySpecial;
fileEntrySpecial.identifier[0] = '/';
fileEntrySpecial.identifier[1] = '/';
fileEntrySpecial.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntrySpecial), reinterpret_cast<const uint8_t *>(&fileEntrySpecial + 1));
arStorage.insert(arStorage.end(), names, names + sizeof(names));
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.longFileNamesEntry.fullHeader);
EXPECT_EQ("//", ar.longFileNamesEntry.fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.longFileNamesEntry.fileData.begin());
EXPECT_EQ(8U, ar.longFileNamesEntry.fileData.size());
EXPECT_EQ(0U, ar.files.size());
}
TEST(ArDecoderDecodeAr, GivenFilesWithLongFilenamesThenNamesAreProperlyDecoded) {
const uint8_t longNames[] = "my_identifier_is_longer_than_16_charters/my_identifier_is_even_longer_than_previous_one/";
size_t longNamesLen = sizeof(longNames) - 1U; // 88, ignore nullterminate
const uint8_t data0[8] = "1234567";
const uint8_t data1[16] = "9ABCDEFGHIJKLMN";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntrySpecial;
fileEntrySpecial.identifier[0] = '/';
fileEntrySpecial.identifier[1] = '/';
fileEntrySpecial.fileSizeInBytes[0] = '8';
fileEntrySpecial.fileSizeInBytes[1] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntrySpecial), reinterpret_cast<const uint8_t *>(&fileEntrySpecial + 1));
arStorage.insert(arStorage.end(), longNames, longNames + longNamesLen);
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = '/';
fileEntry0.identifier[1] = '0';
fileEntry0.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
ArFileEntryHeader fileEntry1;
fileEntry1.identifier[0] = '/';
fileEntry1.identifier[1] = '4';
fileEntry1.identifier[2] = '1';
fileEntry1.fileSizeInBytes[0] = '1';
fileEntry1.fileSizeInBytes[1] = '6';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry1), reinterpret_cast<const uint8_t *>(&fileEntry1 + 1));
arStorage.insert(arStorage.end(), data1, data1 + sizeof(data1));
ASSERT_EQ(arMagic.size() + 3 * sizeof(ArFileEntryHeader) + longNamesLen + sizeof(data0) + sizeof(data1), arStorage.size());
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<const char *>(arStorage.data()), ar.magic);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size()), ar.longFileNamesEntry.fullHeader);
EXPECT_EQ("//", ar.longFileNamesEntry.fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader), ar.longFileNamesEntry.fileData.begin());
EXPECT_EQ(longNamesLen, ar.longFileNamesEntry.fileData.size());
ASSERT_EQ(2U, ar.files.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen), ar.files[0].fullHeader);
EXPECT_EQ("my_identifier_is_longer_than_16_charters", ar.files[0].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen + sizeof(ArFileEntryHeader), ar.files[0].fileData.begin());
EXPECT_EQ(8U, ar.files[0].fileData.size());
EXPECT_EQ(reinterpret_cast<ArFileEntryHeader *>(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen + sizeof(ArFileEntryHeader) + sizeof(data0)), ar.files[1].fullHeader);
EXPECT_EQ("my_identifier_is_even_longer_than_previous_one", ar.files[1].fileName);
EXPECT_EQ(arStorage.data() + arMagic.size() + sizeof(ArFileEntryHeader) + longNamesLen + sizeof(ArFileEntryHeader) + sizeof(data0) + sizeof(ArFileEntryHeader), ar.files[1].fileData.begin());
EXPECT_EQ(16U, ar.files[1].fileData.size());
}
TEST(ArDecoderDecodeAr, GivenFilesWithLongFilenamesWhenFileNamesSpecialEntryNotPresentThenDecodingFails) {
const uint8_t data0[8] = "1234567";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = '/';
fileEntry0.identifier[1] = '0';
fileEntry0.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, ar.magic);
EXPECT_EQ(0U, ar.files.size());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Corrupt AR archive - long file name entry has broken identifier : '/0 '", decodeErrors.c_str());
}
TEST(ArDecoderDecodeAr, GivenFilesWithLongFilenamesWhenLongNameIsOutOfBoundsThenDecodingFails) {
const uint8_t longNames[] = "my_identifier_is_longer_than_16_charters/my_identifier_is_even_longer_than_previous_one/";
size_t longNamesLen = sizeof(longNames) - 1U; // 88, ignore nullterminate
const uint8_t data0[8] = "1234567";
std::vector<uint8_t> arStorage;
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
ArFileEntryHeader fileEntrySpecial;
fileEntrySpecial.identifier[0] = '/';
fileEntrySpecial.identifier[1] = '/';
fileEntrySpecial.fileSizeInBytes[0] = '8';
fileEntrySpecial.fileSizeInBytes[1] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntrySpecial), reinterpret_cast<const uint8_t *>(&fileEntrySpecial + 1));
arStorage.insert(arStorage.end(), longNames, longNames + longNamesLen);
ArFileEntryHeader fileEntry0;
fileEntry0.identifier[0] = '/';
fileEntry0.identifier[1] = '1';
fileEntry0.identifier[2] = '0';
fileEntry0.identifier[3] = '0';
fileEntry0.fileSizeInBytes[0] = '8';
arStorage.insert(arStorage.end(), reinterpret_cast<const uint8_t *>(&fileEntry0), reinterpret_cast<const uint8_t *>(&fileEntry0 + 1));
arStorage.insert(arStorage.end(), data0, data0 + sizeof(data0));
std::string decodeErrors;
std::string decodeWarnings;
auto ar = decodeAr(arStorage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, ar.magic);
EXPECT_EQ(0U, ar.files.size());
EXPECT_EQ(nullptr, ar.longFileNamesEntry.fullHeader);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Corrupt AR archive - long file name entry has broken identifier : '/100 '", decodeErrors.c_str());
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/compiler_interface/intermediate_representations.h"
#include "shared/source/device_binary_format/ar/ar_encoder.h"
#include "shared/source/helpers/ptr_math.h"
#include "shared/source/helpers/string.h"
#include "test.h"
#include <cstring>
using namespace NEO::Ar;
TEST(ArFileEntryHeader, GivenDefaultArFileEntryHeaderThenSectionAreProperlyPopulated) {
ArFileEntryHeader header = {};
EXPECT_EQ(ConstStringRef("/ ", 16), ConstStringRef(header.identifier));
EXPECT_EQ(ConstStringRef("0 ", 12), ConstStringRef(header.fileModificationTimestamp));
EXPECT_EQ(ConstStringRef("0 ", 6), ConstStringRef(header.ownerId));
EXPECT_EQ(ConstStringRef("0 ", 6), ConstStringRef(header.groupId));
EXPECT_EQ(ConstStringRef("644 ", 8), ConstStringRef(header.fileMode));
EXPECT_EQ(ConstStringRef("0 ", 10), ConstStringRef(header.fileSizeInBytes));
EXPECT_EQ(ConstStringRef("\x60\x0A", 2), ConstStringRef(header.trailingMagic));
}
TEST(ArEncoder, GivenTooLongIdentifierThenAppendingFileFails) {
const uint8_t fileData[] = "2357111317192329";
ArEncoder encoder;
EXPECT_EQ(nullptr, encoder.appendFileEntry("my_identifier_is_longer_than_16_charters", fileData));
}
TEST(ArEncoder, GivenEmptyIdentifierThenAppendingFileFails) {
const uint8_t fileData[] = "2357111317192329";
ArEncoder encoder;
EXPECT_EQ(nullptr, encoder.appendFileEntry("", fileData));
}
TEST(ArEncoder, GivenEmptyArThenEncodedFileConsistsOfOnlyArMagic) {
ArEncoder encoder;
auto arData = encoder.encode();
EXPECT_EQ(arMagic.size(), arData.size());
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
}
TEST(ArEncoder, GivenValidFileEntriesThenAppendingFileSucceeds) {
std::string fileName = "file1.txt";
const uint8_t fileData[18] = "23571113171923293";
ArEncoder encoder;
auto returnedSection = encoder.appendFileEntry(fileName, fileData);
ASSERT_NE(nullptr, returnedSection);
ArFileEntryHeader expectedSection;
memcpy_s(expectedSection.identifier, sizeof(expectedSection.identifier), fileName.c_str(), fileName.size());
expectedSection.identifier[fileName.size()] = '/';
expectedSection.fileSizeInBytes[0] = '1';
expectedSection.fileSizeInBytes[1] = '8';
EXPECT_EQ(0, memcmp(returnedSection, &expectedSection, sizeof(expectedSection)));
auto arData = encoder.encode();
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
ASSERT_EQ(arData.size(), arMagic.size() + sizeof(fileData) + sizeof(ArFileEntryHeader));
ArFileEntryHeader *file0 = reinterpret_cast<ArFileEntryHeader *>(arData.data() + arMagic.size());
auto file0Data = arData.data() + arMagic.size() + sizeof(ArFileEntryHeader);
EXPECT_EQ(0, memcmp(file0, &expectedSection, sizeof(expectedSection)));
EXPECT_EQ(0, memcmp(file0Data, fileData, sizeof(fileData)));
}
TEST(ArEncoder, GivenValidTwoFileEntriesWith2byteUnalignedDataThenPaddingIsImplicitlyAdded) {
std::string fileName0 = "a";
std::string fileName1 = "b";
const uint8_t data0[7] = "123456";
const uint8_t data1[16] = "9ABCDEFGHIJKLMN";
ArEncoder encoder;
auto returnedSection = encoder.appendFileEntry(fileName0, data0);
ASSERT_NE(nullptr, returnedSection);
ArFileEntryHeader expectedSection0;
expectedSection0.identifier[0] = 'a';
expectedSection0.identifier[1] = '/';
expectedSection0.fileSizeInBytes[0] = '7';
EXPECT_EQ(0, memcmp(returnedSection, &expectedSection0, sizeof(expectedSection0)));
returnedSection = encoder.appendFileEntry(fileName1, data1);
ASSERT_NE(nullptr, returnedSection);
ArFileEntryHeader expectedSection1;
expectedSection1.identifier[0] = 'b';
expectedSection1.identifier[1] = '/';
expectedSection1.fileSizeInBytes[0] = '1';
expectedSection1.fileSizeInBytes[1] = '6';
EXPECT_EQ(0, memcmp(returnedSection, &expectedSection1, sizeof(expectedSection1)));
auto arData = encoder.encode();
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
ASSERT_EQ(arData.size(), arMagic.size() + sizeof(data0) + sizeof(data1) + 2 * sizeof(ArFileEntryHeader) + 1);
ArFileEntryHeader *file0 = reinterpret_cast<ArFileEntryHeader *>(arData.data() + arMagic.size());
auto file0Data = arData.data() + arMagic.size() + sizeof(ArFileEntryHeader);
ArFileEntryHeader *file1 = reinterpret_cast<ArFileEntryHeader *>(arData.data() + arMagic.size() + sizeof(data0) + sizeof(ArFileEntryHeader) + 1);
auto file1Data = arData.data() + arMagic.size() + sizeof(data0) + 2 * sizeof(ArFileEntryHeader) + 1;
EXPECT_EQ(0, memcmp(file0, &expectedSection0, sizeof(expectedSection0)));
EXPECT_EQ(0, memcmp(file0Data, data0, sizeof(data0)));
EXPECT_EQ(0, memcmp(file1, &expectedSection1, sizeof(expectedSection1)));
EXPECT_EQ(0, memcmp(file1Data, data1, sizeof(data1)));
}
TEST(ArEncoder, GivenValidTwoFileEntriesWhen8BytePaddingIsRequestedThenPaddingFileEntriesAreAddedWhenNeeded) {
std::string fileName0 = "a";
std::string fileName1 = "b";
std::string fileName2 = "c";
const uint8_t data0[4] = "123"; // will require padding before
const uint8_t data1[8] = "9ABCDEF"; // won't require padding before
const uint8_t data2[16] = "9ABCDEF"; // will require padding before
ArEncoder encoder(true);
encoder.appendFileEntry(fileName0, data0);
encoder.appendFileEntry(fileName1, data1);
encoder.appendFileEntry(fileName2, data2);
auto arData = encoder.encode();
EXPECT_TRUE(NEO::hasSameMagic(arMagic, arData));
ASSERT_EQ(arData.size(), arMagic.size() + sizeof(data0) + sizeof(data1) + sizeof(data2) + 5 * sizeof(ArFileEntryHeader) + 16);
auto files = arData.data() + arMagic.size();
ArFileEntryHeader *pad0 = reinterpret_cast<ArFileEntryHeader *>(files);
auto pad0Data = reinterpret_cast<uint8_t *>(pad0) + sizeof(ArFileEntryHeader);
ArFileEntryHeader *file0 = reinterpret_cast<ArFileEntryHeader *>(pad0Data + 8);
auto file0Data = reinterpret_cast<uint8_t *>(file0) + sizeof(ArFileEntryHeader);
ArFileEntryHeader *file1 = reinterpret_cast<ArFileEntryHeader *>(file0Data + sizeof(data0));
auto file1Data = reinterpret_cast<uint8_t *>(file1) + sizeof(ArFileEntryHeader);
ArFileEntryHeader *pad1 = reinterpret_cast<ArFileEntryHeader *>(file1Data + sizeof(data1));
auto pad1Data = reinterpret_cast<uint8_t *>(pad1) + sizeof(ArFileEntryHeader);
ArFileEntryHeader *file2 = reinterpret_cast<ArFileEntryHeader *>(pad1Data + 8);
auto file2Data = reinterpret_cast<uint8_t *>(file2) + sizeof(ArFileEntryHeader);
EXPECT_EQ(0U, ptrDiff(file0Data, arData.data()) % 8);
EXPECT_EQ(0U, ptrDiff(file1Data, arData.data()) % 8);
EXPECT_EQ(0U, ptrDiff(file2Data, arData.data()) % 8);
EXPECT_EQ(0, memcmp(file0Data, data0, sizeof(data0)));
EXPECT_EQ(0, memcmp(file1Data, data1, sizeof(data1)));
EXPECT_EQ(0, memcmp(file2Data, data2, sizeof(data2)));
}