backend-infra-engineer: Release v0.3.0 snapshot

This commit is contained in:
scawful
2025-09-27 00:25:45 -04:00
parent 8ce29e1436
commit e32ac75b9c
346 changed files with 55946 additions and 11764 deletions

134
test/emu/audio/apu_test.cc Normal file
View File

@@ -0,0 +1,134 @@
#include "app/emu/audio/apu.h"
#include "app/emu/memory/memory.h"
#include <gmock/gmock-nice-strict.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace yaze {
namespace test {
using testing::_;
using testing::Return;
using yaze::emu::Apu;
using yaze::emu::MemoryImpl;
class ApuTest : public ::testing::Test {
protected:
void SetUp() override {
memory_ = std::make_unique<MemoryImpl>();
apu_ = std::make_unique<Apu>(*memory_);
apu_->Init();
}
std::unique_ptr<MemoryImpl> memory_;
std::unique_ptr<Apu> apu_;
};
// Test the IPL ROM handshake sequence timing
TEST_F(ApuTest, IplRomHandshakeTiming) {
// 1. Initial state check
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0); // Ready bit should be clear
// 2. Start handshake
apu_->Write(0x00, 0x80); // Set control register bit 7
// 3. Wait for APU ready signal with cycle counting
int cycles = 0;
const int max_cycles = 1000; // Maximum expected cycles for handshake
while (!(apu_->Read(0x00) & 0x80) && cycles < max_cycles) {
apu_->RunCycles(1);
cycles++;
}
// 4. Verify timing constraints
EXPECT_LT(cycles, max_cycles); // Should complete within max cycles
EXPECT_GT(cycles, 0); // Should take some cycles
EXPECT_TRUE(apu_->Read(0x00) & 0x80); // Ready bit should be set
// 5. Verify handshake completion
EXPECT_EQ(apu_->GetStatus() & 0x80, 0x80); // Ready bit in status register
}
// Test APU initialization sequence
TEST_F(ApuTest, ApuInitialization) {
// 1. Check initial state
EXPECT_EQ(apu_->GetStatus(), 0x00);
EXPECT_EQ(apu_->GetControl(), 0x00);
// 2. Initialize APU
apu_->Init();
// 3. Verify initialization
EXPECT_EQ(apu_->GetStatus(), 0x00);
EXPECT_EQ(apu_->GetControl(), 0x00);
// 4. Check DSP registers are initialized
for (int i = 0; i < 128; i++) {
EXPECT_EQ(apu_->Read(0x00 + i), 0x00);
}
}
// Test sample generation and timing
TEST_F(ApuTest, SampleGenerationTiming) {
// 1. Generate samples
const int sample_count = 1024;
std::vector<int16_t> samples(sample_count);
// 2. Measure timing
uint64_t start_cycles = apu_->GetCycles();
apu_->GetSamples(samples.data(), sample_count, false);
uint64_t end_cycles = apu_->GetCycles();
// 3. Verify timing
EXPECT_GT(end_cycles - start_cycles, 0);
// 4. Verify samples
bool has_non_zero = false;
for (int i = 0; i < sample_count; ++i) {
if (samples[i] != 0) {
has_non_zero = true;
break;
}
}
EXPECT_TRUE(has_non_zero);
}
// Test DSP register access timing
TEST_F(ApuTest, DspRegisterAccessTiming) {
// 1. Write to DSP registers
const uint8_t test_value = 0x42;
uint64_t start_cycles = apu_->GetCycles();
apu_->Write(0x00, 0x80); // Set control register
apu_->Write(0x01, test_value); // Write to DSP address
uint64_t end_cycles = apu_->GetCycles();
// 2. Verify timing
EXPECT_GT(end_cycles - start_cycles, 0);
// 3. Verify register access
EXPECT_EQ(apu_->Read(0x01), test_value);
}
// Test DMA transfer timing
TEST_F(ApuTest, DmaTransferTiming) {
// 1. Prepare DMA data
const uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
// 2. Measure DMA timing
uint64_t start_cycles = apu_->GetCycles();
apu_->WriteDma(0x00, data, sizeof(data));
uint64_t end_cycles = apu_->GetCycles();
// 3. Verify timing
EXPECT_GT(end_cycles - start_cycles, 0);
// 4. Verify DMA transfer
EXPECT_EQ(apu_->Read(0x00), 0x01);
EXPECT_EQ(apu_->Read(0x01), 0x02);
}
} // namespace test
} // namespace yaze

View File

@@ -0,0 +1,122 @@
#include "app/emu/audio/apu.h"
#include "app/emu/memory/memory.h"
#include <gmock/gmock-nice-strict.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace yaze {
namespace test {
using testing::_;
using testing::Return;
using yaze::emu::Apu;
using yaze::emu::MemoryImpl;
class IplHandshakeTest : public ::testing::Test {
protected:
void SetUp() override {
memory_ = std::make_unique<MemoryImpl>();
apu_ = std::make_unique<Apu>(*memory_);
apu_->Init();
}
std::unique_ptr<MemoryImpl> memory_;
std::unique_ptr<Apu> apu_;
};
// Test IPL ROM handshake timing with exact cycle counts
TEST_F(IplHandshakeTest, ExactCycleTiming) {
// 1. Initial state
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0); // Ready bit should be clear
// 2. Start handshake
apu_->Write(0x00, 0x80); // Set control register bit 7
// 3. Run exact number of cycles for handshake
const int expected_cycles = 64; // Expected cycle count for handshake
apu_->RunCycles(expected_cycles);
// 4. Verify handshake completed
EXPECT_TRUE(apu_->Read(0x00) & 0x80); // Ready bit should be set
EXPECT_EQ(apu_->GetStatus() & 0x80, 0x80); // Ready bit in status register
}
// Test IPL ROM handshake timing with cycle range
TEST_F(IplHandshakeTest, CycleRange) {
// 1. Initial state
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0); // Ready bit should be clear
// 2. Start handshake
apu_->Write(0x00, 0x80); // Set control register bit 7
// 3. Wait for handshake with cycle counting
int cycles = 0;
const int min_cycles = 32; // Minimum expected cycles
const int max_cycles = 96; // Maximum expected cycles
while (!(apu_->Read(0x00) & 0x80) && cycles < max_cycles) {
apu_->RunCycles(1);
cycles++;
}
// 4. Verify timing constraints
EXPECT_GE(cycles, min_cycles); // Should take at least min_cycles
EXPECT_LE(cycles, max_cycles); // Should complete within max_cycles
EXPECT_TRUE(apu_->Read(0x00) & 0x80); // Ready bit should be set
}
// Test IPL ROM handshake with multiple attempts
TEST_F(IplHandshakeTest, MultipleAttempts) {
const int num_attempts = 10;
std::vector<int> cycle_counts;
for (int i = 0; i < num_attempts; i++) {
// Reset APU
apu_->Init();
// Start handshake
apu_->Write(0x00, 0x80);
// Count cycles until ready
int cycles = 0;
while (!(apu_->Read(0x00) & 0x80) && cycles < 1000) {
apu_->RunCycles(1);
cycles++;
}
// Record cycle count
cycle_counts.push_back(cycles);
// Verify handshake completed
EXPECT_TRUE(apu_->Read(0x00) & 0x80);
}
// Verify cycle count consistency
int min_cycles = *std::min_element(cycle_counts.begin(), cycle_counts.end());
int max_cycles = *std::max_element(cycle_counts.begin(), cycle_counts.end());
EXPECT_LE(max_cycles - min_cycles, 2); // Cycle count should be consistent
}
// Test IPL ROM handshake with interrupts
TEST_F(IplHandshakeTest, WithInterrupts) {
// 1. Initial state
EXPECT_EQ(apu_->Read(0x00) & 0x80, 0);
// 2. Enable interrupts
apu_->Write(0x00, 0x80 | 0x40); // Set control register bits 7 and 6
// 3. Run cycles with interrupts
int cycles = 0;
while (!(apu_->Read(0x00) & 0x80) && cycles < 1000) {
apu_->RunCycles(1);
cycles++;
}
// 4. Verify handshake completed
EXPECT_TRUE(apu_->Read(0x00) & 0x80);
EXPECT_EQ(apu_->GetStatus() & 0x80, 0x80);
}
} // namespace test
} // namespace yaze