// File: AndreRenaud[P]simple_uart/simple_uart_test.c
// Function: test_read_timeout
void test_read_timeout(void)
{
    struct simple_uart *u1, *u2;
    char buffer[10];
    pid_t pid;
    uint64_t start_time, end_time;

    pid = setup_loopback();

    u1 = simple_uart_open(UART_LOOPBACK_1, 115200, "8N1");
    TEST_ASSERT(u1 != NULL);
    u2 = simple_uart_open(UART_LOOPBACK_2, 115200, "8N1");
    TEST_ASSERT(u2 != NULL);

    /* Test timeout=0 (non-blocking) - should return immediately */
    start_time = mseconds();
    ssize_t result = simple_uart_read_timeout(u1, buffer, sizeof(buffer), 0);
    end_time = mseconds();
    TEST_ASSERT(result == -ETIMEDOUT);          // Nothing was available, so it timed out
    TEST_ASSERT((end_time - start_time) < 100); // Should return quickly

    /* Try reading nothing */
    result = simple_uart_read_timeout(u1, buffer, 0, 0);
    TEST_ASSERT(result == 0); // Should return 0 for reading nothing

    /* Test with actual timeout - should timeout after specified period */
    start_time = mseconds();
    result = simple_uart_read_timeout(u1, buffer, sizeof(buffer), 200); // 200ms timeout
    end_time = mseconds();
    TEST_ASSERT(result == -ETIMEDOUT);           // Should timeout
    TEST_ASSERT((end_time - start_time) >= 180); // Should wait at least ~180ms
    TEST_ASSERT((end_time - start_time) < 500);  // But not too long

    /* Test successful read within timeout */
    simple_uart_write(u2, "test", 4);
    usleep(10000); // Small delay to ensure data is available
    start_time = mseconds();
    result = simple_uart_read_timeout(u1, buffer, sizeof(buffer), 1000); // 1 second timeout
    end_time = mseconds();
    TEST_ASSERT(result == 4); // Should read 4 bytes
    TEST_ASSERT(memcmp(buffer, "test", 4) == 0);
    TEST_ASSERT((end_time - start_time) < 100); // Should return quickly when data is available

    simple_uart_close(u1);
    simple_uart_close(u2);
    shutdown_loopback(pid);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
callq 0x48e0
movl %eax, -0x20(%rbp)
leaq 0x4048(%rip), %rdi      # 0x931f
movl $0x1c200, %esi          # imm = 0x1C200
leaq 0x4047(%rip), %rdx      # 0x932a
callq 0x6a90
movq %rax, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x402a(%rip), %rsi      # 0x932e
movl $0xac, %edx
leaq 0x45f4(%rip), %rcx      # 0x9904
leaq 0x4037(%rip), %r8       # 0x934e
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x5328
callq 0x3290
jmp 0x532a
leaq 0x4028(%rip), %rdi      # 0x9359
movl $0x1c200, %esi          # imm = 0x1C200
leaq 0x3fed(%rip), %rdx      # 0x932a
callq 0x6a90
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3fd0(%rip), %rsi      # 0x932e
movl $0xae, %edx
leaq 0x459a(%rip), %rcx      # 0x9904
leaq 0x3ff3(%rip), %r8       # 0x9364
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x5382
callq 0x3290
jmp 0x5384
callq 0x56d0
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x1a(%rbp), %rsi
movl $0xa, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0x6630
movq %rax, -0x38(%rbp)
callq 0x56d0
movq %rax, -0x30(%rbp)
cmpq $-0x6e, -0x38(%rbp)
sete %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3f66(%rip), %rsi      # 0x932e
movl $0xb4, %edx
leaq 0x4530(%rip), %rcx      # 0x9904
leaq 0x4238(%rip), %r8       # 0x9613
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x53ec
callq 0x3290
jmp 0x53ee
jmp 0x53f0
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
cmpq $0x64, %rax
setb %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3f1f(%rip), %rsi      # 0x932e
movl $0xb5, %edx
leaq 0x44e9(%rip), %rcx      # 0x9904
leaq 0x4206(%rip), %r8       # 0x9628
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x5433
callq 0x3290
jmp 0x5435
movq -0x8(%rbp), %rdi
leaq -0x1a(%rbp), %rsi
xorl %eax, %eax
movl %eax, %ecx
movq %rcx, %rdx
callq 0x6630
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
sete %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3ec9(%rip), %rsi      # 0x932e
movl $0xb9, %edx
leaq 0x4493(%rip), %rcx      # 0x9904
leaq 0x41ce(%rip), %r8       # 0x9646
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x5489
callq 0x3290
jmp 0x548b
callq 0x56d0
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x1a(%rbp), %rsi
movl $0xa, %edx
movl $0xc8, %ecx
callq 0x6630
movq %rax, -0x38(%rbp)
callq 0x56d0
movq %rax, -0x30(%rbp)
cmpq $-0x6e, -0x38(%rbp)
sete %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3e5e(%rip), %rsi      # 0x932e
movl $0xbf, %edx
leaq 0x4428(%rip), %rcx      # 0x9904
leaq 0x4130(%rip), %r8       # 0x9613
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x54f4
callq 0x3290
jmp 0x54f6
jmp 0x54f8
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
cmpq $0xb4, %rax
setae %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3e15(%rip), %rsi      # 0x932e
movl $0xc0, %edx
leaq 0x43df(%rip), %rcx      # 0x9904
leaq 0x4126(%rip), %r8       # 0x9652
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x553d
callq 0x3290
jmp 0x553f
jmp 0x5541
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
cmpq $0x1f4, %rax            # imm = 0x1F4
setb %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3dcc(%rip), %rsi      # 0x932e
movl $0xc1, %edx
leaq 0x4396(%rip), %rcx      # 0x9904
leaq 0x40fc(%rip), %r8       # 0x9671
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x5586
callq 0x3290
jmp 0x5588
movq -0x10(%rbp), %rdi
leaq 0x40fc(%rip), %rsi      # 0x968f
movl $0x4, %edx
callq 0x68b0
movl $0x2710, %edi           # imm = 0x2710
callq 0x23e0
callq 0x56d0
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rdi
leaq -0x1a(%rbp), %rsi
movl $0xa, %edx
movl $0x3e8, %ecx            # imm = 0x3E8
callq 0x6630
movq %rax, -0x38(%rbp)
callq 0x56d0
movq %rax, -0x30(%rbp)
cmpq $0x4, -0x38(%rbp)
sete %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3d42(%rip), %rsi      # 0x932e
movl $0xc9, %edx
leaq 0x430c(%rip), %rcx      # 0x9904
leaq 0x4095(%rip), %r8       # 0x9694
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x5610
callq 0x3290
jmp 0x5612
jmp 0x5614
leaq -0x1a(%rbp), %rax
movl (%rax), %eax
subl $0x74736574, %eax       # imm = 0x74736574
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
sete %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3cf3(%rip), %rsi      # 0x932e
movl $0xca, %edx
leaq 0x42bd(%rip), %rcx      # 0x9904
leaq 0x4052(%rip), %r8       # 0x96a0
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x565f
callq 0x3290
jmp 0x5661
jmp 0x5663
movq -0x30(%rbp), %rax
subq -0x28(%rbp), %rax
cmpq $0x64, %rax
setb %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edi
leaq 0x3cac(%rip), %rsi      # 0x932e
movl $0xcb, %edx
leaq 0x4276(%rip), %rcx      # 0x9904
leaq 0x3f93(%rip), %r8       # 0x9628
movb $0x0, %al
callq 0x26e0
cmpl $0x0, %eax
jne 0x56a6
callq 0x3290
jmp 0x56a8
movq -0x8(%rbp), %rdi
callq 0x6a20
movq -0x10(%rbp), %rdi
callq 0x6a20
movl -0x20(%rbp), %edi
callq 0x4980
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)