tidied and simplified test package

This commit is contained in:
JetSetIlly 2023-07-06 12:53:40 +01:00
parent 1b021ccf40
commit 732c433cd2
25 changed files with 225 additions and 721 deletions

View file

@ -26,69 +26,69 @@ func TestDecodeULEB128(t *testing.T) {
// tests from page 162 of the "DWARF4 Standard"
v := []uint8{0x7f, 0x00}
r, n := leb128.DecodeULEB128(v)
test.Equate(t, n, 1)
test.Equate(t, r, uint64(127))
test.ExpectEquality(t, n, 1)
test.ExpectEquality(t, r, uint64(127))
v = []uint8{0x80, 0x01, 0x00}
r, n = leb128.DecodeULEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, uint64(128))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, uint64(128))
v = []uint8{0x81, 0x01, 0x00}
r, n = leb128.DecodeULEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, uint64(129))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, uint64(129))
v = []uint8{0x82, 0x01, 0x00}
r, n = leb128.DecodeULEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, uint64(130))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, uint64(130))
v = []uint8{0xb9, 0x64, 0x00}
r, n = leb128.DecodeULEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, uint64(12857))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, uint64(12857))
}
func TestDecodeSLEB128(t *testing.T) {
// tests from page 163 of the "DWARF4 Standard"
v := []uint8{0x02, 0x00}
r, n := leb128.DecodeSLEB128(v)
test.Equate(t, n, 1)
test.Equate(t, r, int64(2))
test.ExpectEquality(t, n, 1)
test.ExpectEquality(t, r, int64(2))
v = []uint8{0x7e, 0x00}
r, n = leb128.DecodeSLEB128(v)
test.Equate(t, n, 1)
test.Equate(t, r, int64(-2))
test.ExpectEquality(t, n, 1)
test.ExpectEquality(t, r, int64(-2))
v = []uint8{0xff, 0x00}
r, n = leb128.DecodeSLEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, int64(127))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, int64(127))
v = []uint8{0x81, 0x7f}
r, n = leb128.DecodeSLEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, int64(-127))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, int64(-127))
v = []uint8{0x80, 0x01}
r, n = leb128.DecodeSLEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, int64(128))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, int64(128))
v = []uint8{0x80, 0x7f}
r, n = leb128.DecodeSLEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, int64(-128))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, int64(-128))
v = []uint8{0x81, 0x01}
r, n = leb128.DecodeSLEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, int64(129))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, int64(129))
v = []uint8{0xff, 0x7e}
r, n = leb128.DecodeSLEB128(v)
test.Equate(t, n, 2)
test.Equate(t, r, int64(-129))
test.ExpectEquality(t, n, 2)
test.ExpectEquality(t, r, int64(-129))
}

View file

@ -60,7 +60,7 @@ func expectEquivalency(t *testing.T, cmds *commandline.Commands) {
template := strings.Split(cmds.String(), "\n")
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
}
@ -73,14 +73,14 @@ func TestParser_optimised(t *testing.T) {
template = []string{"TEST [1 [2] [3] [4] [5]]"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquivalency(t, cmds)
}
template = []string{"TEST (egg|fog|(nug nog)|big) (tug)"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquivalency(t, cmds)
}
}
@ -93,7 +93,7 @@ func TestParser_nestedGroups(t *testing.T) {
template = []string{"TEST (foo|bar (a|b c|d) baz)"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
}
@ -103,11 +103,11 @@ func TestParser_badGroupings(t *testing.T) {
// optional groups must be closed
_, err = commandline.ParseCommandTemplate([]string{"TEST (arg"})
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
// required groups must be closed
_, err = commandline.ParseCommandTemplate([]string{"TEST (arg]"})
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
}
func TestParser_goodGroupings(t *testing.T) {
@ -118,7 +118,7 @@ func TestParser_goodGroupings(t *testing.T) {
template = []string{"TEST (1 [2] [3] [4] [5])"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
}
@ -131,21 +131,21 @@ func TestParser_nestedGroupings(t *testing.T) {
template = []string{"TEST [(foo)|bar]"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST (foo|[bar])"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST (foo|[bar|(baz|qux)]|wibble)"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
}
@ -158,7 +158,7 @@ func TestParser_rootGroupings(t *testing.T) {
template = []string{"TEST (arg)"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
}
@ -170,22 +170,22 @@ func TestParser_placeholders(t *testing.T) {
// placeholder directives must be complete
_, err = commandline.ParseCommandTemplate([]string{"TEST foo %"})
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
// placeholder directives must be recognised
_, err = commandline.ParseCommandTemplate([]string{"TEST foo %q"})
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
// double %% is a valid placeholder directive
template = []string{"TEST foo %%"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
// placeholder directives must be separated from surrounding text
_, err = commandline.ParseCommandTemplate([]string{"TEST foo%%"})
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
}
func TestParser_doubleArgs(t *testing.T) {
@ -196,21 +196,21 @@ func TestParser_doubleArgs(t *testing.T) {
template = []string{"TEST foo bar"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST (foo bar baz)"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST (egg|fog|nug nog|big) (tug)"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
}
@ -223,42 +223,42 @@ func TestParser_repeatGroups(t *testing.T) {
template = []string{"TEST {foo}"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST {foo|bar}"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST {[foo|bar]}"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST {foo|bar|baz}"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST {foo %f}"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
template = []string{"TEST {foo|bar %f}"}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
}
@ -277,16 +277,16 @@ func TestParser_addHelp(t *testing.T) {
}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquality(t, template, cmds)
}
err = cmds.AddHelp("HELP", map[string]string{})
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
// adding a second HELP command is not allowed
err = cmds.AddHelp("HELP", map[string]string{})
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
}
func TestParser_placeholderLabels(t *testing.T) {
@ -299,7 +299,7 @@ func TestParser_placeholderLabels(t *testing.T) {
}
cmds, err = commandline.ParseCommandTemplate(template)
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquivalency(t, cmds)
expectEquality(t, template, cmds)
}
@ -319,7 +319,7 @@ func TestParser_optional(t *testing.T) {
t.Errorf("does not parse: %s", err)
}
if test.ExpectedSuccess(t, err) {
if test.ExpectSuccess(t, err) {
expectEquivalency(t, cmds)
expectEquality(t, template, cmds)
}

View file

@ -27,37 +27,37 @@ func TestTokeniser_spaces(t *testing.T) {
var s string
toks = commandline.TokeniseInput("FOO")
test.Equate(t, toks.Len(), 1)
test.ExpectEquality(t, toks.Len(), 1)
s, _ = toks.Get()
test.Equate(t, s, "FOO")
test.ExpectEquality(t, s, "FOO")
toks = commandline.TokeniseInput("FOO ")
test.Equate(t, toks.Len(), 1)
test.ExpectEquality(t, toks.Len(), 1)
s, _ = toks.Get()
test.Equate(t, s, "FOO")
test.ExpectEquality(t, s, "FOO")
toks = commandline.TokeniseInput("FOO BAR")
test.Equate(t, toks.Len(), 2)
test.ExpectEquality(t, toks.Len(), 2)
s, _ = toks.Get()
test.Equate(t, s, "FOO")
test.ExpectEquality(t, s, "FOO")
s, _ = toks.Get()
test.Equate(t, s, "BAR")
test.ExpectEquality(t, s, "BAR")
toks = commandline.TokeniseInput(" FOO BAR ")
test.Equate(t, toks.Len(), 2)
test.ExpectEquality(t, toks.Len(), 2)
s, _ = toks.Get()
test.Equate(t, s, "FOO")
test.ExpectEquality(t, s, "FOO")
s, _ = toks.Get()
test.Equate(t, s, "BAR")
test.ExpectEquality(t, s, "BAR")
toks = commandline.TokeniseInput(" FOO BAR BAZ")
test.Equate(t, toks.Len(), 3)
test.ExpectEquality(t, toks.Len(), 3)
s, _ = toks.Get()
test.Equate(t, s, "FOO")
test.ExpectEquality(t, s, "FOO")
s, _ = toks.Get()
test.Equate(t, s, "BAR")
test.ExpectEquality(t, s, "BAR")
s, _ = toks.Get()
test.Equate(t, s, "BAZ")
test.ExpectEquality(t, s, "BAZ")
}
func TestTokeniser_quotes(t *testing.T) {
@ -66,40 +66,40 @@ func TestTokeniser_quotes(t *testing.T) {
// last argument is quoted
toks = commandline.TokeniseInput("FOO \"BAR BAZ\" ")
test.Equate(t, toks.Len(), 2)
test.ExpectEquality(t, toks.Len(), 2)
s, _ = toks.Get()
test.Equate(t, s, "FOO")
test.ExpectEquality(t, s, "FOO")
s, _ = toks.Get()
test.Equate(t, s, "BAR BAZ")
test.ExpectEquality(t, s, "BAR BAZ")
// middle argument is quoted
toks = commandline.TokeniseInput("FOO \"BAR BAZ\" QUX")
test.Equate(t, toks.Len(), 3)
test.ExpectEquality(t, toks.Len(), 3)
s, _ = toks.Get()
test.Equate(t, s, "FOO")
test.ExpectEquality(t, s, "FOO")
s, _ = toks.Get()
test.Equate(t, s, "BAR BAZ")
test.ExpectEquality(t, s, "BAR BAZ")
s, _ = toks.Get()
test.Equate(t, s, "QUX")
test.ExpectEquality(t, s, "QUX")
// first argument is quoted
toks = commandline.TokeniseInput("\"FOO BAR\" BAZ QUX")
test.Equate(t, toks.Len(), 3)
test.ExpectEquality(t, toks.Len(), 3)
s, _ = toks.Get()
test.Equate(t, s, "FOO BAR")
test.ExpectEquality(t, s, "FOO BAR")
s, _ = toks.Get()
test.Equate(t, s, "BAZ")
test.ExpectEquality(t, s, "BAZ")
s, _ = toks.Get()
test.Equate(t, s, "QUX")
test.ExpectEquality(t, s, "QUX")
// the only argument is quoted and with leadig and trailing space
toks = commandline.TokeniseInput(" \" FOO BAR \" ")
test.Equate(t, toks.Len(), 1)
test.ExpectEquality(t, toks.Len(), 1)
s, _ = toks.Get()
test.Equate(t, s, " FOO BAR ")
test.ExpectEquality(t, s, " FOO BAR ")
}
func TestTokeniser_singleCharArgs(t *testing.T) {
toks := commandline.TokeniseInput("FOO & BAR")
test.Equate(t, toks.Len(), 3)
test.ExpectEquality(t, toks.Len(), 3)
}

View file

@ -32,7 +32,7 @@ func TestDefaultSymbols(t *testing.T) {
if err != nil {
t.Errorf("unexpected error (%s)", err)
}
tw := &test.CompareWriter{}
tw := &test.Writer{}
sym.ListSymbols(os.Stdout)
sym.ListSymbols(tw)
@ -55,7 +55,7 @@ func TestFlappySymbols(t *testing.T) {
t.Errorf("unexpected error (%s)", err)
}
tw := &test.CompareWriter{}
tw := &test.Writer{}
sym.ListSymbols(os.Stdout)
sym.ListSymbols(tw)

View file

@ -437,7 +437,7 @@ func testBranchingBackwards(t *testing.T, mc *cpu.CPU, mem *testMem) {
origin = 0x20
err := mc.LoadPC(0x20)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
// BPL backwards
_ = mem.putInstructions(origin, 0x10, 0xfd)
@ -447,7 +447,7 @@ func testBranchingBackwards(t *testing.T, mc *cpu.CPU, mem *testMem) {
// BVS backwards
origin = 0x20
err = mc.LoadPC(0x20)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
mc.Status.Overflow = true
_ = mem.putInstructions(origin, 0x70, 0xfd)
step(t, mc) // BVS $FF
@ -462,7 +462,7 @@ func testBranchingPageFaults(t *testing.T, mc *cpu.CPU, mem *testMem) {
// BNE backwards - with PC wrap (causing a page fault)
origin = 0x20
err := mc.LoadPC(0x20)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
mc.Status.Zero = false
_ = mem.putInstructions(origin, 0xd0, 0x80)
step(t, mc) // BNE $F0

View file

@ -32,12 +32,12 @@ func TestDecimalModeCarry(t *testing.T) {
// addition without carry
rcarry, _, _, _ = r8.AddDecimal(1, false)
rtest.EquateRegisters(t, r8, 0x01)
test.Equate(t, rcarry, false)
test.ExpectEquality(t, rcarry, false)
// addition with carry
rcarry, _, _, _ = r8.AddDecimal(1, true)
rtest.EquateRegisters(t, r8, 0x03)
test.Equate(t, rcarry, false)
test.ExpectEquality(t, rcarry, false)
// subtraction with carry (subtract value)
r8.Load(9)
@ -64,7 +64,7 @@ func TestDecimalModeCarry(t *testing.T) {
rtest.EquateRegisters(t, r8, 0x99)
rcarry, _, _, _ = r8.AddDecimal(1, false)
rtest.EquateRegisters(t, r8, 0x00)
test.Equate(t, rcarry, true)
test.ExpectEquality(t, rcarry, true)
// subtraction on hundreds boundary
r8.SubtractDecimal(1, true)
@ -80,9 +80,9 @@ func TestDecimalModeZero(t *testing.T) {
// subtract to zero
r8.Load(0x02)
_, zero, _, _ = r8.SubtractDecimal(1, true)
test.Equate(t, zero, false)
test.ExpectEquality(t, zero, false)
_, zero, _, _ = r8.SubtractDecimal(1, true)
test.Equate(t, zero, true)
test.ExpectEquality(t, zero, true)
}
func TestDecimalModeInvalid(t *testing.T) {
@ -91,6 +91,6 @@ func TestDecimalModeInvalid(t *testing.T) {
r8 := registers.NewRegister(0x99, "test")
rcarry, rzero, _, _ = r8.AddDecimal(1, false)
rtest.EquateRegisters(t, r8, 0x00)
test.Equate(t, rcarry, true)
test.Equate(t, rzero, false)
test.ExpectEquality(t, rcarry, true)
test.ExpectEquality(t, rzero, false)
}

View file

@ -26,7 +26,7 @@ import (
func TestProgramCounter(t *testing.T) {
// initialisation
pc := registers.NewProgramCounter(0)
test.Equate(t, pc.Address(), 0)
test.ExpectEquality(t, pc.Address(), 0)
// loading & addition
pc.Load(127)

View file

@ -28,7 +28,7 @@ func TestRegister(t *testing.T) {
// initialisation
r8 := registers.NewRegister(0, "test")
test.Equate(t, r8.IsZero(), true)
test.ExpectEquality(t, r8.IsZero(), true)
rtest.EquateRegisters(t, r8, 0)
// loading & addition
@ -39,29 +39,29 @@ func TestRegister(t *testing.T) {
// addition boundary
r8.Load(255)
test.Equate(t, r8.IsNegative(), true)
test.ExpectEquality(t, r8.IsNegative(), true)
carry, overflow = r8.Add(1, false)
test.Equate(t, carry, true)
test.Equate(t, overflow, false)
test.Equate(t, r8.IsZero(), true)
test.ExpectEquality(t, carry, true)
test.ExpectEquality(t, overflow, false)
test.ExpectEquality(t, r8.IsZero(), true)
rtest.EquateRegisters(t, r8, 0)
// addition boundary with carry
r8.Load(254)
test.Equate(t, r8.IsNegative(), true)
test.ExpectEquality(t, r8.IsNegative(), true)
carry, overflow = r8.Add(1, true)
test.Equate(t, carry, true)
test.Equate(t, overflow, false)
test.Equate(t, r8.IsZero(), true)
test.ExpectEquality(t, carry, true)
test.ExpectEquality(t, overflow, false)
test.ExpectEquality(t, r8.IsZero(), true)
rtest.EquateRegisters(t, r8, 0)
// addition boundary with carry
r8.Load(255)
test.Equate(t, r8.IsNegative(), true)
test.ExpectEquality(t, r8.IsNegative(), true)
carry, overflow = r8.Add(1, true)
test.Equate(t, carry, true)
test.Equate(t, overflow, false)
test.Equate(t, r8.IsZero(), false)
test.ExpectEquality(t, carry, true)
test.ExpectEquality(t, overflow, false)
test.ExpectEquality(t, r8.IsZero(), false)
rtest.EquateRegisters(t, r8, 1)
// subtraction
@ -100,19 +100,19 @@ func TestRegister(t *testing.T) {
// shifts
carry = r8.ASL()
rtest.EquateRegisters(t, r8, 0xFE)
test.Equate(t, carry, true)
test.ExpectEquality(t, carry, true)
carry = r8.LSR()
rtest.EquateRegisters(t, r8, 0x007F)
test.Equate(t, carry, false)
test.ExpectEquality(t, carry, false)
carry = r8.LSR()
test.Equate(t, carry, true)
test.ExpectEquality(t, carry, true)
// rotation
r8.Load(0xff)
carry = r8.ROL(false)
rtest.EquateRegisters(t, r8, 0xfe)
test.Equate(t, carry, true)
test.ExpectEquality(t, carry, true)
carry = r8.ROR(true)
rtest.EquateRegisters(t, r8, 0xff)
test.Equate(t, carry, false)
test.ExpectEquality(t, carry, false)
}

View file

@ -35,25 +35,25 @@ func TestEqual(t *testing.T) {
}
// clock fields are different (other fields equal)
test.ExpectedFailure(t, coords.Equal(A, B))
test.ExpectFailure(t, coords.Equal(A, B))
// all fields are equal
B.Clock = 0
test.ExpectedSuccess(t, coords.Equal(A, B))
test.ExpectSuccess(t, coords.Equal(A, B))
// scanline fields are different (other fields equal)
B.Scanline = 1
test.ExpectedFailure(t, coords.Equal(A, B))
test.ExpectFailure(t, coords.Equal(A, B))
// all fields are equal
A.Scanline = 1
test.ExpectedSuccess(t, coords.Equal(A, B))
test.ExpectSuccess(t, coords.Equal(A, B))
// frame fields are different
A.Frame = 1
test.ExpectedFailure(t, coords.Equal(A, B))
test.ExpectFailure(t, coords.Equal(A, B))
// frame fields are different but one is undefined
B.Frame = coords.FrameIsUndefined
test.ExpectedSuccess(t, coords.Equal(A, B))
test.ExpectSuccess(t, coords.Equal(A, B))
}

View file

@ -24,14 +24,14 @@ import (
)
func TestLogger(t *testing.T) {
tw := &test.CompareWriter{}
tw := &test.Writer{}
logger.Write(tw)
test.Equate(t, tw.Compare(""), true)
test.ExpectEquality(t, tw.Compare(""), true)
logger.Log("test", "this is a test")
logger.Write(tw)
test.Equate(t, tw.Compare("test: this is a test\n"), true)
test.ExpectEquality(t, tw.Compare("test: this is a test\n"), true)
// clear the test.Writer buffer before continuing, makes comparisons easier
// to manage
@ -39,26 +39,26 @@ func TestLogger(t *testing.T) {
logger.Log("test2", "this is another test")
logger.Write(tw)
test.Equate(t, tw.Compare("test: this is a test\ntest2: this is another test\n"), true)
test.ExpectEquality(t, tw.Compare("test: this is a test\ntest2: this is another test\n"), true)
// asking for too many entries in a Tail() should be okay
tw.Clear()
logger.Tail(tw, 100)
fmt.Println(tw)
test.Equate(t, tw.Compare("test: this is a test\ntest2: this is another test\n"), true)
test.ExpectEquality(t, tw.Compare("test: this is a test\ntest2: this is another test\n"), true)
// asking for exactly the correct number of entries is okay
tw.Clear()
logger.Tail(tw, 2)
test.Equate(t, tw.Compare("test: this is a test\ntest2: this is another test\n"), true)
test.ExpectEquality(t, tw.Compare("test: this is a test\ntest2: this is another test\n"), true)
// asking for fewer entries is okay too
tw.Clear()
logger.Tail(tw, 1)
test.Equate(t, tw.Compare("test2: this is another test\n"), true)
test.ExpectEquality(t, tw.Compare("test2: this is another test\n"), true)
// and no entries
tw.Clear()
logger.Tail(tw, 0)
test.Equate(t, tw.Compare(""), true)
test.ExpectEquality(t, tw.Compare(""), true)
}

View file

@ -75,7 +75,7 @@ func TestNoModes(t *testing.T) {
}
func TestNoHelpAvailable(t *testing.T) {
tw := &test.CompareWriter{}
tw := &test.Writer{}
md := modalflag.Modes{Output: tw}
md.NewArgs([]string{"-help"})
@ -91,7 +91,7 @@ func TestNoHelpAvailable(t *testing.T) {
}
func TestHelpFlags(t *testing.T) {
tw := &test.CompareWriter{}
tw := &test.Writer{}
md := modalflag.Modes{Output: tw}
md.NewArgs([]string{"-help"})
@ -112,7 +112,7 @@ func TestHelpFlags(t *testing.T) {
}
func TestHelpModes(t *testing.T) {
tw := &test.CompareWriter{}
tw := &test.Writer{}
md := modalflag.Modes{Output: tw}
md.NewArgs([]string{"-help"})
@ -133,7 +133,7 @@ func TestHelpModes(t *testing.T) {
}
func TestHelpFlagsAndModes(t *testing.T) {
tw := &test.CompareWriter{}
tw := &test.Writer{}
md := modalflag.Modes{Output: tw}
md.NewArgs([]string{"-help"})

View file

@ -24,47 +24,47 @@ import (
func TestCommandLineStackValues(t *testing.T) {
// empty on start
test.Equate(t, prefs.PopCommandLineStack(), "")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "")
// single value
prefs.PushCommandLineStack("foo::bar")
test.Equate(t, prefs.PopCommandLineStack(), "foo::bar")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "foo::bar")
// single value but with additional space
prefs.PushCommandLineStack(" foo:: bar ")
test.Equate(t, prefs.PopCommandLineStack(), "foo::bar")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "foo::bar")
// more than one key/value in the prefs string. remaining string will
// will be sorted
prefs.PushCommandLineStack("foo::bar; baz::qux")
test.Equate(t, prefs.PopCommandLineStack(), "baz::qux; foo::bar")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "baz::qux; foo::bar")
// check invalid prefs string
prefs.PushCommandLineStack("foo_bar")
test.Equate(t, prefs.PopCommandLineStack(), "")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "")
// check (partically) invalid prefs string
prefs.PushCommandLineStack("foo_bar;baz::qux")
test.Equate(t, prefs.PopCommandLineStack(), "baz::qux")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "baz::qux")
// get prefs value that doesn't exist after pushing a parially invalid prefs string
prefs.PushCommandLineStack("foo::bar;baz_qux")
ok, _ := prefs.GetCommandLinePref("baz")
test.ExpectedFailure(t, ok)
test.Equate(t, prefs.PopCommandLineStack(), "foo::bar")
test.ExpectFailure(t, ok)
test.ExpectEquality(t, prefs.PopCommandLineStack(), "foo::bar")
}
func TestCommandLineStack(t *testing.T) {
// empty on start
test.Equate(t, prefs.PopCommandLineStack(), "")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "")
// single value
prefs.PushCommandLineStack("foo::bar")
// add another command line group
prefs.PushCommandLineStack("baz::qux")
test.Equate(t, prefs.PopCommandLineStack(), "baz::qux")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "baz::qux")
// first group still exists
test.Equate(t, prefs.PopCommandLineStack(), "foo::bar")
test.ExpectEquality(t, prefs.PopCommandLineStack(), "foo::bar")
}

View file

@ -102,18 +102,18 @@ func TestBool(t *testing.T) {
var w prefs.Bool
var x prefs.Bool
err = dsk.Add("test", &v)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Add("testB", &w)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Add("testC", &x)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = v.Set(true)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = w.Set("foo")
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = x.Set("true")
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Save()
if err != nil {
@ -136,10 +136,10 @@ func TestString(t *testing.T) {
var v prefs.String
err = dsk.Add("foo", &v)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = v.Set("bar")
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Save()
if err != nil {
@ -161,19 +161,19 @@ func TestFloat(t *testing.T) {
var v prefs.Float
err = dsk.Add("foo", &v)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = v.Set("bar")
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
err = v.Set(1.0)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = v.Set(2.0)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = v.Set(-3.0)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Save()
if err != nil {
@ -194,16 +194,16 @@ func TestInt(t *testing.T) {
var v prefs.Int
var w prefs.Int
err = dsk.Add("number", &v)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Add("numberB", &w)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = v.Set(10)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
// test string conversion to int
err = w.Set("99")
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Save()
if err != nil {
@ -215,10 +215,10 @@ func TestInt(t *testing.T) {
// while we have a prefs.Int instance set up we'll test some
// failure conditions
err = v.Set("---")
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
err = v.Set(1.0)
test.ExpectedFailure(t, err)
test.ExpectFailure(t, err)
}
func TestGeneric(t *testing.T) {
@ -247,7 +247,7 @@ func TestGeneric(t *testing.T) {
)
err = dsk.Add("generic", v)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
// change values
w = 1
@ -272,8 +272,8 @@ func TestGeneric(t *testing.T) {
}
// check that the values have been restoed
test.Equate(t, w, 1)
test.Equate(t, h, 2)
test.ExpectEquality(t, w, 1)
test.ExpectEquality(t, h, 2)
}
// write bool and then a string from a different prefs.Disk instance. tests
@ -290,10 +290,10 @@ func TestBoolAndString(t *testing.T) {
var v prefs.Bool
err = dsk.Add("test", &v)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = v.Set(true)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Save()
if err != nil {
@ -310,10 +310,10 @@ func TestBoolAndString(t *testing.T) {
var s prefs.String
err = dsk.Add("foo", &s)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = s.Set("bar")
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = dsk.Save()
if err != nil {
@ -337,24 +337,24 @@ func TestMaxStringLength(t *testing.T) {
var s prefs.String
err = dsk.Add("test", &s)
test.ExpectedSuccess(t, err)
test.ExpectSuccess(t, err)
err = s.Set("123456789")
test.ExpectedSuccess(t, err)
test.Equate(t, s.String(), "123456789")
test.ExpectSuccess(t, err)
test.ExpectEquality(t, s.String(), "123456789")
// setting maximum length will crop the existing string
s.SetMaxLen(5)
test.Equate(t, s.String(), "12345")
test.ExpectEquality(t, s.String(), "12345")
// unsetting a maximum length (using value zero) will not result in
// cropped string infomration reappearing
s.SetMaxLen(0)
test.Equate(t, s.String(), "12345")
test.ExpectEquality(t, s.String(), "12345")
// set string after setting a maximum length will result in the set string
// being cropped
s.SetMaxLen(3)
err = s.Set("abcdefghi")
test.ExpectedSuccess(t, err)
test.Equate(t, s.String(), "abc")
test.ExpectSuccess(t, err)
test.ExpectEquality(t, s.String(), "abc")
}

View file

@ -39,6 +39,6 @@ func TestRandom(t *testing.T) {
b := random.NewRandom(&mockTV{})
for i := 1; i < 256; i++ {
test.Equate(t, a.Rewindable(i), b.Rewindable(i))
test.ExpectEquality(t, a.Rewindable(i), b.Rewindable(i))
}
}

View file

@ -24,22 +24,22 @@ import (
func TestJoinPath(t *testing.T) {
pth, err := resources.JoinPath("foo/bar", "baz")
test.Equate(t, err, nil)
test.Equate(t, pth, ".gopher2600/foo/bar/baz")
test.ExpectEquality(t, err, nil)
test.ExpectEquality(t, pth, ".gopher2600/foo/bar/baz")
pth, err = resources.JoinPath("foo", "bar", "baz")
test.Equate(t, err, nil)
test.Equate(t, pth, ".gopher2600/foo/bar/baz")
test.ExpectEquality(t, err, nil)
test.ExpectEquality(t, pth, ".gopher2600/foo/bar/baz")
pth, err = resources.JoinPath("foo/bar", "")
test.Equate(t, err, nil)
test.Equate(t, pth, ".gopher2600/foo/bar")
test.ExpectEquality(t, err, nil)
test.ExpectEquality(t, pth, ".gopher2600/foo/bar")
pth, err = resources.JoinPath("", "baz")
test.Equate(t, err, nil)
test.Equate(t, pth, ".gopher2600/baz")
test.ExpectEquality(t, err, nil)
test.ExpectEquality(t, pth, ".gopher2600/baz")
pth, err = resources.JoinPath("", "")
test.Equate(t, err, nil)
test.Equate(t, pth, ".gopher2600")
test.ExpectEquality(t, err, nil)
test.ExpectEquality(t, pth, ".gopher2600")
}

View file

@ -1,56 +0,0 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
//go:build assertions
// +build assertions
package test
import (
"bytes"
"fmt"
"runtime"
"strconv"
)
func init() {
fmt.Println("running with active assertions")
}
// AssertMainThread causes a panic if calling function is not the main thread.
func AssertMainThread() {
threadInfoBuffer := make([]byte, 64)
threadInfoBuffer = threadInfoBuffer[:runtime.Stack(threadInfoBuffer, false)]
threadInfoBuffer = bytes.TrimPrefix(threadInfoBuffer, []byte("goroutine "))
threadInfoBuffer = threadInfoBuffer[:bytes.IndexByte(threadInfoBuffer, ' ')]
n, _ := strconv.ParseUint(string(threadInfoBuffer), 10, 64)
if n != 1 {
panic("not called from the main thread")
}
}
// AssertNonMainThread causes a panic if calling function is the main thread.
func AssertNonMainThread() {
threadInfoBuffer := make([]byte, 64)
threadInfoBuffer = threadInfoBuffer[:runtime.Stack(threadInfoBuffer, false)]
threadInfoBuffer = bytes.TrimPrefix(threadInfoBuffer, []byte("goroutine "))
threadInfoBuffer = threadInfoBuffer[:bytes.IndexByte(threadInfoBuffer, ' ')]
n, _ := strconv.ParseUint(string(threadInfoBuffer), 10, 64)
if n == 1 {
panic("not called from the main thread")
}
}

View file

@ -1,27 +0,0 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
//go:build !assertions
// +build !assertions
package test
// AssertMainThread is a stub for when "assertions" build tag is missing.
func AssertMainThread() {
}
// AssertNonMainThread is a stub for when "assertions" build tag is missing.
func AssertNonMainThread() {
}

View file

@ -1,68 +0,0 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package test
import (
"fmt"
)
// CapperWriter is an implementation of io.Writer that stops buffering once a
// predefined size is reached.
type CappedWriter struct {
buffer []byte
size int
}
// NewCappedWriter is the preferred method of initialisation for the
// CappedWriter type.
func NewCappedWriter(size int) (*CappedWriter, error) {
if size <= 0 {
return nil, fmt.Errorf("invalid size for CappedWriter (%d)", size)
}
return &CappedWriter{
size: size,
buffer: make([]byte, 0, size),
}, nil
}
func (r *CappedWriter) String() string {
return string(r.buffer)
}
// Reset empties the ring writer's buffer
func (r *CappedWriter) Reset() {
r.buffer = r.buffer[:0]
}
// Write implements io.Writer
func (r *CappedWriter) Write(p []byte) (n int, err error) {
remaining := r.size - len(r.buffer)
// no space remaining
if remaining == 0 {
return 0, nil
}
// plenty of space remaining
if len(p) < remaining {
r.buffer = append(r.buffer, p...)
return len(p), nil
}
// limit how much we append
r.buffer = append(r.buffer, p[:remaining]...)
return remaining, nil
}

View file

@ -1,62 +0,0 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package test_test
import (
"testing"
"github.com/jetsetilly/gopher2600/test"
)
func TestCappedWriter(t *testing.T) {
c, err := test.NewCappedWriter(10)
test.Equate(t, err, nil)
// testing that the ring writer starts off with the empty string
test.Equate(t, c.String(), "")
// add one character
c.Write([]byte("a"))
test.Equate(t, c.String(), "a")
// add another three characters
c.Write([]byte("bcd"))
test.Equate(t, c.String(), "abcd")
// add another six characters, taken us to the limit of 10
c.Write([]byte("efghij"))
test.Equate(t, c.String(), "abcdefghij")
// add another three, which should just be ignoed
c.Write([]byte("klm"))
test.Equate(t, c.String(), "abcdefghij")
// reset and test for empty string
c.Reset()
test.Equate(t, c.String(), "")
// add entire limit in one go
c.Write([]byte("abcdefghij"))
test.Equate(t, c.String(), "abcdefghij")
// reset again
c.Reset()
test.Equate(t, c.String(), "")
// add entire limit and more in one go
c.Write([]byte("abcdefghijklm"))
test.Equate(t, c.String(), "abcdefghij")
}

View file

@ -16,37 +16,14 @@
// Package test contains helper functions to remove common boilerplate to make
// testing easier.
//
// The ExpectedFailure and ExpectedSuccess functions test for failure and
// success under generic conditions. The documentation for those functions
// describe the currently supported types.
// The ExpectEquality() is the most basic and probably the most useful function.
// It compares like-typed variables for equality and returns true if they match.
//
// It is worth describing how the "Expected" functions handle the nil type
// because it is not obvious. The nil type is considered a success and
// consequently will cause ExpectedFailure to fail and ExpectedSuccess to
// succeed. This may not be how we want to interpret nil in all situations but
// because of how errors usually works (nil to indicate no error) we *need* to
// interpret nil in this way. If the nil was a value of a nil type we wouldn't
// have this problem incidentally, but that isn't how Go is designed (with good
// reason).
// The ExpectFailure() and ExpectSuccess() functions test for failure and
// success. These two functions work with bool or error and special handling for
// nil.
//
// The Writer type meanwhile, implements the io.Writer interface and should be
// used to capture output. The Writer.Compare() function can then be used to
// test for equality.
//
// The Equate() function compares like-typed variables for equality. Some
// types (eg. uint16) can be compared against int for convenience. See Equate()
// documentation for discussion why.
//
// The two "assert thread" functions, AssertMainThread() and
// AssertNonMainThread() will panic if they are not called from, respectively,
// the main thread or from a non-main thread. These functions do nothing unless
// the "assertions" build tag is specified at compile time.
// Package test bundles a bunch of useful functions useful for testing
// purposes, particular useful in conjunction with the standard go test harness
//
// The AssertMainThread() and AssertNonMainThread() functions require a bit of
// explanation. When compiled with the "assertions" tag these functions will
// panic if the calling function is in the wrong thread. Otherwise they are
// stubbed.
package test

View file

@ -1,111 +0,0 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package test
import (
"testing"
)
// Equate is used to test equality between one value and another. Generally,
// both values must be of the same type but if a is of type uint16, b can be
// uint16 or int. The reason for this is that a literal number value is of type
// int. It is very convenient to write something like this, without having to
// cast the expected number value:
//
// var r uint16
// r = someFunction()
// test.Equate(t, r, 10)
//
// This is by no means a comprehensive comparison function. With a bit more
// work with the reflect package we could generalise the testing a lot more. At
// is is however, it's good enough.
func Equate(t *testing.T, value, expectedValue interface{}) {
t.Helper()
switch v := value.(type) {
default:
t.Fatalf("unhandled type for Equate() function (%T))", v)
case nil:
if expectedValue != nil {
t.Errorf("equation of type %T failed (%d - wanted nil)", v, v)
}
case int64:
switch ev := expectedValue.(type) {
case int64:
if v != ev {
t.Errorf("equation of type %T failed (%d - wanted %d)", v, v, expectedValue.(int64))
}
default:
t.Fatalf("values for Equate() are not the same type (%T and %T)", v, expectedValue)
}
case uint64:
switch ev := expectedValue.(type) {
case uint64:
if v != ev {
t.Errorf("equation of type %T failed (%d - wanted %d)", v, v, expectedValue.(uint64))
}
default:
t.Fatalf("values for Equate() are not the same type (%T and %T)", v, expectedValue)
}
case int:
switch ev := expectedValue.(type) {
case int:
if v != ev {
t.Errorf("equation of type %T failed (%d - wanted %d)", v, v, expectedValue.(int))
}
default:
t.Fatalf("values for Equate() are not the same type (%T and %T)", v, expectedValue)
}
case uint16:
switch ev := expectedValue.(type) {
case int:
if v != uint16(ev) {
t.Errorf("equation of type %T failed (%d - wanted %d)", v, v, ev)
}
case uint16:
if v != ev {
t.Errorf("equation of type %T failed (%d - wanted %d)", v, v, ev)
}
default:
t.Fatalf("values for Equate() are not the same compatible (%T and %T)", v, ev)
}
case string:
switch ev := expectedValue.(type) {
case string:
if v != ev {
t.Errorf("equation of type %T failed (%s - wanted %s)", v, v, expectedValue.(string))
}
default:
t.Fatalf("values for Equate() are not the same type (%T and %T)", v, expectedValue)
}
case bool:
switch ev := expectedValue.(type) {
case bool:
if v != ev {
t.Errorf("equation of type %T failed (%v - wanted %v)", v, v, expectedValue.(bool))
}
default:
t.Fatalf("values for Equate() are not the same type (%T and %T)", v, expectedValue)
}
}
}

View file

@ -17,61 +17,69 @@ package test
import "testing"
// ExpectedFailure tests argument v for a failure condition suitable for it's
// type. Currentlly support types:
// ExpectEquality_ is used to test equality between one value and another
func ExpectEquality[T comparable](t *testing.T, value T, expectedValue T) {
t.Helper()
if value != expectedValue {
t.Errorf("equality test of type %T failed: %v does not equal %v)", value, value, expectedValue)
}
}
// ExpectFailure tests argument v for a failure condition suitable for it's
// type. Types bool and error are treated thus:
//
// bool -> bool == false
// error -> error != nil
// bool == false
// error != nil
//
// If type is nil then the test will fail.
func ExpectedFailure(t *testing.T, v interface{}) bool {
// If type is nil then the test will fail
func ExpectFailure(t *testing.T, v interface{}) bool {
t.Helper()
switch v := v.(type) {
case bool:
if v {
t.Errorf("expected failure (bool)")
t.Errorf("failure test of type %T failed: %T does not equal false", v, v)
return false
}
case error:
if v == nil {
t.Errorf("expected failure (error)")
t.Errorf("failure test of type %T failed: %T equals nil", v, v)
return false
}
case nil:
t.Errorf("expected failure (nil)")
t.Errorf("failure test of type %T failed: %T is not expected", v, v)
return false
default:
t.Fatalf("unsupported type (%T) for expectation testing", v)
t.Fatalf("unsupported type %T for ExpectFailure()", v)
return false
}
return true
}
// ExpectedSuccess tests argument v for a success condition suitable for it's
// type. Currentlly support types:
// ExpectSuccess tests argument v for a success condition suitable for it's
// type. Types bool and error are treated thus:
//
// bool -> bool == true
// error -> error == nil
// bool == true
// error == nil
//
// If type is nil then the test will succeed.
func ExpectedSuccess(t *testing.T, v interface{}) bool {
// If type is nil then the test will succeed
func ExpectSuccess(t *testing.T, v interface{}) bool {
t.Helper()
switch v := v.(type) {
case bool:
if !v {
t.Errorf("expected success (bool)")
t.Errorf("success test of type %T failed: %T does not equal true", v, v)
return false
}
case error:
if v != nil {
t.Errorf("expected success (error: %v)", v)
t.Errorf("success test of type %T failed: %T does not equal nil", v, v)
return false
}
@ -79,7 +87,7 @@ func ExpectedSuccess(t *testing.T, v interface{}) bool {
return true
default:
t.Fatalf("unsupported type (%T) for expectation testing", v)
t.Fatalf("unsupported type (%T) for ExpectSuccess()", v)
return false
}

View file

@ -1,90 +0,0 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package test
import (
"fmt"
"strings"
)
// RingWriter is an implementation of io.Writer that will keep the buffer to a
// predefined size, keeping the most recent writes and dropping the earlier
// writes as appropriate.
type RingWriter struct {
buffer []byte
size int
cursor int
wrapped bool
}
// NewRingWriter is the preferred method of initialisation for the CappedWriter
// type.
func NewRingWriter(size int) (*RingWriter, error) {
if size <= 0 {
return nil, fmt.Errorf("invalid size for RingWriter (%d)", size)
}
return &RingWriter{
size: size,
buffer: make([]byte, size),
}, nil
}
func (r *RingWriter) String() string {
var s strings.Builder
if r.wrapped {
s.WriteString(string(r.buffer[r.cursor:]))
s.WriteString(string(r.buffer[:r.cursor]))
} else {
s.WriteString(string(r.buffer[:r.cursor]))
}
return s.String()
}
// Reset empties the ring writer's buffer
func (r *RingWriter) Reset() {
r.cursor = 0
r.wrapped = false
}
// Write implements io.Writer
func (r *RingWriter) Write(p []byte) (n int, err error) {
l := len(p)
// new text is larger than ring so simply reset the ring and continue as
// normal
if l > r.size {
r.cursor = 0
r.wrapped = false
}
// copy p to buffer, accounting for any wrapping as required
l = r.size - r.cursor
copy(r.buffer[r.cursor:], p)
if len(p) >= l {
r.wrapped = true
copy(r.buffer, p[l:])
}
// adjust cursor
r.cursor = ((r.cursor + len(p)) % r.size)
if len(p) > r.size {
return r.size, nil
}
return len(p), nil
}

View file

@ -1,67 +0,0 @@
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package test_test
import (
"testing"
"github.com/jetsetilly/gopher2600/test"
)
func TestRingWriter(t *testing.T) {
r, err := test.NewRingWriter(10)
test.Equate(t, err, nil)
// testing that the ring writer starts off with the empty string
test.Equate(t, r.String(), "")
// writing a short string
r.Write([]byte("abcde"))
test.Equate(t, r.String(), "abcde")
// writing another short string
r.Write([]byte("fgh"))
test.Equate(t, r.String(), "abcdefgh")
// writing another short string that takes the total written the same size
// as the ring writer's buffer
r.Write([]byte("ij"))
test.Equate(t, r.String(), "abcdefghij")
// writing another short string that takes the written string beyond the
// size of the ring writer's buffer
r.Write([]byte("kl"))
test.Equate(t, r.String(), "cdefghijkl")
r.Write([]byte("mn"))
test.Equate(t, r.String(), "efghijklmn")
// writing a string the same length as the ring writer's buffer. when there
// is already content in the ring writer
r.Write([]byte("1234567890"))
test.Equate(t, r.String(), "1234567890")
// writing a string that is longer than the ring writer's buffer. when
// there is already content in the ring writer
r.Write([]byte("1234567890ABC"))
test.Equate(t, r.String(), "4567890ABC")
// reseting the buffer and then writing a string that is longer than the
// ring writer's buffer
r.Reset()
test.Equate(t, r.String(), "")
r.Write([]byte("1234567890ABC"))
test.Equate(t, r.String(), "4567890ABC")
}

View file

@ -15,28 +15,28 @@
package test
// CompareWriter is an implementation of the io.CompareWriter interface. It should be used to
// Writer is an implementation of the io.Writer interface. It should be used to
// capture output and to compare with predefined strings.
type CompareWriter struct {
type Writer struct {
buffer []byte
}
func (tw *CompareWriter) Write(p []byte) (n int, err error) {
func (tw *Writer) Write(p []byte) (n int, err error) {
tw.buffer = append(tw.buffer, p...)
return len(p), nil
}
// clear string empties the buffer.
func (tw *CompareWriter) Clear() {
func (tw *Writer) Clear() {
tw.buffer = tw.buffer[:0]
}
// Compare buffered output with predefined/example string.
func (tw *CompareWriter) Compare(s string) bool {
func (tw *Writer) Compare(s string) bool {
return s == string(tw.buffer)
}
// implements Stringer interface.
func (tw *CompareWriter) String() string {
func (tw *Writer) String() string {
return string(tw.buffer)
}