166 lines
7.8 KiB
JavaScript
166 lines
7.8 KiB
JavaScript
const { SatLocLogParser } = require('./helpers/satloc_log_parser');
|
|
|
|
/**
|
|
* Test timestamp parsing with rollover cases
|
|
*/
|
|
function testTimestampRollover() {
|
|
const parser = new SatLocLogParser();
|
|
|
|
console.log('=== SatLoc Timestamp Rollover Test ===\n');
|
|
|
|
// Helper function to create timestamp bytes
|
|
function createTimestamp(year, month, day, hour, minute, seconds, hundredths) {
|
|
const yearOffset = year - 1993;
|
|
const yearLow4 = yearOffset & 0x0F;
|
|
const yearHigh3 = (yearOffset >> 4) & 0x07;
|
|
|
|
// Byte 4: (Y<<4) + Month
|
|
const byte4 = (yearLow4 << 4) | month;
|
|
|
|
// 4 bytes: ((Y>>4)<<29) + (Day<<24) + (Hour<<19) + (Minute<<13) + (Seconds<<7) + Hundredths
|
|
const timeValue = ((yearHigh3 << 29) >>> 0) |
|
|
(day << 24) |
|
|
(hour << 19) |
|
|
(minute << 13) |
|
|
(seconds << 7) |
|
|
hundredths;
|
|
|
|
const buffer = Buffer.alloc(5);
|
|
buffer[0] = byte4;
|
|
buffer.writeUInt32LE(timeValue, 1);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
// Test cases
|
|
const testCases = [
|
|
// Modern format (7-bit year) - uses high bits
|
|
{ year: 2024, month: 9, day: 11, hour: 14, minute: 30, seconds: 45, hundredths: 50, desc: 'Modern format: 2024' },
|
|
];
|
|
|
|
// Test legacy format by creating timestamps that only use 4-bit year (force high bits to 0)
|
|
const legacyTestCases = [
|
|
{ year: 1993, month: 1, day: 1, hour: 0, minute: 0, seconds: 0, hundredths: 0, desc: 'Legacy format: 1993' },
|
|
{ year: 2000, month: 6, day: 15, hour: 12, minute: 0, seconds: 0, hundredths: 0, desc: 'Legacy format: 2000' },
|
|
{ year: 2008, month: 12, day: 31, hour: 23, minute: 59, seconds: 59, hundredths: 99, desc: 'Legacy format: 2008 (last before rollover)' },
|
|
];
|
|
|
|
function createLegacyTimestamp(year, month, day, hour, minute, seconds, hundredths) {
|
|
const yearOffset = year - 1993;
|
|
const yearLow4 = yearOffset & 0x0F; // Only use low 4 bits, ignore high bits
|
|
|
|
// Byte 4: (Y<<4) + Month - only low 4 bits of year
|
|
const byte4 = (yearLow4 << 4) | month;
|
|
|
|
// 4 bytes: NO high year bits (yearHigh3 = 0)
|
|
const timeValue = (day << 24) | (hour << 19) | (minute << 13) | (seconds << 7) | hundredths;
|
|
|
|
const buffer = Buffer.alloc(5);
|
|
buffer[0] = byte4;
|
|
buffer.writeUInt32LE(timeValue, 1);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
// Test legacy rollover cases manually by creating 4-bit only timestamps
|
|
console.log('Testing legacy 4-bit rollover cases:\n');
|
|
|
|
// Create timestamps that only use 4-bit year (high 3 bits = 0)
|
|
const rolloverTestCases = [
|
|
{ yearOffset: 0, expectedYear: 1993, desc: 'Legacy: offset 0 -> 1993' },
|
|
{ yearOffset: 7, expectedYear: 2000, desc: 'Legacy: offset 7 -> 2000' },
|
|
{ yearOffset: 15, expectedYear: 2008, desc: 'Legacy: offset 15 -> 2008 (last before rollover)' },
|
|
{ yearOffset: 0, expectedYear: 2009, desc: 'Legacy rollover: offset 0 -> 2009 (if detected as rollover)' },
|
|
{ yearOffset: 5, expectedYear: 2014, desc: 'Legacy rollover: offset 5 -> 2014 (if detected as rollover)' },
|
|
];
|
|
|
|
rolloverTestCases.forEach((testCase, index) => {
|
|
const { yearOffset, expectedYear, desc } = testCase;
|
|
|
|
// Create legacy format timestamp (high 3 bits = 0)
|
|
const buffer = Buffer.alloc(5);
|
|
const month = 6;
|
|
const day = 15;
|
|
const hour = 12;
|
|
const minute = 30;
|
|
const seconds = 45;
|
|
const hundredths = 50;
|
|
|
|
// Byte 4: only low 4 bits for year
|
|
buffer[0] = (yearOffset << 4) | month;
|
|
|
|
// 4 bytes: no high year bits (yearHigh3 = 0)
|
|
const timeValue = (day << 24) | (hour << 19) | (minute << 13) | (seconds << 7) | hundredths;
|
|
buffer.writeUInt32LE(timeValue, 1);
|
|
|
|
const result = parser.parseTimestamp(buffer, 0);
|
|
|
|
console.log(`${desc}:`);
|
|
console.log(` Input: yearOffset=${yearOffset}, month=${month}, day=${day}`);
|
|
console.log(` Bytes: [${Array.from(buffer).map(b => '0x' + b.toString(16).padStart(2, '0')).join(', ')}]`);
|
|
|
|
if (result) {
|
|
console.log(` Parsed: ${result.year}-${result.month.toString().padStart(2, '0')}-${result.day.toString().padStart(2, '0')} ${result.hour.toString().padStart(2, '0')}:${result.minute.toString().padStart(2, '0')}:${result.seconds.toString().padStart(2, '0')}.${result.milliseconds.toString().padStart(3, '0')}`);
|
|
console.log(` Year: ${result.year} (expected around ${expectedYear})`);
|
|
} else {
|
|
console.log(` Parsed: null (invalid)`);
|
|
}
|
|
console.log();
|
|
});
|
|
|
|
// Test normal cases
|
|
console.log('Testing normal cases:\n');
|
|
testCases.forEach((testCase, index) => {
|
|
const { year, month, day, hour, minute, seconds, hundredths, desc } = testCase;
|
|
const buffer = createTimestamp(year, month, day, hour, minute, seconds, hundredths);
|
|
const result = parser.parseTimestamp(buffer, 0);
|
|
|
|
console.log(`${desc}:`);
|
|
console.log(` Input: ${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${(hundredths * 10).toString().padStart(3, '0')}`);
|
|
console.log(` Bytes: [${Array.from(buffer).map(b => '0x' + b.toString(16).padStart(2, '0')).join(', ')}]`);
|
|
|
|
if (result) {
|
|
console.log(` Parsed: ${result.year}-${result.month.toString().padStart(2, '0')}-${result.day.toString().padStart(2, '0')} ${result.hour.toString().padStart(2, '0')}:${result.minute.toString().padStart(2, '0')}:${result.seconds.toString().padStart(2, '0')}.${result.milliseconds.toString().padStart(3, '0')}`);
|
|
const match = result.year === year && result.month === month && result.day === day &&
|
|
result.hour === hour && result.minute === minute && result.seconds === seconds &&
|
|
result.milliseconds === hundredths * 10;
|
|
console.log(` Match: ${match ? 'PASS' : 'FAIL'}`);
|
|
} else {
|
|
console.log(` Parsed: null (invalid)`);
|
|
}
|
|
console.log();
|
|
});
|
|
|
|
// Test legacy format cases
|
|
console.log('Testing legacy format cases:\n');
|
|
legacyTestCases.forEach((testCase, index) => {
|
|
const { year, month, day, hour, minute, seconds, hundredths, desc } = testCase;
|
|
const buffer = createLegacyTimestamp(year, month, day, hour, minute, seconds, hundredths);
|
|
const result = parser.parseTimestamp(buffer, 0);
|
|
|
|
console.log(`${desc}:`);
|
|
console.log(` Input: ${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${(hundredths * 10).toString().padStart(3, '0')}`);
|
|
console.log(` Bytes: [${Array.from(buffer).map(b => '0x' + b.toString(16).padStart(2, '0')).join(', ')}]`);
|
|
|
|
if (result) {
|
|
console.log(` Parsed: ${result.year}-${result.month.toString().padStart(2, '0')}-${result.day.toString().padStart(2, '0')} ${result.hour.toString().padStart(2, '0')}:${result.minute.toString().padStart(2, '0')}:${result.seconds.toString().padStart(2, '0')}.${result.milliseconds.toString().padStart(3, '0')}`);
|
|
// For legacy formats, we expect rollover correction for recent years
|
|
const expectedYear = year <= 2008 && (new Date().getFullYear() - year) > 15 ? year + 16 : year;
|
|
const match = result.year === expectedYear && result.month === month && result.day === day &&
|
|
result.hour === hour && result.minute === minute && result.seconds === seconds &&
|
|
result.milliseconds === hundredths * 10;
|
|
console.log(` Expected Year: ${expectedYear} (rollover ${expectedYear !== year ? 'applied' : 'not applied'})`);
|
|
console.log(` Match: ${match ? 'PASS' : 'FAIL'}`);
|
|
} else {
|
|
console.log(` Parsed: null (invalid)`);
|
|
}
|
|
console.log();
|
|
});
|
|
}
|
|
|
|
if (require.main === module) {
|
|
testTimestampRollover();
|
|
}
|
|
|
|
module.exports = { testTimestampRollover };
|