/* test_blocks.c -- the kernel serves a node's block requests. * docs/v4.0.0/MESH.md sections 8.2 and 8.3. * * A node, stopped, with a number and an address on its data stack; the * blocks are v3's block subsystem (v3/src/block_subsystem.c): its fast RAM * and a device of 64 blocks. */ #include "v4/blocks.h" #include #include #include #include "block_subsystem.h" extern void sf_time_init(void); extern void log_set_level(int level); static int failures = 0, checks = 0; #define CHECK(c,...) do{checks++; if(!(c)){failures++; printf("FAIL %s:%d: ",__FILE__,__LINE__); printf(__VA_ARGS__); printf("\n");}}while(0) #define DEVICE_BLOCKS 64u #define BUF 100 static unsigned char ram[(size_t)BLK_RAM_BLOCKS * BLK_FORTH_SIZE], dev[DEVICE_BLOCKS * BLK_FORTH_SIZE]; static v4_node n; static v4_cell ask(v4_cell request, v4_cell block, v4_cell addr) { v4_dstack_push(&n.ds, 7777); v4_dstack_push(&n.ds, block); v4_dstack_push(&n.ds, addr); if (!v4_blocks_serve(&n, request)) return -100; { v4_cell status = v4_dstack_pop(&n.ds); return v4_dstack_pop(&n.ds) == 7777 ? status : -200; /* what was under its arguments is still there */ } } int main(void) { unsigned i; v4_cell top = (v4_cell)V4_NODE_WORDS; printf("v4 block request tests: V4_CELL_BITS=%d, V4_NODE_WORDS=%u\n", V4_CELL_BITS, (unsigned)V4_NODE_WORDS); sf_time_init(); log_set_level(-1); CHECK(blk_subsys_init(ram, sizeof ram) == BLK_OK && blk_subsys_add_raw_device(dev, DEVICE_BLOCKS) == BLK_OK, "the kernel's chain: fast RAM and a device of 64 blocks"); v4_node_reset(&n); /* ---- a block is written and read ---- */ for (i = 0; i < V4_BLOCK_CELLS; i++) n.mem[BUF + i] = (v4_cell)((v4_ucell)0x41424344u + i); #if V4_CELL_BITS > 32 n.mem[BUF + 5] = (v4_cell)0x7766554433221100LL; /* only its low 32 bits are the block's */ #endif CHECK(ask(V4_REQ_BLOCK_WRITE, 2050, BUF) == V4_BLOCK_OK, "a block is written"); CHECK(dev[2 * 1024] == 0x44 && dev[2 * 1024 + 1] == 0x43 && dev[2 * 1024 + 2] == 0x42 && dev[2 * 1024 + 3] == 0x41 && dev[2 * 1024 + 4] == 0x45, "block 2050 is the device's third, four bytes to a cell, the first lowest"); CHECK(dev[1 * 1024 + 1023] == 0 && dev[3 * 1024] == 0, "and no other block was touched"); for (i = 0; i < V4_BLOCK_CELLS; i++) n.mem[400 + i] = -1; CHECK(ask(V4_REQ_BLOCK_READ, 2050, 400) == V4_BLOCK_OK, "it is read"); for (i = 0; i < V4_BLOCK_CELLS && (i == 5 || n.mem[400 + i] == (v4_cell)((v4_ucell)0x41424344u + i)); i++) { } CHECK(i == V4_BLOCK_CELLS, "as it was written: cell %u differs", i); #if V4_CELL_BITS > 32 CHECK(n.mem[400 + 5] == (v4_cell)0x33221100, "the rest of each cell is zero"); #else CHECK(n.mem[400 + 5] == (v4_cell)((v4_ucell)0x41424344u + 5u), "cell 5 as the others"); #endif CHECK(n.mem[399] == 0 && n.mem[400 + V4_BLOCK_CELLS] == 0, "256 cells and no more"); n.mem[BUF] = 0x5A; CHECK(ask(V4_REQ_BLOCK_WRITE, 20, BUF) == V4_BLOCK_OK && ram[((size_t)20 + BLK_FORTH_SYS_RESERVED) * 1024] == 0x5A, "a block below 2048 is the chain's fast RAM"); /* ---- numbers that are no block ---- */ CHECK(ask(V4_REQ_BLOCK_READ, 0, 400) == V4_BLOCK_RANGE, "0 is no block"); CHECK(ask(V4_REQ_BLOCK_READ, -1, 400) == V4_BLOCK_RANGE && ask(V4_REQ_BLOCK_WRITE, -5, BUF) == V4_BLOCK_RANGE, "nor is a number below it"); CHECK(ask(V4_REQ_BLOCK_READ, 2111, 400) == V4_BLOCK_OK && ask(V4_REQ_BLOCK_READ, 2112, 400) == V4_BLOCK_RANGE, "the device's last block is, and the one after it is not"); CHECK(ask(V4_REQ_BLOCK_WRITE, 2112, BUF) == V4_BLOCK_RANGE, "nor can it be written"); #if V4_CELL_BITS > 32 CHECK(ask(V4_REQ_BLOCK_READ, (v4_cell)0x100000014LL, 400) == V4_BLOCK_RANGE, "a number 32 bits do not hold is no block, whatever its low bits are"); #endif /* ---- cells that are not in the node's memory ---- */ n.mem[top - 1] = 123; CHECK(ask(V4_REQ_BLOCK_READ, 2050, top - 255) == V4_BLOCK_REFUSED && n.mem[top - 1] == 123, "256 cells that run past the end of memory are refused, and nothing is read"); CHECK(ask(V4_REQ_BLOCK_READ, 2050, top - 256) == V4_BLOCK_OK, "the last 256 cells are not"); CHECK(ask(V4_REQ_BLOCK_READ, 2050, -1) == V4_BLOCK_REFUSED && ask(V4_REQ_BLOCK_WRITE, 2050, top) == V4_BLOCK_REFUSED, "an address below 0, or at the end, is refused"); CHECK(dev[2 * 1024] == 0x44, "and nothing was written"); /* ---- what v3 wrote ---- */ { uint8_t *b = blk_get_buffer(2070, 1); CHECK(b != 0, "v3 gives a buffer for block 2070"); if (b) { memset(b, 'V', BLK_FORTH_SIZE); CHECK(blk_update(2070) == BLK_OK && blk_flush(2070) == BLK_OK, "and v3 writes it"); } CHECK(ask(V4_REQ_BLOCK_READ, 2070, 400) == V4_BLOCK_OK && n.mem[400] == (v4_cell)0x56565656 && n.mem[400 + 255] == (v4_cell)0x56565656, "what v3's own calls wrote is what the node reads"); } /* ---- what is not a block request ---- */ v4_dstack_push(&n.ds, 11); v4_dstack_push(&n.ds, 22); CHECK(!v4_blocks_serve(&n, 5) && !v4_blocks_serve(&n, 0) && !v4_blocks_serve(&n, -3) && v4_dstack_pop(&n.ds) == 22 && v4_dstack_pop(&n.ds) == 11, "any other request is not served here, and the stack is as it was"); printf(" %d checks, %d failures\n", checks, failures); return failures ? 1 : 0; }