2020-02-23 15:54:16 +01:00
|
|
|
' Gambas class file
|
|
|
|
|
|
|
|
''' Assertions which print TAP.
|
|
|
|
|
|
|
|
Export
|
|
|
|
Create Static
|
|
|
|
|
|
|
|
Public Struct Subtest
|
|
|
|
Printer As TapPrinter
|
|
|
|
Description As String
|
|
|
|
Indent As Integer
|
|
|
|
Success As Boolean
|
|
|
|
' Directive to apply to the next "ok" line
|
|
|
|
Directive As Integer
|
|
|
|
Comment As String
|
|
|
|
End Struct
|
|
|
|
|
2020-02-24 14:11:10 +01:00
|
|
|
Property Output As Stream
|
2020-02-24 17:52:35 +01:00
|
|
|
Property Read Finished As Boolean
|
2020-02-24 14:11:10 +01:00
|
|
|
|
2020-02-24 14:55:00 +01:00
|
|
|
Private $aActiveTests As Subtest[]
|
2020-02-23 15:54:16 +01:00
|
|
|
Private $hCurrent As New Subtest
|
2020-02-24 14:55:00 +01:00
|
|
|
Private $hOutput As Stream
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Public Sub _new()
|
|
|
|
|
2020-02-24 14:55:00 +01:00
|
|
|
Reset()
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Reset()
|
|
|
|
|
|
|
|
$aActiveTests = New Subtest[]
|
|
|
|
$hOutput = File.Out
|
|
|
|
With $hCurrent = New Subtest
|
2020-02-23 15:54:16 +01:00
|
|
|
.Printer = New TapPrinter As "Printer"
|
|
|
|
.Indent = 0
|
|
|
|
.Success = True
|
|
|
|
.Directive = Tap.NONE
|
|
|
|
End With
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Setup(Optional Tests As Integer, Optional Comment As String, Optional {Output} As Stream)
|
|
|
|
|
2020-02-24 14:11:10 +01:00
|
|
|
If IsMissing({Output}) Then {Output} = $hOutput
|
2020-02-23 15:54:16 +01:00
|
|
|
$hCurrent.Printer.Output = {Output}
|
|
|
|
Plan(Tests, Comment)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Subtest(Description As String, Optional Tests As Integer)
|
|
|
|
|
|
|
|
Dim iIndent As Integer = $hCurrent.Indent
|
2020-02-24 14:11:10 +01:00
|
|
|
Dim hOutput As Stream = $hCurrent.Printer.Output
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
$aActiveTests.Push($hCurrent)
|
|
|
|
With $hCurrent = New Subtest
|
|
|
|
.Printer = New TapPrinter As "Printer"
|
2020-02-24 14:11:10 +01:00
|
|
|
.Printer.Output = hOutput
|
2020-02-23 15:54:16 +01:00
|
|
|
.Description = Description
|
|
|
|
.Indent = iIndent + 1
|
|
|
|
.Success = True
|
|
|
|
.Directive = Tap.NONE
|
|
|
|
End With
|
|
|
|
If Tests Then Plan(Tests)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Finish()
|
|
|
|
|
|
|
|
Dim hFinished As Subtest
|
|
|
|
|
2020-02-24 17:20:49 +01:00
|
|
|
With $hCurrent
|
|
|
|
.Printer.Finish()
|
2020-02-24 17:52:35 +01:00
|
|
|
.Success = .Success And (.Printer.SkippedAll Or (.Printer.Planned > 0 And .Printer.Count = .Printer.Planned))
|
2020-02-24 17:20:49 +01:00
|
|
|
End With
|
2020-02-23 15:54:16 +01:00
|
|
|
hFinished = $hCurrent
|
2020-02-24 17:20:49 +01:00
|
|
|
|
2020-02-23 15:54:16 +01:00
|
|
|
Try $hCurrent = $aActiveTests.Pop()
|
|
|
|
If Not Error Then
|
|
|
|
$hCurrent.Printer.Test(hFinished.Success,, hFinished.Description)
|
|
|
|
Endif
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Printer_Filter()
|
|
|
|
|
|
|
|
Last.Line = String$($hCurrent.Indent, "\t") & Last.Line
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Plan(Tests As Integer, Optional Comment As String)
|
|
|
|
|
|
|
|
$hCurrent.Printer.Plan(Tests, Comment)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-24 17:52:35 +01:00
|
|
|
Public Sub SkipAll(Optional Comment As String)
|
|
|
|
|
|
|
|
$hCurrent.Printer.SkipAll(Comment)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 15:54:16 +01:00
|
|
|
Public Sub Ok(Result As Boolean, Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
With $hCurrent
|
|
|
|
If .Directive <> Tap.NONE Then
|
|
|
|
.Printer.Test(Result,, Description, .Directive, .Comment)
|
|
|
|
Else
|
|
|
|
.Printer.Test(Result,, Description)
|
|
|
|
.Success = .Success And Result
|
|
|
|
Endif
|
|
|
|
.Directive = Tap.NONE
|
|
|
|
.Comment = Null
|
|
|
|
End With
|
|
|
|
Return Result
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Todo(Optional Comment As String)
|
|
|
|
|
|
|
|
$hCurrent.Directive = Tap.TODO
|
|
|
|
$hCurrent.Comment = Comment
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Skip(Optional Comment As String)
|
|
|
|
|
|
|
|
$hCurrent.Directive = Tap.SKIP
|
|
|
|
$hCurrent.Comment = Comment
|
2020-02-23 22:46:16 +01:00
|
|
|
Pass()
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub BailOut(Optional Comment As String)
|
|
|
|
|
|
|
|
$hCurrent.Printer.BailOut(Comment)
|
2020-02-24 17:20:49 +01:00
|
|
|
$hCurrent.Success = False
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Diagnostic(Comment As String)
|
|
|
|
|
|
|
|
$hCurrent.Printer.Diagnostic(Comment)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Note(Comment As String)
|
|
|
|
|
|
|
|
Diagnostic(Comment)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 15:54:16 +01:00
|
|
|
Public Sub Print({Line} As String)
|
|
|
|
|
|
|
|
$hCurrent.Printer.Print({Line})
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-24 14:11:10 +01:00
|
|
|
Private Function Output_Read() As Stream
|
|
|
|
|
|
|
|
Return $hOutput
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Private Sub Output_Write(Value As Stream)
|
|
|
|
|
|
|
|
$hOutput = Value
|
|
|
|
$hCurrent.Printer.Output = Value
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-24 17:52:35 +01:00
|
|
|
Private Function Finished_Read() As Boolean
|
|
|
|
|
|
|
|
Return $hCurrent.Printer.Finished
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 15:54:16 +01:00
|
|
|
' -------------------- High-level test functions --------------------
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Pass(Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Return Ok(True, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Fail(Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Return Ok(False, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 15:54:16 +01:00
|
|
|
Public Sub NotOk(Result As Boolean, Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Return Ok(Not Result, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Equals(Got As Variant, Expected As Variant, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Got = Expected, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub NotEquals(Got As Variant, UnExpected As Variant, Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Return Ok(Got <> UnExpected, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub LessEqual(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Got <= Bound, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Less(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Got < Bound, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub GreaterEqual(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Got >= Bound, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Greater(Got As Variant, Bound As Variant, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Got > Bound, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Approximate(Got As Float, Expected As Float, Precision As Float, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Abs(Got - Expected) <= Precision, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub RelativeApproximate(Got As Float, Expected As Float, RelPrecision As Float, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Abs((Got - Expected) / Expected) <= RelPrecision, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub IsType(Got As Variant, Type As Integer, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(TypeOf(Got) = Type, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Null(Got As Variant, Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Return Equals(Got, Null, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub NotNull(Got As Variant, Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Return NotEquals(Got, Null, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub Like(Got As String, Pattern As String, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Got Like Pattern, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Match(Got As String, Pattern As String, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Return Ok(Got Match Pattern, Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub StringEquals(Got As String, Expected As String, Optional Description As String) As Boolean
|
2020-02-23 15:54:16 +01:00
|
|
|
|
|
|
|
Dim bRes As Boolean
|
|
|
|
Dim iPos As Integer
|
|
|
|
|
|
|
|
bRes = Equals(Got, Expected, Description)
|
|
|
|
If Not bRes Then
|
|
|
|
If Len(Got) <> Len(Expected) Then
|
2020-02-23 20:06:19 +01:00
|
|
|
Note(("Strings are of different length."))
|
|
|
|
Note(Subst$((" Got: &1"), Len(Got)))
|
|
|
|
Note(Subst$((" Expected: &1"), Len(Expected)))
|
2020-02-23 15:54:16 +01:00
|
|
|
Endif
|
|
|
|
For iPos = 1 To Min(Len(Got), Len(Expected))
|
|
|
|
If Mid$(Got, iPos, 1) <> Mid$(Expected, iPos, 1) Then Break
|
|
|
|
Next
|
2020-02-23 20:06:19 +01:00
|
|
|
Note(Subst$(("Strings differ at position &1"), iPos))
|
|
|
|
Note(Subst$((" Got: &1"), Quote$(Mid$(Got, iPos, 20)) & IIf(Len(Got) > iPos + 20, "...", "")))
|
2020-02-23 22:11:15 +01:00
|
|
|
Note(Subst$((" Expected: &1"), Quote$(Mid$(Expected, iPos, 20)) & IIf(Len(Expected) > iPos + 20, "...", "")))
|
2020-02-23 15:54:16 +01:00
|
|
|
Endif
|
|
|
|
Return bRes
|
|
|
|
|
|
|
|
End
|
|
|
|
|
2020-02-23 20:06:19 +01:00
|
|
|
Public Sub Error(Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Return Ok( Error , Description)
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub ErrorCode(Code As Integer, Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Dim bRes As Boolean
|
|
|
|
|
|
|
|
If Not Error Then
|
|
|
|
bRes = Fail(Description)
|
|
|
|
Note(("No error happened"))
|
|
|
|
Else
|
|
|
|
bRes = Equals(Error.Code, Code)
|
|
|
|
If Not bRes Then
|
|
|
|
Note(Subst$(("Error was: &1 (code: &2) at &3"), Error.Text, Error.Code, Error.Where))
|
|
|
|
Endif
|
|
|
|
Endif
|
|
|
|
|
|
|
|
Error.Clear()
|
|
|
|
Return bRes
|
|
|
|
|
|
|
|
End
|
|
|
|
|
|
|
|
Public Sub NotError(Optional Description As String) As Boolean
|
|
|
|
|
|
|
|
Dim bRes As Boolean
|
|
|
|
|
|
|
|
bRes = Ok(Not Error , Description)
|
|
|
|
If Not bRes Then
|
|
|
|
Note(Subst$(("Error was: &1 (code: &2) at &3"), Error.Text, Error.Code, Error.Where))
|
|
|
|
Endif
|
|
|
|
|
|
|
|
Error.Clear()
|
|
|
|
Return bRes
|
|
|
|
|
|
|
|
End
|