import { describe, it, expect } from 'vitest';
import { shr } from './shr.js';
describe('SHR (0x1c)', () => {
it('shifts right by 8 bits', () => {
const frame = createFrame({ stack: [8n, 0xFF00n] });
expect(shr(frame)).toBeNull();
expect(frame.stack[0]).toBe(0xFFn);
});
it('divides by power of 2', () => {
const frame = createFrame({ stack: [3n, 40n] });
expect(shr(frame)).toBeNull();
expect(frame.stack[0]).toBe(5n); // 40 / 2^3
});
it('handles zero shift (identity)', () => {
const value = 0x123456n;
const frame = createFrame({ stack: [0n, value] });
expect(shr(frame)).toBeNull();
expect(frame.stack[0]).toBe(value);
});
it('returns 0 for shift >= 256', () => {
const frame = createFrame({ stack: [256n, 0xFFFFFFFFn] });
expect(shr(frame)).toBeNull();
expect(frame.stack[0]).toBe(0n);
});
it('extracts MSB', () => {
const value = 1n << 255n;
const frame = createFrame({ stack: [255n, value] });
expect(shr(frame)).toBeNull();
expect(frame.stack[0]).toBe(1n);
});
it('zero-fills on negative values (logical shift)', () => {
const value = 1n << 255n; // MSB set (negative if signed)
const frame = createFrame({ stack: [1n, value] });
expect(shr(frame)).toBeNull();
// Logical shift: zero-filled
expect(frame.stack[0]).toBe(1n << 254n);
});
it('truncates low bits', () => {
const value = 0xFFFFn;
const frame = createFrame({ stack: [4n, value] });
expect(shr(frame)).toBeNull();
expect(frame.stack[0]).toBe(0xFFFn);
});
it('extracts high bits', () => {
const value = (0x123456n << 128n) | 0xABCDEFn;
const frame = createFrame({ stack: [128n, value] });
expect(shr(frame)).toBeNull();
expect(frame.stack[0]).toBe(0x123456n);
});
it('returns InvalidOpcode before Constantinople', () => {
const frame = createFrame({
stack: [8n, 0xFF00n],
hardfork: 'byzantium'
});
expect(shr(frame)).toEqual({ type: 'InvalidOpcode' });
});
it('returns StackUnderflow with insufficient stack', () => {
const frame = createFrame({ stack: [8n] });
expect(shr(frame)).toEqual({ type: 'StackUnderflow' });
});
it('returns OutOfGas when insufficient gas', () => {
const frame = createFrame({ stack: [8n, 0xFF00n], gasRemaining: 2n });
expect(shr(frame)).toEqual({ type: 'OutOfGas' });
});
});