Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
05ed5f0
TwinTimerLib test project: 24 cases back its notes and prose (all pas…
KubaO Oct 14, 2026
7f971f4
TBMANLIB_ListBoxHScroll test project: 38 cases (76 of 76 as documente…
KubaO Oct 15, 2026
d224ef8
VBComDlg test project: 57 cases (114 of 114 as documented); ShowFont …
KubaO Oct 15, 2026
35f9df1
Package tests: a compile case that expects an error goes in the packa…
KubaO Oct 15, 2026
c27826b
Package tests: a project's Resources/ is staged by package_tests.mjs …
KubaO Oct 15, 2026
d01835e
TBMANLIB_RES test project: 40 cases (80 of 80 as documented) with its…
KubaO Oct 15, 2026
ab4dcf6
Generics test project: 18 run-time cases and 4 compile cases in compi…
KubaO Oct 15, 2026
e920890
TBMANLIB_ListBoxHScroll moves to Experimental Packages: its scroll ar…
KubaO Oct 15, 2026
f596998
package_tests.mjs: a run-time project that does not compile stops the…
KubaO Oct 15, 2026
c386e0b
TBMANLIB_Diagnostic test project: 122 cases (244 of 244 as documented…
KubaO Oct 15, 2026
f250637
tsPwGen test project: 129 run-time cases and 3 compile cases (264 of …
KubaO Oct 15, 2026
21ab183
OLEGuids test project: 52 run-time cases and 10 compile cases (124 of…
KubaO Oct 15, 2026
1bc0c37
Package tests: RunAll skips a case on the architecture where expect.j…
KubaO Oct 15, 2026
fb7da3f
tsJson test project: 230 run-time cases and 1 compile case (462 of 46…
KubaO Oct 15, 2026
9d81974
tbProjPacker test project: 74 cases (148 of 148 as documented); its P…
KubaO Oct 15, 2026
9f05e76
WIP.md: tsJson 1.0.15.0 stays Contributed (owner), its defects confir…
KubaO Oct 15, 2026
63bef7c
WIP.md: a package that does not compile on the newest BETA gets no te…
KubaO Oct 15, 2026
6a9a5a6
TBMANLIB_ConsoleCore test project: 291 run-time cases and 8 compile c…
KubaO Oct 15, 2026
26886e5
FileProps test project: 41 cases (82 of 82 as documented); a read-onl…
KubaO Oct 15, 2026
36c8439
Fmt test project: 175 cases, independent of regional settings (350 of…
KubaO Oct 15, 2026
3d7b816
Package tests: a package that compiles for one architecture only is t…
KubaO Oct 15, 2026
b0ffc21
check_package_tests: expect.json's arches is a non-empty list of win3…
KubaO Oct 15, 2026
d92cb07
TBMANLIB_Aes test project: 136 cases against FIPS 197, SP 800-38A and…
KubaO Oct 15, 2026
6c1675a
xCalendar test project: 159 run-time cases and 6 compile cases on a t…
KubaO Oct 15, 2026
a35854c
BigNumberLib test project: 128 cases (256 of 256 as documented); new …
KubaO Oct 15, 2026
5b8887b
AutoCompleteLib test project: 44 cases on a hidden Edit window (88 of…
KubaO Oct 15, 2026
5638020
TBMANLIB_ConsoleComponents test project: 213 run-time cases and 28 co…
KubaO Oct 15, 2026
e199fc8
VBA_JSON test project: 126 run-time cases and 8 compile cases (268 of…
KubaO Oct 15, 2026
ce509c4
TBMANLIB test project, 32-bit only: 260 run-time cases and 3 compile …
KubaO Oct 15, 2026
a9ca392
TBMANLIB_Xml test project: 174 cases, XPath checked against MSXML6 (3…
KubaO Oct 15, 2026
f1fd6a6
tbrun --tests: a case still running at --timeout leaves the compiler …
KubaO Oct 15, 2026
dc88c34
Downloads: the package test projects are the documentation project's,…
KubaO Oct 15, 2026
eda346d
TBMANLIB_Dialog test project: 329 cases, dialogs operated on the priv…
KubaO Oct 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ test/repro-templates/vb6/** -text
# in every checkout for the same reason: PngDump.bas is VB6's, and the copy is compared
# with the template line by line.
test/repro-templates/png/** -text

# A package test project's resources are read by its cases byte for byte (TBMANLIB_RES
# compares them with what it returns), and most have no extension git would know.
test/package-tests/*/Resources/** -text
11 changes: 11 additions & 0 deletions WIP.PackageTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ Available Packages with Embedded cleared) and restarts the compiler; an author p
their own build. The runner embeds the package from `%TEMP%\tb-twinserv` instead, as
`check_examples` does, so it never touches a packages folder.

## Compile cases that expect an error are a project of their own (owner)

A compile case that expects an error is, by design, a compile error of the project it is in, and
the compiler's test mode runs nothing in a project with errors: `tbrun --tests` reports every
`[TestCase]` *not run*. The first package with such claims (Generics: TB5074 on `New` of a package
generic, TB5124 on its unusable tuples) lost all its run-time cases to one line. So those cases
go in the package folder's `compile/`, a second project that `package_tests.mjs` stages with the
package embedded and judges with the rest. The published project stays `Sources/` alone, which
compiles, so the author's Sub Main still runs every run-time case; the compile cases are the
documentation's own re-check on each new build and version.

## Markers, and a gate that only tightens

A callout names its cases in an HTML comment on the line above it. The marker lives with the
Expand Down
4 changes: 2 additions & 2 deletions WIP.md

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion builder/package-tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@

import { promises as fs } from "node:fs";
import path from "node:path";
import { downloadName, packageTestNames, templateSettings, testSettings, testSources } from "../lib/package-tests.mjs";
import {
downloadName,
packageTestNames,
resourceFiles,
templateSettings,
testSettings,
testSources,
} from "../lib/package-tests.mjs";
import { packFiles } from "../scripts/impexp.mjs";
import { posix } from "./paths.mjs";

Expand Down Expand Up @@ -50,6 +57,7 @@ export async function packPackageTests(cfg, pkg) {
const files = [{ rel: "Settings", bytes: Buffer.from(`${JSON.stringify(settings, null, "\t")}\n`, "utf8") }];
for (const f of testSources(cfg.src, pkg))
files.push({ rel: `Sources/${f.name}`, bytes: Buffer.from(f.text, "utf8") });
for (const r of resourceFiles(cfg.src, pkg)) files.push({ rel: `Resources/${r.name}`, bytes: r.bytes });
return packFiles(files, `${pkg}Tests`).bytes;
}

Expand Down
2 changes: 1 addition & 1 deletion docs/Documentation/Tools-Compiler.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ A defect that is a compile-time diagnostic is a **compile case** instead: a line
| `--llvm` | Compile the whole probe, and the exe, with LLVM. The same as `--compiler-options +llvm`. |
| `--compiler-options <s>` | The project's compiler options, for the run and the exe. |
| `--exe` | Also run the built exe; print what it writes with `TbRun.Out`, its exit code, the fault the event log records for it, and the boxes it opened, each closed with OK. |
| `--tests` | Build nothing: judge the compile cases and run each `[TestCase]` Sub in the compiler's test mode, printing `PASS` or `FAIL` for each. `--timeout` is the limit on each case. Not with `--exe`. |
| `--tests` | Build nothing: judge the compile cases and run each `[TestCase]` Sub in the compiler's test mode, printing `PASS` or `FAIL` for each. `--timeout` is the limit on each case, not on the run. A case still running at the limit is reported as `no answer from the compiler`, and the cases after it as `not run: <case> did not return`: the compiler cannot stop a case, and refuses every other request (`main thread is busy`) until it ends. Run the cases after it again in a new `tbrun` with `--only`. Not with `--exe`. |
| `--raw` | Keep the console's timestamp column, which is otherwise stripped. |
| `--json` | One object with the path of the built file, the target, the captured lines, whether the probe returned, the licence an LLVM run checked, the exe's run, the IDE pid and anything reaped. |
| `--keep` | Leave the IDE running and print its pid as `ide-pid: <n>` (with `--json`, `idePid`) and the `taskkill` commands, as for `tbbuild`. Implies `--no-reap`, and leaves the IDE's registry entries for the probe as they are. |
Expand Down
2 changes: 2 additions & 0 deletions docs/Documentation/Tools-Samples.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ For each package and architecture (both by default), the tool stages the project
- **fixed** --- `expect.json` says it fails or never returns, and it passes: the page's callout and the entry go;
- **changed** --- anything else: a claim of the page is no longer true, or the case is wrong.

A compile case that expects an error is in the package folder's `compile/`, a second project of compile cases only, because a project with compile errors runs none of its test cases. The tool stages it with the package embedded as well and judges its cases with the others; it is not published.

A case that never returns stops the compiler. The tool catches it, runs the cases after it again in a new IDE, and from then on, once `expect.json` says so, runs it alone with `--hang-timeout`. `--update` writes `expect.json` from the run, for the architectures run. The run also writes `RunAll.twin` again whenever the cases or `expect.json` change; [`check_package_tests.mjs`](Tools-Toolchain-Tests#check-package-tests) fails while it is out of date.

The build publishes each project as `<Package>-tests.twinproj` beside the package's section, and the section's landing page links to it. It carries none of the package's code: it references the package as a [linked package](../../Features/Packages/Linked), which the IDE loads from `%APPDATA%\twinBASIC\packages`. With the package's file there, the project's `Sub Main` runs every case and prints `PASS`, `FAIL` or `SKIP` for each in the DEBUG CONSOLE.
Expand Down
2 changes: 1 addition & 1 deletion docs/Documentation/Tools-Toolchain-Tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ A callout names its cases in an HTML comment on the line above it:

The same comment anywhere else opens a region, which `<!-- /test -->` closes: it ties the paragraphs, lists, tables and samples between them, which describe how the package works, to the cases that check them. Regions do not nest, and a callout inside one is marked by it.

Each item is a `Fixture.Sub` for a `[TestCase]`, `compile <Name>` for a compile case, `probe <id>` for a scenario of the package's `probe/` harness, or `none -- <reason>` for a callout no program can check. For a package with a test project, the gate fails when a callout has neither a marker nor a region around it, when a region is not closed or opens inside another, when an item names nothing that exists, when a case is named by no marker, when a `[TestCase]` does not start with `Expect.Begin` and end with `Expect.Done`, when `expect.json` is for another version than the section's `indexed_from` or names a case that does not exist, and when the generated `RunAll.twin` is out of date. A section with no test project yet is listed in the script's `PENDING` set; the gate fails on a name there with a project, and on a section neither there nor with one, so the list only shrinks.
Each item is a `Fixture.Sub` for a `[TestCase]`, `compile <Name>` for a compile case, `probe <id>` for a scenario of the package's `probe/` harness, or `none -- <reason>` for a callout no program can check. For a package with a test project, the gate fails when a callout has neither a marker nor a region around it, when a region is not closed or opens inside another, when an item names nothing that exists, when a case is named by no marker (a compile case of the package's `compile/` project included), when `compile/` holds a `[TestCase]`, when a `[TestCase]` does not start with `Expect.Begin` and end with `Expect.Done`, when `expect.json` is for another version than the section's `indexed_from` or names a case that does not exist, and when the generated `RunAll.twin` is out of date. A section with no test project yet is listed in the script's `PENDING` set; the gate fails on a name there with a project, and on a section neither there nor with one, so the list only shrinks.

Thirteen probes run first, on pages, sources and an `expect.json` built in memory: how a marker, a region and their items are read, the RunAll module, how `expect.json` is read and written, and how a case's result is judged.

Expand Down
2 changes: 1 addition & 1 deletion docs/Downloads/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Every page of this site, to read from disk in any browser with no network. Navig

## Package test projects

Each contributed package that has test cases publishes them as a twinBASIC project. The project holds only the tests: it references the package, which goes in `%APPDATA%\twinBASIC\packages`. The package's landing page says what the cases check.
For each contributed package it has test cases for, the documentation project publishes those cases as a twinBASIC project. The project holds only the tests: it references the package, which goes in `%APPDATA%\twinBASIC\packages`. The package's landing page says what the cases check.

| Package | Test project | Size |
|---------|--------------|------|
Expand Down
1 change: 0 additions & 1 deletion docs/Reference/Contributed.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ Each package is versioned apart from twinBASIC, and its section says which versi
- [**Generics**](Generics/) -- tuples, read-only objects that hold one to seven values of declared types
- [**OLEGuids**](OLEGuids/) -- OLE and COM interfaces and structures in twinBASIC source, in place of `OLEGuids.tlb`
- [**tbFileSysTools**](tbFileSysTools/) -- files, folders, drives and text streams, in place of the Scripting Runtime's **FileSystemObject**
- [**TBMANLIB_ListBoxHScroll**](TBMANLIB_ListBoxHScroll/) -- a horizontal scroll bar for a **ListBox**
- [**TBMANLIB_RES**](TBMANLIB_RES/) -- resources embedded in an executable, as bytes, strings, hex, Base64 or pictures
- [**tbProjPacker**](tbProjPacker/) -- a `.twinproj` or `.twinpack` file unpacked into a folder of source files, and packed again
- [**tbRegExp**](tbRegExp/) -- regular expressions, in place of VBScript's **RegExp** object
Expand Down
38 changes: 35 additions & 3 deletions docs/Reference/Contributed/AutoCompleteLib/AutoComplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ has_toc: false

A class that attaches Windows shell auto-complete behaviour to a text-input control's window handle.

<!-- test: InitTests.CustomSource_CompletesTheTypedText, InitTests.FileSystem_CompletesAPath, InitTests.All_CompletesAPath, InitTests.HistoryMruAndAll_RaiseNothing -->
**AutoComplete** wraps the `IAutoComplete2` COM interface. After calling [**Init**](#init) with the window handle of an edit box and a source type, the Windows shell begins offering suggestions as the user types. The source can be the shell history, the file system, the most-recently-used list, all three combined, or a custom string array supplied through [**CustomSource**](#customsource).
<!-- /test -->

```tb check_build
Private m_AC As AutoComplete
Expand All @@ -34,10 +36,14 @@ Returns or sets a one-dimensional **String** array used as the suggestion list w

Syntax: *object*.**CustomSource** [ = *StringArray* ]

<!-- test: CustomSourceTests.Set_Strings_AreKeptInOrder, CustomSourceTests.Set_EmptyStrings_AreIgnored, CustomSourceTests.Set_NonStringElements_AreIgnored, CustomSourceTests.Set_ArrayOfNumbers_GivesAnEmptyList, CustomSourceTests.Set_TypedStringArray_WithALowerBound_IsKept, CustomSourceTests.Set_ZeroLengthArray_ClearsTheList, CustomSourceTests.Set_Empty_ClearsTheList, CustomSourceTests.Set_TwoDimensionalArray_Raises5_AndKeepsTheList, CustomSourceTests.Set_UnallocatedArray_Raises91_AndKeepsTheList, CustomSourceTests.Set_AValueThatIsNotAnArray_Raises380, InitTests.CustomSource_ClearedAfterInit_CompletesNothing -->
*StringArray*
: A one-dimensional **Variant** holding a **String** array. Empty strings and non-string elements are silently ignored. Assigning **Empty** clears the list. A two-or-more-dimensional array raises run-time error 5 ("Array must be single dimensioned"). An unallocated array raises run-time error 91. Any other value that is not an array raises run-time error 380.
: A one-dimensional **Variant** holding a **String** array. Empty strings and non-string elements are silently ignored. Assigning **Empty** clears the list. A two-or-more-dimensional array raises run-time error 5 ("Array must be single dimensioned"). An unallocated array raises run-time error 91. Any other value that is not an array raises run-time error 380. An assignment that raises an error leaves the list as it was.
<!-- /test -->

The getter returns the filtered array currently stored in the object. Assigning a new value replaces the previous list in full; there is no way to append individual entries.
<!-- test: CustomSourceTests.Get_ReturnsAZeroBasedStringArray, CustomSourceTests.Set_TypedStringArray_WithALowerBound_IsKept, CustomSourceTests.Set_NewArray_ReplacesThePreviousListInFull, CustomSourceTests.Get_EmptyList_IsAnArrayThatIsNotAllocated, InitTests.CustomSource_ReplacedAfterInit_CompletesFromTheNewList, InitTests.CustomSource_NoMatch_LeavesTheText, InitTests.CustomSource_EmptyList_LeavesTheText -->
The getter returns the filtered array currently stored in the object: a zero-based array of **String**, whatever the bounds of the array that was assigned. While the list is empty, the array is not allocated, and **UBound** of it raises run-time error 9. Assigning a new value replaces the previous list in full, also while the list is attached to a window; there is no way to append individual entries.
<!-- /test -->

### FileSystemOptions
{: .no_toc }
Expand All @@ -59,6 +65,10 @@ Syntax: *object*.**FileSystemOptions** [ = *value* ]
| **AutoCompleteFileSystemOptionFileSysOnly** | 16 | File-system items only (no virtual shell folders). |
| **AutoCompleteFileSystemOptionFileSysDirs** | 32 | Directories only. |

<!-- test: FileSystemOptionsTests.EachConstant_IsKept, FileSystemOptionsTests.Combination_IsKept, FileSystemOptionsTests.FileSysDirs_OffersADirectory, FileSystemOptionsTests.FileSysDirs_DoesNotOfferAFile, FileSystemOptionsTests.FileSysOnly_OffersAFile, FileSystemOptionsTests.SetBeforeInit_Applies, FileSystemOptionsTests.SetAfterInit_Applies, FileSystemOptionsTests.AllSource_FollowsTheSetting, OptionsTests.Constants_HaveTheDocumentedValues -->
The getter returns the value that was set. The setting applies whether it is made before or after [**Init**](#init), and to the source **AutoCompleteSourceAll** as to **AutoCompleteSourceFileSystem**. With **AutoCompleteFileSystemOptionFileSysDirs**, the list offers directories and no files; with **AutoCompleteFileSystemOptionFileSysOnly**, it offers files.
<!-- /test -->

### Options
{: .no_toc }

Expand All @@ -81,6 +91,10 @@ Syntax: *object*.**Options** [ = *value* ]
| **AutoCompleteOptionUpDownKeyDropsList** | &H20 | Opens the drop-down list when the user presses the **Up** or **Down** arrow key. |
| **AutoCompleteOptionRightToLeft** | &H40 | Shows the text of the drop-down list from right to left. |

<!-- test: OptionsTests.EachConstant_IsKept, OptionsTests.Combination_IsKept, OptionsTests.Append_AppendsTheBestMatch, OptionsTests.None_AppendsNothing, OptionsTests.SetAfterInit_Applies, InitTests.CustomSource_CompletesTheTypedText -->
The getter returns the value that was set. The setting applies whether it is made before or after [**Init**](#init). With **AutoCompleteOptionAppend** the text of the best match is appended to what was typed and selected; with **AutoCompleteOptionNone** nothing is appended.
<!-- /test -->

## Methods

### Disable
Expand All @@ -90,7 +104,9 @@ Disables auto-complete without destroying the object.

Syntax: *object*.**Disable**

<!-- test: SwitchTests.Disable_StopsTheSuggestions, SwitchTests.Disable_KeepsTheSourceAndTheList -->
Auto-complete stops offering suggestions. Call [**Enable**](#enable) to turn it back on without calling [**Init**](#init) again.
<!-- /test -->

### DroppedDown
{: .no_toc }
Expand All @@ -101,10 +117,16 @@ Syntax: *object*.**DroppedDown** ( ) **As Boolean**

Returns **True** when the drop-down is open, **False** otherwise. The return value is **False** if the `IAutoCompleteDropDown` interface cannot be obtained.

<!-- test: SwitchTests.DroppedDown_BeforeAnyList_IsFalse -->
An object that has not been initialised, and one whose list has not been opened, return **False**.
<!-- /test -->

### Enable
{: .no_toc }

<!-- test: SwitchTests.Enable_ResumesTheSuggestions -->
Re-enables auto-complete after a call to [**Disable**](#disable).
<!-- /test -->

Syntax: *object*.**Enable**

Expand All @@ -130,7 +152,17 @@ Syntax: *object*.**Init** *hWndEdit*, *Source*
| **AutoCompleteSourceAll** | 4 | History, file system, and MRU combined through an `IObjMgr`. |
| **AutoCompleteSourceCustomSource** | 5 | The one-dimensional string array set through [**CustomSource**](#customsource). |

The target control must exist when **Init** is called, and **Init** is called before the user starts typing. Calling **Init** with **AutoCompleteSourceNone**, or with any other value outside the table, raises run-time error 380 (Invalid property value). If the internal `IAutoComplete2` object could not be created when the **AutoComplete** object was created, **Init** exits silently.
The target control must exist when **Init** is called, and **Init** is called before the user starts typing.

<!-- test: InitTests.SourceNone_Raises380, InitTests.SourceOutsideTheTable_Raises380, InitTests.WindowHandleZero_Raises5 -->
Calling **Init** with **AutoCompleteSourceNone**, or with any other value outside the table, raises run-time error 380 (Invalid property value). A *hWndEdit* of 0 raises run-time error 5 (Automation error).
<!-- /test -->

If the internal `IAutoComplete2` object could not be created when the **AutoComplete** object was created, **Init** exits silently.

<!-- test: InitTests.SecondCall_OnTheSameObject_Raises, InitTests.OneObjectForEachWindow_RaiseNothing -->
> [!NOTE] 1.0.3.0
> An **AutoComplete** object attaches to one window, once. A second call to **Init** on the same object, for the same window or for another, raises run-time error -2147467259 (Automation error) and attaches nothing. Create one **AutoComplete** object for each text box.

### Refresh
{: .no_toc }
Expand Down
4 changes: 4 additions & 0 deletions docs/Reference/Contributed/AutoCompleteLib/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ The **AutoCompleteLib** contributed package provides Windows shell auto-complete
## Classes

- [AutoComplete](AutoComplete) -- attaches Windows shell auto-complete behaviour to a text-input control's window handle.

## Test cases

The notes and warnings of this section are checked by the test cases in [AutoCompleteLib-tests.twinproj](AutoCompleteLib-tests.twinproj), a twinBASIC project. It uses AutoCompleteLib as a [linked package](../../../../Features/Packages/Linked#manual-management): put the package's `.twinpack` in `%APPDATA%\twinBASIC\packages`, then run the project, and each case prints whether it passes.
Loading
Loading