# selftest_less.exp — drives less's pager half over a REAL pty. # # WHY THIS FILE EXISTS. less is two programs in one binary, selected by # isatty(1). The one the piped runner reaches is a byte copier: main.c takes the # `if (!is_tty)` branch and cat_file()s the input straight to stdout, so a build # whose termcap/ncurses link was silently broken would still pass every # non-interactive case in 70-less.test. Paging, end-of-file positioning and # search only exist on a terminal, and these five cases are the only thing that # says the pager — the whole point of the package — works on target. # # EVERY SESSION SIZES ITS OWN TERMINAL. expect's stty_init is not applied to the # pty it allocates on this target — a fresh spawn reports the controlling # console's geometry instead — so the `stty rows 24 columns 80` prefix is # load-bearing: which corpus lines land on which screen is computed from LINES, # and without it every needle below becomes a property of whoever ran the suite. # 61-bitwise.test and 59-dialog.test carry the same prologue for the same reason. # # THE SCREEN ARITHMETIC, since the needles depend on it. At 24 rows less paints # 23 corpus lines plus one status line, so screen 1 is line0000..line0022 and a # single SPACE (forward one window) brings line0023..line0045. line0030 is # therefore off screen 1 and on screen 2 — that gap is what makes L2page an # assertion about paging rather than about the first repaint. # # THE MATCH STRINGS ARE WHOLE, UNHIGHLIGHTED LINE PREFIXES, deliberately. less # wraps a search hit in standout (ESC[7m ... ESC[27m), so L4search matches the # line's "line0150" prefix and NOT the "MARKER-LESS-BST" token it searched for — # a needle inside the highlighted run would have escapes spliced through it. # # Emits LSX-OK/LSX-FAIL lines for 70-less.test to grade, and ALL-LESS-OK # only when all five passed. log_user 0 set env(TERM) "xterm" set timeout 20 set SIZE "stty rows 24 columns 80;" set F [lindex $argv 0] set fails 0 proc emit {verdict case detail} { global fails if {$verdict eq "FAIL"} { incr fails } puts "LSX-$verdict $case $detail" } spawn -noecho sh -c "$SIZE exec less $F" # --- L1first: the pager painted its first screen ----------------------------- set seen 0 expect { "line0000" { set seen 1 } timeout { } eof { } } if {$seen} { emit OK L1first "" } else { emit FAIL L1first "no line0000 — less never painted a first screen" } # --- L2page: SPACE advances one window --------------------------------------- # line0030 is on screen 2 only; seeing it means the keystroke reached less and a # whole window was scrolled, not merely that the file was dumped. send -- " " set paged 0 expect { "line0030" { set paged 1 } timeout { } eof { } } if {$paged} { emit OK L2page "" } else { emit FAIL L2page "SPACE did not bring line0030 onto the screen" } # --- L3end: G goes to end-of-file -------------------------------------------- send -- "G" set atend 0 expect { "line0199" { set atend 1 } timeout { } eof { } } if {$atend} { emit OK L3end "" } else { emit FAIL L3end "G did not reach the last line (line0199)" } # --- L4search: /pattern finds a match 150 lines down ------------------------- # Back to the top first, so the search has to travel rather than match whatever # happens to be under the cursor at end-of-file. send -- "g" expect { "line0000" { } timeout { } eof { } } send -- "/MARKER-LESS-BST\r" set found 0 expect { "line0150" { set found 1 } timeout { } eof { } } if {$found} { emit OK L4search "" } else { emit FAIL L4search "/MARKER-LESS-BST did not position on line0150" } # --- L5quit: q exits the pager cleanly --------------------------------------- send -- "q" expect { eof {} timeout {} } lassign [wait] _pid _spawnid _oserr _rc if {$_oserr == 0 && $_rc == 0} { emit OK L5quit "" } else { emit FAIL L5quit "oserr=$_oserr rc=$_rc" } if {$fails == 0} { puts "ALL-LESS-OK" }