╭ ssh_tui.zig ──────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1 const std = @import("std"); 2 const hx = @import("haxy"); 3 const ssh_tui = hx.ssh_tui; 4 5 test "prelude round-trip" { 6 const allocator = std.testing.allocator; 7 8 var out: std.Io.Writer.Allocating = .init(allocator); 9 defer out.deinit(); 10 11 try ssh_tui.writePrelude(&out.writer, .{ 12 .user_key = "SHA256:abcdef", 13 .term = "xterm-256color", 14 .width = 120, 15 .height = 40, 16 }); 17 18 var in = std.Io.Reader.fixed(out.written()); 19 const prelude = try ssh_tui.readPrelude(allocator, &in); 20 defer prelude.deinit(allocator); 21 22 try std.testing.expectEqualStrings("SHA256:abcdef", prelude.user_key); 23 try std.testing.expectEqualStrings("xterm-256color", prelude.term); 24 try std.testing.expectEqual(@as(u16, 120), prelude.width); 25 try std.testing.expectEqual(@as(u16, 40), prelude.height); 26 } 27 28 test "prelude rejects bad magic" { 29 const allocator = std.testing.allocator; 30 var in = std.Io.Reader.fixed("not-the-magic\nuser-key=x\nterm=x\nwidth=80\nheight=24\n\n"); 31 try std.testing.expectError(error.InvalidMagic, ssh_tui.readPrelude(allocator, &in)); 32 } 33 34 test "prelude rejects missing field" { 35 const allocator = std.testing.allocator; 36 var in = std.Io.Reader.fixed("haxy-tui-v1\nuser-key=x\nwidth=80\nheight=24\n\n"); 37 try std.testing.expectError(error.InvalidPrelude, ssh_tui.readPrelude(allocator, &in)); 38 } 39 40 test "prelude rejects unparseable width" { 41 const allocator = std.testing.allocator; 42 var in = std.Io.Reader.fixed("haxy-tui-v1\nuser-key=x\nterm=x\nwidth=wide\nheight=24\n\n"); 43 try std.testing.expectError(error.InvalidPrelude, ssh_tui.readPrelude(allocator, &in)); 44 } 45 46 test "prelude rejects oversized user-key" { 47 const allocator = std.testing.allocator; 48 var buf: std.Io.Writer.Allocating = .init(allocator); 49 defer buf.deinit(); 50 try buf.writer.writeAll("haxy-tui-v1\nuser-key="); 51 try buf.writer.splatByteAll('x', ssh_tui.max_user_key_len + 1); 52 try buf.writer.writeAll("\nterm=x\nwidth=80\nheight=24\n\n"); 53 54 var in = std.Io.Reader.fixed(buf.written()); 55 try std.testing.expectError(error.InvalidPrelude, ssh_tui.readPrelude(allocator, &in)); 56 } 57 58 test "data frame round-trip" { 59 const allocator = std.testing.allocator; 60 61 var out: std.Io.Writer.Allocating = .init(allocator); 62 defer out.deinit(); 63 try ssh_tui.writeDataFrame(&out.writer, "hello"); 64 65 var in = std.Io.Reader.fixed(out.written()); 66 const frame = try ssh_tui.readFrame(allocator, &in); 67 defer frame.deinit(allocator); 68 69 try std.testing.expectEqualStrings("hello", frame.data); 70 } 71 72 test "resize frame round-trip" { 73 const allocator = std.testing.allocator; 74 75 var out: std.Io.Writer.Allocating = .init(allocator); 76 defer out.deinit(); 77 try ssh_tui.writeResizeFrame(&out.writer, 132, 50); 78 79 var in = std.Io.Reader.fixed(out.written()); 80 const frame = try ssh_tui.readFrame(allocator, &in); 81 defer frame.deinit(allocator); 82 83 try std.testing.expectEqual(@as(u16, 132), frame.resize.width); 84 try std.testing.expectEqual(@as(u16, 50), frame.resize.height); 85 } 86 87 test "close frame round-trip" { 88 const allocator = std.testing.allocator; 89 90 var out: std.Io.Writer.Allocating = .init(allocator); 91 defer out.deinit(); 92 try ssh_tui.writeCloseFrame(&out.writer); 93 94 var in = std.Io.Reader.fixed(out.written()); 95 const frame = try ssh_tui.readFrame(allocator, &in); 96 defer frame.deinit(allocator); 97 98 try std.testing.expect(frame == .close); 99 } 100 101 test "frame rejects unknown type" { 102 const allocator = std.testing.allocator; 103 // type 0xFF (unknown), length 0 104 var in = std.Io.Reader.fixed(&[_]u8{ 0xFF, 0, 0, 0, 0 }); 105 try std.testing.expectError(error.InvalidFrameType, ssh_tui.readFrame(allocator, &in)); 106 } 107 108 test "frame rejects oversized data payload" { 109 const allocator = std.testing.allocator; 110 // type 0x01 (data), length max+1 111 var header: [5]u8 = undefined; 112 header[0] = 0x01; 113 std.mem.writeInt(u32, header[1..5], @intCast(ssh_tui.max_data_frame_len + 1), .big); 114 115 var in = std.Io.Reader.fixed(&header); 116 try std.testing.expectError(error.FrameTooLarge, ssh_tui.readFrame(allocator, &in)); 117 } 118 119 test "frame rejects resize with wrong length" { 120 const allocator = std.testing.allocator; 121 // type 0x02 (resize), length 3 (should be 4) 122 var in = std.Io.Reader.fixed(&[_]u8{ 0x02, 0, 0, 0, 3, 0, 0, 0 }); 123 try std.testing.expectError(error.InvalidResizeFrame, ssh_tui.readFrame(allocator, &in)); 124 } 125 126 test "frame rejects close with non-zero length" { 127 const allocator = std.testing.allocator; 128 // type 0x03 (close), length 1 (should be 0) 129 var in = std.Io.Reader.fixed(&[_]u8{ 0x03, 0, 0, 0, 1, 0 }); 130 try std.testing.expectError(error.InvalidCloseFrame, ssh_tui.readFrame(allocator, &in)); 131 } 132