OEMCrypto and OPK v20 prerelease initial commit

This commit is contained in:
Matt Feddersen
2025-05-20 20:30:59 -07:00
parent 98dfef4389
commit a2b9e085e9
193 changed files with 22480 additions and 3275 deletions

View File

@@ -0,0 +1,841 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#include "buffer_reader.h"
#include <inttypes.h>
#include <string>
#include <vector>
#include <gtest/gtest.h>
namespace wvutil {
class BufferReaderTest : public testing::Test {
public:
template <typename T>
void WriteToBuffer(uint8_t* buffer, T v) {
for (size_t i = 0; i < sizeof(T); ++i) {
size_t insert_at = (sizeof(T) - i) - 1; // reverse the order of i
size_t shift_amount = 8 * i;
buffer[insert_at] = static_cast<uint8_t>((v >> shift_amount) & 0xff);
}
}
// populate and validate data by cycling through the alphabet
// (lower case) so that it will work for strings and raw bytes
void PopulateData(uint8_t* dest, size_t byte_count) {
for (size_t i = 0; i < byte_count; i++) {
dest[i] = static_cast<uint8_t>(i % 26 + 'a');
}
}
bool ValidateData(const uint8_t* data, size_t byte_count) {
for (size_t i = 0; i < byte_count; i++) {
if (data[i] != static_cast<uint8_t>(i % 26 + 'a')) {
return false;
}
}
return true;
}
bool ValidateReader(const BufferReader& reader,
const uint8_t* expected_address, size_t expected_size,
size_t expected_position) {
return reader.data() == expected_address &&
reader.size() == expected_size && reader.pos() == expected_position;
}
bool CheckRead1(uint8_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
uint8_t read;
return reader.Read1(&read) && input == read &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead2(uint16_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
uint16_t read;
return reader.Read2(&read) && input == read &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead2s(int16_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
int16_t read;
return reader.Read2s(&read) && input == read &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead4(uint32_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
uint32_t read;
return reader.Read4(&read) && input == read &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead4s(int32_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
int32_t read;
return reader.Read4s(&read) && input == read &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead8(uint64_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
uint64_t read;
return reader.Read8(&read) && input == read &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead8s(int64_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
int64_t read;
return reader.Read8s(&read) && input == read &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead4Into8(uint32_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
uint64_t read;
return reader.Read4Into8(&read) && read == input &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
bool CheckRead4sInto8s(int32_t input) {
uint8_t raw_data[sizeof(input)];
WriteToBuffer(raw_data, input);
BufferReader reader(raw_data, sizeof(raw_data));
int64_t read;
return reader.Read4sInto8s(&read) && read == input &&
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(input));
}
};
TEST_F(BufferReaderTest, InitializeGoodDataAndGoodSize) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, InitializeGoodDataAndNoSize) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, InitializeNoDataNoSize) {
BufferReader reader(nullptr, 0);
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, InitializeNoDataBadSize) {
BufferReader reader(nullptr, 16);
// Buffer reader should default to a size of 0 when given
// NULL data to ensure no reading of bad data
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, HasBytesWithBytes) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
// the reader should have enough bytes from 0 to the size of the buffer
for (size_t i = 0; i <= sizeof(raw_data); i++) {
ASSERT_TRUE(reader.HasBytes(i));
}
ASSERT_FALSE(reader.HasBytes(sizeof(raw_data) + 1));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, HasBytesWithEmptyBuffer) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
ASSERT_FALSE(reader.HasBytes(1));
ASSERT_TRUE(reader.HasBytes(0));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, HasBytesWithNullBuffer) {
BufferReader reader(nullptr, 8);
ASSERT_FALSE(reader.HasBytes(1));
ASSERT_TRUE(reader.HasBytes(0));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, HasBytesAfterAllRead) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
for (size_t i = 0; i < sizeof(raw_data); i++) {
uint8_t read;
ASSERT_TRUE(reader.Read1(&read));
}
ASSERT_FALSE(reader.HasBytes(1));
ASSERT_TRUE(reader.HasBytes(0));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(raw_data)));
}
TEST_F(BufferReaderTest, Read1LargeNumber) { ASSERT_TRUE(CheckRead1(0xFF)); }
TEST_F(BufferReaderTest, Read1SmallNumber) { ASSERT_TRUE(CheckRead1(0x0F)); }
TEST_F(BufferReaderTest, Read1Zero) { ASSERT_TRUE(CheckRead1(0)); }
TEST_F(BufferReaderTest, Read1WithNoData) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
uint8_t read;
ASSERT_FALSE(reader.Read1(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, Read1WithNullBuffer) {
BufferReader reader(nullptr, 16);
uint8_t read;
ASSERT_FALSE(reader.Read1(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read1WithNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read1(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read2LargeNumber) { ASSERT_TRUE(CheckRead2(30000)); }
TEST_F(BufferReaderTest, Read2SmallNumber) { ASSERT_TRUE(CheckRead2(10)); }
TEST_F(BufferReaderTest, Read2Zero) { ASSERT_TRUE(CheckRead2(0)); }
TEST_F(BufferReaderTest, Read2WithNoData) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
uint16_t read;
ASSERT_FALSE(reader.Read2(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, Read2WithNullBuffer) {
BufferReader reader(nullptr, 16);
uint16_t read;
ASSERT_FALSE(reader.Read2(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read2WithNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read2(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read2sLargePositive) {
ASSERT_TRUE(CheckRead2s(30000));
}
TEST_F(BufferReaderTest, Read2sSmallPositive) { ASSERT_TRUE(CheckRead2s(10)); }
TEST_F(BufferReaderTest, Read2sZero) { ASSERT_TRUE(CheckRead2s(0)); }
TEST_F(BufferReaderTest, Read2sSmallNegative) { ASSERT_TRUE(CheckRead2s(-10)); }
TEST_F(BufferReaderTest, Read2sLargeNegative) {
ASSERT_TRUE(CheckRead2s(-30000));
}
TEST_F(BufferReaderTest, Read2sWithNoData) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
int16_t read;
ASSERT_FALSE(reader.Read2s(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, Read2sWithNullBuffer) {
BufferReader reader(nullptr, 16);
int16_t read;
ASSERT_FALSE(reader.Read2s(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read2sWithNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read2s(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read4LargeNumber) {
// a number near uint32's max value
ASSERT_TRUE(CheckRead4(2000000000));
}
TEST_F(BufferReaderTest, Read4SmallNumber) { ASSERT_TRUE(CheckRead4(10)); }
TEST_F(BufferReaderTest, Read4Zero) { ASSERT_TRUE(CheckRead4(0)); }
TEST_F(BufferReaderTest, Read4WithNoData) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
uint32_t read;
ASSERT_FALSE(reader.Read4(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, Read4WithNullBuffer) {
BufferReader reader(nullptr, 16);
uint32_t read;
ASSERT_FALSE(reader.Read4(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read4WithNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read4(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read4sLargePositive) {
// a number near int32's max value
ASSERT_TRUE(CheckRead4s(2000000000));
}
TEST_F(BufferReaderTest, Read4sSmallPositive) { ASSERT_TRUE(CheckRead4s(10)); }
TEST_F(BufferReaderTest, Read4sZero) { ASSERT_TRUE(CheckRead4s(0)); }
TEST_F(BufferReaderTest, Read4sSmallNegative) { ASSERT_TRUE(CheckRead4s(-10)); }
TEST_F(BufferReaderTest, Read4sLargeNegative) {
// a number near int32's max negative value
ASSERT_TRUE(CheckRead4s(-2000000000));
}
TEST_F(BufferReaderTest, Read4sWithNoData) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
int32_t read;
ASSERT_FALSE(reader.Read4s(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, Read4sWithNullBuffer) {
BufferReader reader(nullptr, 16);
int32_t read;
ASSERT_FALSE(reader.Read4s(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read4sWithNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read4s(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read8LargeNumber) {
// a number near uint64's max value
ASSERT_TRUE(CheckRead8(9000000000000000000));
}
TEST_F(BufferReaderTest, Read8SmallNumber) { ASSERT_TRUE(CheckRead8(10)); }
TEST_F(BufferReaderTest, Read8Zero) { ASSERT_TRUE(CheckRead8(0)); }
TEST_F(BufferReaderTest, Read8WithNoData) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
uint64_t read;
ASSERT_FALSE(reader.Read8(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, Read8WithNullBuffer) {
BufferReader reader(nullptr, 16);
uint64_t read;
ASSERT_FALSE(reader.Read8(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read8WithNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read8(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read8sLargePositive) {
// a number near int64's max value
ASSERT_TRUE(CheckRead8s(9000000000000000000));
}
TEST_F(BufferReaderTest, Read8sSmallPositive) { ASSERT_TRUE(CheckRead8s(10)); }
TEST_F(BufferReaderTest, Read8sZero) { ASSERT_TRUE(CheckRead8s(0)); }
TEST_F(BufferReaderTest, Read8sSmallNegative) { ASSERT_TRUE(CheckRead8s(-10)); }
TEST_F(BufferReaderTest, Read8sLargeNegative) {
// a number near int64's max negative value
ASSERT_TRUE(CheckRead8s(-9000000000000000000));
}
TEST_F(BufferReaderTest, Read8sWithNoData) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, 0);
int64_t read;
ASSERT_FALSE(reader.Read8s(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, 0, 0));
}
TEST_F(BufferReaderTest, Read8sWithNullBuffer) {
BufferReader reader(nullptr, 16);
int64_t read;
ASSERT_FALSE(reader.Read8s(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read8sWithNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read8s(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, ReadString) {
uint8_t raw_data[5];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
std::string read;
ASSERT_TRUE(reader.ReadString(&read, sizeof(raw_data)));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(read.length() == sizeof(raw_data));
ASSERT_TRUE(ValidateData((const uint8_t*)read.c_str(), read.length()));
ASSERT_TRUE(
ValidateReader(reader, raw_data, sizeof(raw_data), sizeof(raw_data)));
}
TEST_F(BufferReaderTest, ReadStringNullSource) {
BufferReader reader(nullptr, 5);
std::string read;
ASSERT_FALSE(reader.ReadString(&read, 5));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, ReadStringNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.ReadString(nullptr, 5));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, ReadStringZeroCount) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
std::string read;
ASSERT_TRUE(reader.ReadString(&read, 0));
ASSERT_TRUE(0 == read.length());
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, ReadStringTooLarge) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
std::string read;
ASSERT_FALSE(reader.ReadString(&read, sizeof(raw_data) * 2));
ASSERT_TRUE(0 == read.length());
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, ReadVector) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
std::vector<uint8_t> read;
ASSERT_TRUE(reader.ReadVec(&read, 4));
ASSERT_TRUE(read.size() == 4);
for (size_t i = 0; i < 4; i++) {
ASSERT_TRUE(raw_data[i] == read[i]);
}
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 4));
}
TEST_F(BufferReaderTest, ReadVectorTooLarge) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
std::vector<uint8_t> read;
ASSERT_FALSE(reader.ReadVec(&read, sizeof(raw_data) * 2));
ASSERT_TRUE(0 == read.size());
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, ReadVectorNullSource) {
BufferReader reader(nullptr, 16);
std::vector<uint8_t> read;
ASSERT_FALSE(reader.ReadVec(&read, 4));
ASSERT_TRUE(0 == read.size());
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, ReadVectorNullReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.ReadVec(nullptr, 4));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, ReadVectorNone) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
std::vector<uint8_t> read;
ASSERT_TRUE(reader.ReadVec(&read, 0));
ASSERT_TRUE(0 == read.size());
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read4Into84Bytes) {
ASSERT_TRUE(CheckRead4Into8(0xFFFFFF));
}
TEST_F(BufferReaderTest, Read4Into83Bytes) {
ASSERT_TRUE(CheckRead4Into8(0xFFFF));
}
TEST_F(BufferReaderTest, Read4Into82Bytes) {
ASSERT_TRUE(CheckRead4Into8(0xFF));
}
TEST_F(BufferReaderTest, Read4Into8Zero) { ASSERT_TRUE(CheckRead4Into8(0)); }
TEST_F(BufferReaderTest, Read4Into8NullSource) {
BufferReader reader(nullptr, 4);
uint64_t read;
ASSERT_FALSE(reader.Read4Into8(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read4Into8TooLittleData) {
uint8_t raw_data[2];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
uint64_t read;
ASSERT_FALSE(reader.Read4Into8(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read4Into8NoReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read4Into8(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read4sInto8s4Bytes) {
ASSERT_TRUE(CheckRead4sInto8s(0x0FFFFFFF));
}
TEST_F(BufferReaderTest, Read4sInto8s3Bytes) {
ASSERT_TRUE(CheckRead4sInto8s(0xFFFFFF));
}
TEST_F(BufferReaderTest, Read4sInto8s2Bytes) {
ASSERT_TRUE(CheckRead4sInto8s(0xFFFF));
}
TEST_F(BufferReaderTest, Read4sInto8s1Bytes) {
ASSERT_TRUE(CheckRead4sInto8s(0xFF));
}
TEST_F(BufferReaderTest, Read4sInto8sZero) {
ASSERT_TRUE(CheckRead4sInto8s(0));
}
TEST_F(BufferReaderTest, Read4sInto8sNegative) {
ASSERT_TRUE(CheckRead4sInto8s(-100));
}
TEST_F(BufferReaderTest, Read4sInto8sNullSource) {
BufferReader reader(nullptr, 4);
int64_t read;
ASSERT_FALSE(reader.Read4sInto8s(&read));
ASSERT_TRUE(ValidateReader(reader, nullptr, 0, 0));
}
TEST_F(BufferReaderTest, Read4sInto8sTooLittleData) {
uint8_t raw_data[2];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
int64_t read;
ASSERT_FALSE(reader.Read4sInto8s(&read));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, Read4sInto8sNoReturn) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.Read4sInto8s(nullptr));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, SkipBytesNone) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_TRUE(reader.SkipBytes(0));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
TEST_F(BufferReaderTest, SkipBytes) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_TRUE(reader.SkipBytes(4));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 4));
}
TEST_F(BufferReaderTest, SkipBytesTooLarge) {
uint8_t raw_data[16];
PopulateData(raw_data, sizeof(raw_data));
BufferReader reader(raw_data, sizeof(raw_data));
ASSERT_FALSE(reader.SkipBytes(sizeof(raw_data) * 2));
ASSERT_TRUE(ValidateData(raw_data, sizeof(raw_data)));
ASSERT_TRUE(ValidateReader(reader, raw_data, sizeof(raw_data), 0));
}
} // namespace wvutil

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,11 +5,14 @@
// Clock - A fake clock just for running tests. This is used when running
// OEMCrypto unit tests. It is not used when tests include the CE CDM source
// code because that uses the clock in cdm/test_host.cpp instead.
#include <inttypes.h>
#include <chrono>
#include "clock.h"
#include "test_sleep.h"
#include "wv_duration.h"
#include "wv_timestamp.h"
namespace wvutil {
@@ -19,16 +22,19 @@ class FakeClock : public TestSleep::CallBack {
public:
FakeClock() {
auto now = std::chrono::system_clock().now();
now_ = now.time_since_epoch() / std::chrono::milliseconds(1);
now_ = Timestamp::FromUnixMilliseconds(
std::chrono::floor<Milliseconds>(now.time_since_epoch()));
TestSleep::AddCallback(this);
}
~FakeClock() { TestSleep::RemoveCallback(this); }
void ElapseTime(int64_t milliseconds) { now_ += milliseconds; }
void ElapseTime(int64_t milliseconds) override {
now_ += Duration::FromMilliseconds(milliseconds);
}
int64_t now() const { return now_; }
Timestamp now() const { return now_; }
private:
int64_t now_;
Timestamp now_;
};
FakeClock* g_fake_clock = nullptr;
@@ -38,7 +44,12 @@ FakeClock* g_fake_clock = nullptr;
int64_t Clock::GetCurrentTime() {
TestSleep::SyncFakeClock();
if (g_fake_clock == nullptr) g_fake_clock = new FakeClock();
return g_fake_clock->now() / 1000;
return static_cast<int64_t>(g_fake_clock->now().epoch_seconds().count());
}
Timestamp Clock::GetCurrentTimestamp() {
TestSleep::SyncFakeClock();
if (g_fake_clock == nullptr) g_fake_clock = new FakeClock();
return g_fake_clock->now();
}
} // namespace wvutil

View File

@@ -0,0 +1,464 @@
// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#include "wv_date_time.h"
#include <stdint.h>
// #include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "wv_duration.h"
#include "wv_timestamp.h"
namespace wvutil {
namespace test {
namespace {
// This is a Unix time chosen for testing.
// Friday, April 19th, 2024 13:36:18.507
// April 19th is the 110th day of the year when a leap year.
constexpr uint64_t kTestUnixTimeS = 1713533778;
constexpr uint64_t kTestUnixTimeMs = 1713533778507;
constexpr Seconds kTestTimeS = Seconds(kTestUnixTimeS);
constexpr Milliseconds kTestTimeMs = Milliseconds(kTestUnixTimeMs);
constexpr uint32_t kTestYear = 2024;
constexpr uint32_t kTestMonth = 4; // April
constexpr uint32_t kTestDay = 19;
constexpr uint32_t kTestHour = 13;
constexpr uint32_t kTestMinute = 36;
constexpr uint32_t kTestSecond = 18;
constexpr uint32_t kTestMs = 507;
constexpr uint32_t kTestDayOfWeek = 6; // Friday
constexpr uint32_t kTestDayOfYear = 110;
constexpr int64_t kOneMinuteS = 60;
constexpr int64_t kOneHourS = kOneMinuteS * 60;
constexpr int64_t kOneDayS = kOneHourS * 24;
constexpr int64_t kOneCommonYearS = kOneDayS * 365;
constexpr int64_t kOneLeapYearS = kOneDayS * 366;
constexpr int64_t kOneSecondMs = 1000;
constexpr int64_t kOneMinuteMs = kOneSecondMs * 60;
constexpr int64_t kOneHourMs = kOneMinuteMs * 60;
constexpr int64_t kOneDayMs = kOneHourMs * 24;
uint32_t DayOfWeekAddition(uint32_t day_of_week, uint32_t inc) {
return ((day_of_week - 1 + inc) % 7) + 1;
}
uint32_t DayOfWeekSubtraction(uint32_t day_of_week, uint32_t dec) {
const uint32_t reverse_day_of_week = (8 - day_of_week);
const uint32_t reverse_new_day_of_week =
DayOfWeekAddition(reverse_day_of_week, dec);
return (8 - reverse_new_day_of_week);
}
} // namespace
TEST(WvDateTimeUtilTest, FromUnixSeconds) {
const DateTime datetime = DateTime::FromUnixSeconds(kTestUnixTimeS, kTestMs);
ASSERT_TRUE(datetime.IsSet());
EXPECT_EQ(datetime.epoch_seconds(), kTestTimeS);
EXPECT_EQ(datetime.epoch_milliseconds(), kTestTimeMs);
EXPECT_EQ(datetime.year(), kTestYear);
EXPECT_EQ(datetime.month(), kTestMonth);
EXPECT_EQ(datetime.day(), kTestDay);
EXPECT_EQ(datetime.day_of_year(), kTestDayOfYear);
EXPECT_EQ(datetime.day_of_week(), kTestDayOfWeek);
EXPECT_EQ(datetime.hour(), kTestHour);
EXPECT_EQ(datetime.minute(), kTestMinute);
EXPECT_EQ(datetime.second(), kTestSecond);
EXPECT_EQ(datetime.millisecond(), kTestMs);
}
TEST(WvDateTimeUtilTest, FromUnixMilliseconds) {
const DateTime datetime = DateTime::FromUnixMilliseconds(kTestUnixTimeMs);
ASSERT_TRUE(datetime.IsSet());
EXPECT_EQ(datetime.epoch_seconds(), kTestTimeS);
EXPECT_EQ(datetime.epoch_milliseconds(), kTestTimeMs);
EXPECT_EQ(datetime.year(), kTestYear);
EXPECT_EQ(datetime.month(), kTestMonth);
EXPECT_EQ(datetime.day(), kTestDay);
EXPECT_EQ(datetime.day_of_year(), kTestDayOfYear);
EXPECT_EQ(datetime.day_of_week(), kTestDayOfWeek);
EXPECT_EQ(datetime.hour(), kTestHour);
EXPECT_EQ(datetime.minute(), kTestMinute);
EXPECT_EQ(datetime.second(), kTestSecond);
EXPECT_EQ(datetime.millisecond(), kTestMs);
}
TEST(WvDateTimeUtilTest, Min) {
// Thursday, January 1st, 1970 00:00:00.001
const DateTime datetime = DateTime::Min();
ASSERT_TRUE(datetime.IsSet());
EXPECT_EQ(datetime.epoch_seconds(), Seconds(0));
EXPECT_EQ(datetime.epoch_milliseconds(), Milliseconds(1));
EXPECT_EQ(datetime.year(), 1970u);
EXPECT_EQ(datetime.month(), 1u);
EXPECT_EQ(datetime.day(), 1u);
EXPECT_EQ(datetime.day_of_year(), 1u);
EXPECT_EQ(datetime.day_of_week(), 5u);
EXPECT_EQ(datetime.hour(), 0u);
EXPECT_EQ(datetime.minute(), 0u);
EXPECT_EQ(datetime.second(), 0u);
EXPECT_EQ(datetime.millisecond(), 1u);
}
TEST(WvDateTimeUtilTest, Max) {
constexpr int64_t kMaxEpochTimeS = 253402300799;
constexpr int64_t kMaxEpochTimeMs = (kMaxEpochTimeS * 1000) + 999;
// Friday, December 31st, 9999 23:59:59.999
const DateTime datetime = DateTime::Max();
ASSERT_TRUE(datetime.IsSet());
EXPECT_EQ(datetime.epoch_seconds(), Seconds(kMaxEpochTimeS));
EXPECT_EQ(datetime.epoch_milliseconds(), Milliseconds(kMaxEpochTimeMs));
EXPECT_EQ(datetime.year(), 9999u);
EXPECT_EQ(datetime.month(), 12u);
EXPECT_EQ(datetime.day(), 31u);
EXPECT_EQ(datetime.day_of_year(), 365u);
EXPECT_EQ(datetime.day_of_week(), 6u);
EXPECT_EQ(datetime.hour(), 23u);
EXPECT_EQ(datetime.minute(), 59u);
EXPECT_EQ(datetime.second(), 59u);
EXPECT_EQ(datetime.millisecond(), 999u);
}
TEST(WvDateTimeUtilTest, Clear) {
DateTime datetime = DateTime::FromUnixMilliseconds(kTestUnixTimeMs);
ASSERT_TRUE(datetime.IsSet());
datetime.Clear();
EXPECT_FALSE(datetime.IsSet());
EXPECT_EQ(datetime.year(), 0u);
EXPECT_EQ(datetime.month(), 0u);
EXPECT_EQ(datetime.day(), 0u);
EXPECT_EQ(datetime.day_of_year(), 0u);
EXPECT_EQ(datetime.day_of_week(), 0u);
EXPECT_EQ(datetime.hour(), 0u);
EXPECT_EQ(datetime.minute(), 0u);
EXPECT_EQ(datetime.second(), 0u);
EXPECT_EQ(datetime.millisecond(), 0u);
}
TEST(WvDateTimeUtilTest, Comparison) {
const DateTime datetime_a = DateTime::Min();
const DateTime datetime_b =
DateTime::FromUnixMilliseconds(kTestUnixTimeMs - kOneDayMs);
const DateTime datetime_c = DateTime::FromUnixMilliseconds(kTestUnixTimeMs);
const DateTime datetime_d =
DateTime::FromUnixMilliseconds(kTestUnixTimeMs + 1);
const DateTime datetime_e = DateTime::Max();
// Equality
EXPECT_EQ(datetime_a, datetime_a);
EXPECT_EQ(datetime_b, datetime_b);
EXPECT_EQ(datetime_c, datetime_c);
EXPECT_EQ(datetime_d, datetime_d);
EXPECT_EQ(datetime_e, datetime_e);
// Inequality.
EXPECT_NE(datetime_a, datetime_b);
EXPECT_NE(datetime_a, datetime_c);
EXPECT_NE(datetime_a, datetime_d);
EXPECT_NE(datetime_a, datetime_e);
EXPECT_NE(datetime_b, datetime_c);
EXPECT_NE(datetime_b, datetime_d);
EXPECT_NE(datetime_b, datetime_e);
EXPECT_NE(datetime_c, datetime_d);
EXPECT_NE(datetime_c, datetime_e);
EXPECT_NE(datetime_d, datetime_e);
// Less than
EXPECT_LT(datetime_a, datetime_b);
EXPECT_LT(datetime_a, datetime_c);
EXPECT_LT(datetime_a, datetime_d);
EXPECT_LT(datetime_a, datetime_e);
EXPECT_LT(datetime_b, datetime_c);
EXPECT_LT(datetime_b, datetime_d);
EXPECT_LT(datetime_b, datetime_e);
EXPECT_LT(datetime_c, datetime_d);
EXPECT_LT(datetime_c, datetime_e);
EXPECT_LT(datetime_d, datetime_e);
// Less than or equal.
EXPECT_LE(datetime_a, datetime_a);
EXPECT_LE(datetime_a, datetime_b);
EXPECT_LE(datetime_a, datetime_c);
EXPECT_LE(datetime_a, datetime_d);
EXPECT_LE(datetime_a, datetime_e);
EXPECT_LE(datetime_b, datetime_b);
EXPECT_LE(datetime_b, datetime_c);
EXPECT_LE(datetime_b, datetime_d);
EXPECT_LE(datetime_b, datetime_e);
EXPECT_LE(datetime_c, datetime_c);
EXPECT_LE(datetime_c, datetime_d);
EXPECT_LE(datetime_c, datetime_e);
EXPECT_LE(datetime_d, datetime_d);
EXPECT_LE(datetime_d, datetime_e);
EXPECT_LE(datetime_e, datetime_e);
// Greater than
EXPECT_GT(datetime_b, datetime_a);
EXPECT_GT(datetime_c, datetime_a);
EXPECT_GT(datetime_d, datetime_a);
EXPECT_GT(datetime_e, datetime_a);
EXPECT_GT(datetime_c, datetime_b);
EXPECT_GT(datetime_d, datetime_b);
EXPECT_GT(datetime_e, datetime_b);
EXPECT_GT(datetime_d, datetime_c);
EXPECT_GT(datetime_e, datetime_c);
EXPECT_GT(datetime_e, datetime_d);
// Greater than or equal.
EXPECT_GE(datetime_a, datetime_a);
EXPECT_GE(datetime_b, datetime_a);
EXPECT_GE(datetime_c, datetime_a);
EXPECT_GE(datetime_d, datetime_a);
EXPECT_GE(datetime_e, datetime_a);
EXPECT_GE(datetime_b, datetime_b);
EXPECT_GE(datetime_c, datetime_b);
EXPECT_GE(datetime_d, datetime_b);
EXPECT_GE(datetime_e, datetime_b);
EXPECT_GE(datetime_c, datetime_c);
EXPECT_GE(datetime_d, datetime_c);
EXPECT_GE(datetime_e, datetime_c);
EXPECT_GE(datetime_d, datetime_d);
EXPECT_GE(datetime_e, datetime_d);
EXPECT_GE(datetime_e, datetime_e);
}
TEST(WvDateTimeUtilTest, Addition_WithDuration) {
const DateTime start = DateTime::FromUnixMilliseconds(kTestUnixTimeMs);
ASSERT_TRUE(start.IsSet());
const Duration one_day = Duration::FromMilliseconds(kOneDayMs);
const DateTime tomorrow = start + one_day;
ASSERT_TRUE(tomorrow.IsSet());
EXPECT_EQ(tomorrow.epoch_seconds(), kTestTimeS + Seconds(kOneDayS));
EXPECT_EQ(tomorrow.epoch_milliseconds(),
kTestTimeMs + Milliseconds(kOneDayMs));
EXPECT_EQ(tomorrow.year(), kTestYear);
EXPECT_EQ(tomorrow.month(), kTestMonth);
EXPECT_EQ(tomorrow.day(), kTestDay + 1);
EXPECT_EQ(tomorrow.day_of_year(), kTestDayOfYear + 1);
EXPECT_EQ(tomorrow.day_of_week(), DayOfWeekAddition(kTestDayOfWeek, 1));
EXPECT_EQ(tomorrow.hour(), kTestHour);
EXPECT_EQ(tomorrow.minute(), kTestMinute);
EXPECT_EQ(tomorrow.second(), kTestSecond);
EXPECT_EQ(tomorrow.millisecond(), kTestMs);
// Note: This is 30 days for April to May.
const Duration one_month = Duration::FromSeconds(kOneDayS * 30);
const DateTime next_month = start + one_month;
EXPECT_EQ(next_month.year(), kTestYear);
EXPECT_EQ(next_month.month(), kTestMonth + 1);
EXPECT_EQ(next_month.day(), kTestDay);
EXPECT_EQ(next_month.day_of_year(), kTestDayOfYear + 30);
EXPECT_EQ(next_month.day_of_week(), DayOfWeekAddition(kTestDayOfWeek, 30));
EXPECT_EQ(next_month.hour(), kTestHour);
EXPECT_EQ(next_month.minute(), kTestMinute);
EXPECT_EQ(next_month.second(), kTestSecond);
EXPECT_EQ(next_month.millisecond(), kTestMs);
// Note: This should roll over a day.
const uint32_t day_inc_11h = (kTestHour + 11) / 24;
const Duration eleven_hours = Duration::FromSeconds(kOneHourS * 11);
const DateTime hours_later = start + eleven_hours;
EXPECT_EQ(hours_later.year(), kTestYear);
EXPECT_EQ(hours_later.month(), kTestMonth);
EXPECT_EQ(hours_later.day(), kTestDay + day_inc_11h);
EXPECT_EQ(hours_later.day_of_year(), kTestDayOfYear + day_inc_11h);
EXPECT_EQ(hours_later.day_of_week(),
DayOfWeekAddition(kTestDayOfWeek, day_inc_11h));
const uint32_t new_hour_11h = (kTestHour + 11) % 24;
EXPECT_EQ(hours_later.hour(), new_hour_11h);
EXPECT_EQ(hours_later.minute(), kTestMinute);
EXPECT_EQ(hours_later.second(), kTestSecond);
EXPECT_EQ(hours_later.millisecond(), kTestMs);
const Duration five_years =
Duration::FromSeconds(kOneCommonYearS * 4 + kOneLeapYearS);
const DateTime fewer_years_later = start + five_years;
EXPECT_EQ(fewer_years_later.year(), kTestYear + 5);
EXPECT_EQ(fewer_years_later.month(), kTestMonth);
EXPECT_EQ(fewer_years_later.day(), kTestDay);
EXPECT_EQ(fewer_years_later.hour(), kTestHour);
EXPECT_EQ(fewer_years_later.minute(), kTestMinute);
EXPECT_EQ(fewer_years_later.second(), kTestSecond);
EXPECT_EQ(fewer_years_later.millisecond(), kTestMs);
const DateTime same_time = start + Duration::Zero();
EXPECT_EQ(start, same_time);
}
TEST(WvDateTimeUtilTest, Addition_WithDuration_Invalid) {
// Addition with an unset date time is not allowed.
const DateTime unset;
ASSERT_FALSE(unset.IsSet());
const Duration one_month = Duration::FromSeconds(kOneDayS * 30);
DateTime result = unset + one_month;
EXPECT_FALSE(result.IsSet());
// Addition that causes overflow is not allowed.
result = DateTime::Max() + Duration::FromMilliseconds(1);
EXPECT_FALSE(result.IsSet());
result = DateTime::Min() + Duration::FromSeconds(kOneCommonYearS * 10000);
EXPECT_FALSE(result.IsSet());
}
TEST(WvDateTimeUtilTest, Subtraction_WithDuration) {
const DateTime start = DateTime::FromUnixMilliseconds(kTestUnixTimeMs);
ASSERT_TRUE(start.IsSet());
const Duration one_day = Duration::FromMilliseconds(kOneDayMs);
const DateTime yesterday = start - one_day;
ASSERT_TRUE(yesterday.IsSet());
EXPECT_EQ(yesterday.epoch_seconds(), Seconds(kTestUnixTimeS - kOneDayS));
EXPECT_EQ(yesterday.epoch_milliseconds(),
Milliseconds(kTestUnixTimeMs - kOneDayMs));
EXPECT_EQ(yesterday.year(), kTestYear);
EXPECT_EQ(yesterday.month(), kTestMonth);
EXPECT_EQ(yesterday.day(), kTestDay - 1);
EXPECT_EQ(yesterday.day_of_year(), kTestDayOfYear - 1);
EXPECT_EQ(yesterday.day_of_week(), DayOfWeekSubtraction(kTestDayOfWeek, 1));
EXPECT_EQ(yesterday.hour(), kTestHour);
EXPECT_EQ(yesterday.minute(), kTestMinute);
EXPECT_EQ(yesterday.second(), kTestSecond);
EXPECT_EQ(yesterday.millisecond(), kTestMs);
// Note: This is a 31 days for March.
const Duration one_month = Duration::FromSeconds(kOneDayS * 31);
const DateTime previous_month = start - one_month;
EXPECT_EQ(previous_month.year(), kTestYear);
EXPECT_EQ(previous_month.month(), kTestMonth - 1);
EXPECT_EQ(previous_month.day(), kTestDay);
EXPECT_EQ(previous_month.day_of_year(), kTestDayOfYear - 31);
EXPECT_EQ(previous_month.day_of_week(),
DayOfWeekSubtraction(kTestDayOfWeek, 31));
EXPECT_EQ(previous_month.hour(), kTestHour);
EXPECT_EQ(previous_month.minute(), kTestMinute);
EXPECT_EQ(previous_month.second(), kTestSecond);
EXPECT_EQ(previous_month.millisecond(), kTestMs);
const uint32_t day_dec_14h = (kTestHour < 14) ? 1 : 0;
const Duration fourteen_hours = Duration::FromSeconds(kOneHourS * 14);
const DateTime hours_earlier = start - fourteen_hours;
EXPECT_EQ(yesterday.year(), kTestYear);
EXPECT_EQ(yesterday.month(), kTestMonth);
EXPECT_EQ(yesterday.day(), kTestDay - day_dec_14h);
EXPECT_EQ(yesterday.day_of_year(), kTestDayOfYear - day_dec_14h);
EXPECT_EQ(yesterday.day_of_week(),
DayOfWeekSubtraction(kTestDayOfWeek, day_dec_14h));
const uint32_t new_hour_14h =
(kTestHour < 14) ? (kTestHour + 10) : kTestHour - 14;
EXPECT_EQ(hours_earlier.hour(), new_hour_14h);
EXPECT_EQ(hours_earlier.minute(), kTestMinute);
EXPECT_EQ(hours_earlier.second(), kTestSecond);
EXPECT_EQ(hours_earlier.millisecond(), kTestMs);
const Duration five_years =
Duration::FromSeconds(kOneCommonYearS * 3 + kOneLeapYearS * 2);
const DateTime few_years_earlier = start - five_years;
EXPECT_EQ(few_years_earlier.year(), kTestYear - 5);
EXPECT_EQ(few_years_earlier.month(), kTestMonth);
EXPECT_EQ(few_years_earlier.day(), kTestDay);
EXPECT_EQ(few_years_earlier.hour(), kTestHour);
EXPECT_EQ(few_years_earlier.minute(), kTestMinute);
EXPECT_EQ(few_years_earlier.second(), kTestSecond);
EXPECT_EQ(few_years_earlier.millisecond(), kTestMs);
const DateTime same_time = start - Duration::Zero();
EXPECT_EQ(start, same_time);
}
TEST(WvDateTimeUtilTest, Subtraction_WithDuration_Invalid) {
// Subtract with an unset date time is not allowed.
const DateTime unset;
ASSERT_FALSE(unset.IsSet());
const Duration one_month = Duration::FromSeconds(kOneDayS * 30);
DateTime result = unset - one_month;
EXPECT_FALSE(result.IsSet());
// Subtract that causes overflow is not allowed.
result = DateTime::Min() - Duration::FromMilliseconds(1);
EXPECT_FALSE(result.IsSet());
result = DateTime::Max() - Duration::FromSeconds(kOneCommonYearS * 10000);
EXPECT_FALSE(result.IsSet());
}
TEST(WvDateTimeUtilTest, Difference) {
const Duration expected_diff =
Duration(Hours(15) + Minutes(6) + Seconds(30) + Milliseconds(123));
const DateTime datetime_a =
DateTime::FromUnixSeconds(kTestUnixTimeS, kTestMs);
const DateTime datetime_b = DateTime::FromUnixMilliseconds(
datetime_a.epoch_milliseconds() + expected_diff.total_milliseconds());
const Duration diff_ab = datetime_b - datetime_a;
EXPECT_EQ(diff_ab, expected_diff);
const Duration diff_ba = datetime_a - datetime_b;
EXPECT_EQ(diff_ba, -expected_diff);
// Very big diff
const Duration diff_min_max = DateTime::Max() - DateTime::Min();
EXPECT_TRUE(diff_min_max.IsPositive());
const Duration diff_max_min = DateTime::Min() - DateTime::Max();
EXPECT_TRUE(diff_max_min.IsNegative());
EXPECT_EQ(diff_min_max, -diff_max_min);
// No difference.
const Duration diff_aa = datetime_a - datetime_a;
EXPECT_TRUE(diff_aa.IsZero());
}
TEST(WvDateTimeUtilTest, Difference_Invalid) {
const DateTime datetime = DateTime::FromUnixSeconds(kTestUnixTimeS, kTestMs);
const DateTime unset;
Duration diff = datetime - unset;
EXPECT_TRUE(diff.IsZero());
diff = unset - datetime;
EXPECT_TRUE(diff.IsZero());
}
TEST(WvDateTimeUtilTest, ToString) {
// Default should ISO date times with short timezones, and milliseconds
// only printed if non-zero.
DateTime datetime = DateTime::FromUnixSeconds(kTestUnixTimeS, kTestMs);
EXPECT_EQ(datetime.ToString(), "2024-04-19T13:36:18.507Z");
datetime = DateTime::FromUnixSeconds(kTestUnixTimeS);
EXPECT_EQ(datetime.ToString(), "2024-04-19T13:36:18Z");
EXPECT_EQ(DateTime::Min().ToString(), "1970-01-01T00:00:00.001Z");
EXPECT_EQ(DateTime::Max().ToString(), "9999-12-31T23:59:59.999Z");
EXPECT_EQ(DateTime().ToString(), "<unset>");
}
} // namespace test
} // namespace wvutil

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,300 @@
// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#include "wv_timestamp.h"
#include <inttypes.h>
#include <chrono>
#include <gtest/gtest.h>
#include "wv_duration.h"
namespace wvutil {
namespace test {
namespace {
constexpr uint64_t kRawValidEpochSeconds = 1733526346;
constexpr Seconds kValidEpochSeconds = Seconds(kRawValidEpochSeconds);
constexpr uint64_t kRawOutOfRangeEpochSeconds = 253402300800; // Year 10000
constexpr Seconds kOutOfRangeEpochSeconds = Seconds(kRawOutOfRangeEpochSeconds);
constexpr uint64_t kOneS = 1;
constexpr uint64_t kOneMinuteS = kOneS * 60;
constexpr uint64_t kOneHourS = kOneMinuteS * 60;
constexpr uint64_t kOneDayS = kOneHourS * 24;
} // namespace
TEST(WvTimestampUtilTest, DefaultConstructor) {
const Timestamp ts;
EXPECT_FALSE(ts.IsSet());
EXPECT_EQ(ts.epoch_milliseconds(), Milliseconds::zero());
EXPECT_EQ(ts.epoch_seconds(), Seconds::zero());
}
TEST(WvTimestampUtilTest, MinMax) {
const Timestamp max = Timestamp::Max();
EXPECT_TRUE(max.IsSet());
const Timestamp min = Timestamp::Min();
EXPECT_TRUE(min.IsSet());
EXPECT_LE(min, max);
EXPECT_GE(max, min);
}
TEST(WvTimestampUtilTest, FromUnixSeconds) {
const Milliseconds epoch_milliseconds =
std::chrono::duration_cast<Milliseconds>(kValidEpochSeconds);
const Timestamp ts = Timestamp::FromUnixSeconds(kValidEpochSeconds);
EXPECT_TRUE(ts.IsSet());
EXPECT_EQ(ts.epoch_seconds(), kValidEpochSeconds);
EXPECT_EQ(ts.epoch_milliseconds(), epoch_milliseconds);
EXPECT_EQ(ts.milliseconds(), 0u);
EXPECT_EQ(ts, Timestamp::FromUnixSeconds(kRawValidEpochSeconds));
}
TEST(WvTimestampUtilTest, FromUnixSeconds_WithMs) {
constexpr uint32_t raw_milliseconds = 123;
const Milliseconds epoch_milliseconds =
kValidEpochSeconds + Milliseconds(raw_milliseconds);
const Timestamp ts =
Timestamp::FromUnixSeconds(kValidEpochSeconds, raw_milliseconds);
EXPECT_TRUE(ts.IsSet());
EXPECT_EQ(ts.epoch_seconds(), kValidEpochSeconds);
EXPECT_EQ(ts.epoch_milliseconds(), epoch_milliseconds);
EXPECT_EQ(ts.milliseconds(), raw_milliseconds);
EXPECT_EQ(
ts, Timestamp::FromUnixSeconds(kRawValidEpochSeconds, raw_milliseconds));
}
TEST(WvTimestampUtilTest, FromUnixSeconds_SecondsOutOfRange) {
EXPECT_FALSE(Timestamp::FromUnixSeconds(kRawOutOfRangeEpochSeconds).IsSet());
EXPECT_FALSE(Timestamp::FromUnixSeconds(kOutOfRangeEpochSeconds).IsSet());
constexpr Seconds negative_epoch_seconds = Seconds(-1);
EXPECT_FALSE(Timestamp::FromUnixSeconds(negative_epoch_seconds).IsSet());
}
TEST(WvTimestampUtilTest, FromUnixSeconds_MsOutOfRange) {
EXPECT_FALSE(Timestamp::FromUnixSeconds(kValidEpochSeconds, 1000).IsSet());
EXPECT_FALSE(Timestamp::FromUnixSeconds(kRawValidEpochSeconds, 1000).IsSet());
}
TEST(WvTimestampUtilTest, FromUnixMilliseconds) {
constexpr uint32_t raw_milliseconds = 123;
constexpr uint64_t raw_total_milliseconds =
(kRawValidEpochSeconds * 1000) + raw_milliseconds;
constexpr Milliseconds epoch_milliseconds =
Milliseconds(raw_total_milliseconds);
constexpr Timestamp ts = Timestamp::FromUnixMilliseconds(epoch_milliseconds);
EXPECT_TRUE(ts.IsSet());
EXPECT_EQ(ts.epoch_seconds(), kValidEpochSeconds);
EXPECT_EQ(ts.epoch_milliseconds(), epoch_milliseconds);
EXPECT_EQ(ts.milliseconds(), raw_milliseconds);
EXPECT_EQ(ts, Timestamp::FromUnixMilliseconds(raw_total_milliseconds));
}
TEST(WvTimestampUtilTest, FromUnixMilliseconds_OutOfRange) {
constexpr uint64_t raw_total_milliseconds = kRawOutOfRangeEpochSeconds * 1000;
constexpr Milliseconds epoch_milliseconds =
Milliseconds(raw_total_milliseconds);
EXPECT_FALSE(Timestamp::FromUnixMilliseconds(raw_total_milliseconds).IsSet());
EXPECT_FALSE(Timestamp::FromUnixMilliseconds(epoch_milliseconds).IsSet());
}
TEST(WvTimestampUtilTest, Clear) {
Timestamp ts = Timestamp::FromUnixSeconds(kValidEpochSeconds);
EXPECT_TRUE(ts.IsSet());
ts.Clear();
EXPECT_FALSE(ts.IsSet());
}
TEST(WvTimestampUtilTest, Comparison) {
constexpr Timestamp ts_a = Timestamp::Min();
constexpr Timestamp ts_b =
Timestamp::FromUnixSeconds(kRawValidEpochSeconds - kOneDayS);
constexpr Timestamp ts_c = Timestamp::FromUnixSeconds(kValidEpochSeconds);
constexpr Timestamp ts_d =
Timestamp::FromUnixSeconds(kValidEpochSeconds, 123);
constexpr Timestamp ts_e = Timestamp::Max();
// Equality
EXPECT_EQ(ts_a, ts_a);
EXPECT_EQ(ts_b, ts_b);
EXPECT_EQ(ts_c, ts_c);
EXPECT_EQ(ts_d, ts_d);
EXPECT_EQ(ts_e, ts_e);
// Inequality.
EXPECT_NE(ts_a, ts_b);
EXPECT_NE(ts_a, ts_c);
EXPECT_NE(ts_a, ts_d);
EXPECT_NE(ts_a, ts_e);
EXPECT_NE(ts_b, ts_c);
EXPECT_NE(ts_b, ts_d);
EXPECT_NE(ts_b, ts_e);
EXPECT_NE(ts_c, ts_d);
EXPECT_NE(ts_c, ts_e);
EXPECT_NE(ts_d, ts_e);
// Less than
EXPECT_LT(ts_a, ts_b);
EXPECT_LT(ts_a, ts_c);
EXPECT_LT(ts_a, ts_d);
EXPECT_LT(ts_a, ts_e);
EXPECT_LT(ts_b, ts_c);
EXPECT_LT(ts_b, ts_d);
EXPECT_LT(ts_b, ts_e);
EXPECT_LT(ts_c, ts_d);
EXPECT_LT(ts_c, ts_e);
EXPECT_LT(ts_d, ts_e);
// Less than or equal.
EXPECT_LE(ts_a, ts_a);
EXPECT_LE(ts_a, ts_b);
EXPECT_LE(ts_a, ts_c);
EXPECT_LE(ts_a, ts_d);
EXPECT_LE(ts_a, ts_e);
EXPECT_LE(ts_b, ts_b);
EXPECT_LE(ts_b, ts_c);
EXPECT_LE(ts_b, ts_d);
EXPECT_LE(ts_b, ts_e);
EXPECT_LE(ts_c, ts_c);
EXPECT_LE(ts_c, ts_d);
EXPECT_LE(ts_c, ts_e);
EXPECT_LE(ts_d, ts_d);
EXPECT_LE(ts_d, ts_e);
EXPECT_LE(ts_e, ts_e);
// Greater than
EXPECT_GT(ts_b, ts_a);
EXPECT_GT(ts_c, ts_a);
EXPECT_GT(ts_d, ts_a);
EXPECT_GT(ts_e, ts_a);
EXPECT_GT(ts_c, ts_b);
EXPECT_GT(ts_d, ts_b);
EXPECT_GT(ts_e, ts_b);
EXPECT_GT(ts_d, ts_c);
EXPECT_GT(ts_e, ts_c);
EXPECT_GT(ts_e, ts_d);
// Greater than or equal.
EXPECT_GE(ts_a, ts_a);
EXPECT_GE(ts_b, ts_a);
EXPECT_GE(ts_c, ts_a);
EXPECT_GE(ts_d, ts_a);
EXPECT_GE(ts_e, ts_a);
EXPECT_GE(ts_b, ts_b);
EXPECT_GE(ts_c, ts_b);
EXPECT_GE(ts_d, ts_b);
EXPECT_GE(ts_e, ts_b);
EXPECT_GE(ts_c, ts_c);
EXPECT_GE(ts_d, ts_c);
EXPECT_GE(ts_e, ts_c);
EXPECT_GE(ts_d, ts_d);
EXPECT_GE(ts_e, ts_d);
EXPECT_GE(ts_e, ts_e);
}
TEST(WvTimestampUtilTest, Addition_WithDuration) {
constexpr Timestamp start = Timestamp::FromUnixSeconds(kValidEpochSeconds);
constexpr Duration one_day = Duration::FromSeconds(kOneDayS);
constexpr Timestamp tomorrow = start + one_day;
constexpr decltype(tomorrow.epoch_seconds().count()) expected_second_count =
kRawValidEpochSeconds + kOneDayS;
EXPECT_EQ(tomorrow.epoch_seconds().count(), expected_second_count);
}
TEST(WvTimestampUtilTest, Addition_WithDuration_Unset) {
constexpr Timestamp unset;
constexpr Duration one_day = Duration::FromSeconds(kOneDayS);
constexpr Timestamp result = unset + one_day;
EXPECT_FALSE(result.IsSet());
}
TEST(WvTimestampUtilTest, Addition_WithDuration_Overflow) {
Timestamp start = Timestamp::Max();
constexpr Duration one_day = Duration::FromSeconds(kOneDayS);
Timestamp result = start + one_day;
EXPECT_FALSE(result.IsSet());
start = Timestamp::Min();
constexpr Duration very_long_duration =
Duration::FromSeconds(kOneDayS * 365 * 10000);
result = start + very_long_duration;
EXPECT_FALSE(result.IsSet());
}
TEST(WvTimestampUtilTest, Subtraction_WithDuration) {
constexpr Timestamp start = Timestamp::FromUnixSeconds(kValidEpochSeconds);
constexpr Duration one_day = Duration::FromSeconds(kOneDayS);
constexpr Timestamp yesterday = start - one_day;
constexpr decltype(yesterday.epoch_seconds().count()) expected_second_count =
kRawValidEpochSeconds - kOneDayS;
EXPECT_EQ(yesterday.epoch_seconds().count(), expected_second_count);
}
TEST(WvTimestampUtilTest, Subtraction_WithDuration_Unset) {
constexpr Timestamp unset;
constexpr Duration one_day = Duration::FromSeconds(kOneDayS);
constexpr Timestamp result = unset - one_day;
EXPECT_FALSE(result.IsSet());
}
TEST(WvTimestampUtilTest, Subtraction_WithDuration_Underflow) {
Timestamp start = Timestamp::Min();
constexpr Duration one_day = Duration::FromSeconds(kOneDayS);
Timestamp result = start - one_day;
EXPECT_FALSE(result.IsSet());
start = Timestamp::Max();
constexpr Duration very_long_duration =
Duration::FromSeconds(kOneDayS * 365 * 10000);
result = start - very_long_duration;
EXPECT_FALSE(result.IsSet());
}
TEST(WvTimestampUtilTest, Difference) {
// 4 days, 3 hours, 2 minutes and 1 second.
constexpr int64_t kDifferenceS =
1 + 2 * kOneMinuteS + 3 * kOneHourS + 4 * kOneDayS;
constexpr Timestamp ts_a = Timestamp::FromUnixSeconds(kValidEpochSeconds);
constexpr Timestamp ts_b =
Timestamp::FromUnixSeconds(kRawValidEpochSeconds + kDifferenceS);
constexpr Duration diff_ab = ts_b - ts_a;
EXPECT_EQ(diff_ab.total_seconds().count(), kDifferenceS);
constexpr Duration diff_ba = ts_a - ts_b;
EXPECT_EQ(diff_ba.total_seconds().count(), -kDifferenceS);
}
TEST(WvTimestampUtilTest, Difference_Unset) {
constexpr Duration unset_duration;
constexpr Timestamp ts = Timestamp::FromUnixSeconds(kValidEpochSeconds);
constexpr Timestamp unset;
EXPECT_EQ(ts - unset, unset_duration);
EXPECT_EQ(unset - ts, unset_duration);
EXPECT_EQ(unset - unset, unset_duration);
}
} // namespace test
} // namespace wvutil