summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/winConsole.test105
-rw-r--r--win/tclWinConsole.c74
2 files changed, 136 insertions, 43 deletions
diff --git a/tests/winConsole.test b/tests/winConsole.test
index 795e16d..ae0d939 100644
--- a/tests/winConsole.test
+++ b/tests/winConsole.test
@@ -34,25 +34,24 @@ proc yesno {question {default "Y"}} {
}
proc prompt {prompt} {
- set answer ""
- # Make sure we are seen but catch because ui and console
+ # Make sure we are seen but catch because twapi ui and console
# packages may not be available
catch {twapi::set_foreground_window [twapi::get_console_window]}
puts -nonewline stdout "$prompt"
- return [gets stdin]
+ flush stdout
}
+# Input tests
-test winConsole-1.0 {Console blocking gets} -constraints {win interactive xx} -body {
- set response [prompt "Type a line of text and press Return\n"]
- yesno "Did you type \"$response\""
-} -result 1
+test console-gets-1.0 {Console blocking gets} -constraints {win interactive} -body {
+ set response [prompt "Type \"xyz\" and hit Enter: "]
+ gets stdin
+} -result xyz
-test winConsole-1.1 {Console file channel: non-blocking gets} {win interactive} {
+test console-gets-1.1 {Console file channel: non-blocking gets} {win interactive} {
set oldmode [fconfigure stdin]
- puts stdout "Enter abcdef<return> now: " nonewline
- flush stdout
+ set response [prompt "Type \"abc\" and hit Enter: "]
fileevent stdin readable {
if {[gets stdin line] >= 0} {
set result $line
@@ -72,9 +71,93 @@ test winConsole-1.1 {Console file channel: non-blocking gets} {win interactive}
set result
-} "abcdef"
+} abc
+
+# Output tests
+
+test console-puts-1.0 {Console blocking puts stdout} -constraints {win interactive} -body {
+ puts stdout "123"
+ yesno "Did you see the string \"123\"?"
+} -result 1
+test console-puts-1.1 {Console blocking puts stderr} -constraints {win interactive} -body {
+ puts stderr "456"
+ yesno "Did you see the string \"456\"?"
+} -result 1
+# fconfigure tests
+
+## stdin
+
+test console-fconfigure-1.0 {
+ Console get stdin configuration
+} -constraints {win interactive} -body {
+ lsort [dict keys [fconfigure stdin]]
+} -result {-blocking -buffering -buffersize -encoding -eofchar -inputmode -translation}
+
+set testnum 0
+foreach {opt result} {
+ -blocking 1
+ -buffering line
+ -buffersize 4096
+ -encoding utf-16
+ -inputmode normal
+ -translation auto
+} {
+ test console-fconfigure-1.[incr testnum] "Console get stdin option $opt" \
+ -constraints {win interactive} -body {
+ fconfigure stdin $opt
+ } -result $result
+}
+test console-fconfigure-1.[incr testnum] {
+ Console get stdin option -eofchar
+} -constraints {win interactive} -body {
+ fconfigure stdin -eofchar
+} -result \x1a
+
+test console-fconfigure-1.[incr testnum] {
+ fconfigure -inputmode password
+} -constraints {win interactive} -body {
+ prompt "Type \"password\" and hit Enter. You should NOT see characters echoed"
+ fconfigure stdin -inputmode password
+ gets stdin password
+ set password_echoed [yesno "Were the characters echoed?"]
+ prompt "Type \"normal\" and hit Enter. You should see characters echoed"
+ fconfigure stdin -inputmode normal
+ gets stdin normal
+ set normal_echoed [yesno "Were the characters echoed?"]
+ list $password_echoed $password $normal_echoed $normal
+
+} -result [list 0 password 1 normal]
+
+## stdout/stderr
+foreach chan {stdout stderr} major {2 3} {
+ test console-fconfigure-$major.0 "Console get $chan configuration" -constraints {
+ win interactive
+ } -body {
+ lsort [dict keys [fconfigure $chan]]
+ } -result {-blocking -buffering -buffersize -encoding -eofchar -translation -winsize}
+ set testnum 0
+ foreach {opt result} {
+ -blocking 1
+ -buffersize 4096
+ -encoding utf-16
+ -translation crlf
+ } {
+ test console-fconfigure-$major.[incr testnum] "Console get $chan option $opt" \
+ -constraints {win interactive} -body {
+ fconfigure $chan $opt
+ } -result $result
+ }
+
+ test console-fconfigure-$major.[incr testnum] "Console get $chan option -winsize" -constraints {win interactive} -body {
+ fconfigure $chan -winsize
+ } -result {\d+ \d+} -match regexp
+
+ test console-fconfigure-$major.[incr testnum] "Console get $chan option -buffering" -constraints {win interactive} -body {
+ fconfigure $chan -buffering
+ } -result [expr {$chan eq "stdout" ? "line" : "none"}]
+}
#cleanup
diff --git a/win/tclWinConsole.c b/win/tclWinConsole.c
index 653d580..7ca94ce 100644
--- a/win/tclWinConsole.c
+++ b/win/tclWinConsole.c
@@ -54,15 +54,14 @@
static int initialized = 0;
-#ifdef TCL_CONSOLE_DEBUG
-#ifndef CONSOLE_BUFFER_SIZE
/*
- * Force tiny to stress synchronization. Must be at least 2*sizeof(WCHAR) :-)
- * to work around Tcl channel bug https://core.tcl-lang.org/tcl/tktview/b3977d199b08e3979a8da970553d5209b3042e9c
+ * Permit CONSOLE_BUFFER_SIZE to be defined on build command for stress test.
+ *
+ * In theory, at least sizeof(WCHAR) but note the Tcl channel bug
+ * https://core.tcl-lang.org/tcl/tktview/b3977d199b08e3979a8da970553d5209b3042e9c
+ * will cause failures in test suite if close to max input line in the suite.
*/
-#define CONSOLE_BUFFER_SIZE (2*sizeof(WCHAR))
-#endif
-#else
+#ifndef CONSOLE_BUFFER_SIZE
#define CONSOLE_BUFFER_SIZE 8000 /* In bytes */
#endif
@@ -1161,7 +1160,7 @@ ConsoleInputProc(
* holds a reference count on handleInfoPtr, it will not
* be deallocated while the lock is released.
*/
- //WakeConditionVariable(&handleInfoPtr->consoleThreadCV); TODO - Needed?
+ // WakeConditionVariable(&handleInfoPtr->consoleThreadCV); // TODO - Needed?
if (!SleepConditionVariableSRW(&handleInfoPtr->interpThreadCV,
&handleInfoPtr->lock,
INFINITE,
@@ -2263,41 +2262,52 @@ ConsoleGetOptionProc(
}
}
}
+ else {
+ /*
+ * Output channel. Get option -winsize
+ * Option is readonly and returned by [fconfigure chan -winsize] but not
+ * returned by [fconfigure chan] without explicit option name.
+ */
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-winsize");
+ }
- /*
- * Get option -winsize
- * Option is readonly and returned by [fconfigure chan -winsize] but not
- * returned by [fconfigure chan] without explicit option name.
- */
-
- if ((len > 1) && (strncmp(optionName, "-winsize", len) == 0)) {
- CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
+ if (len == 0 || (len > 1 && strncmp(optionName, "-winsize", len) == 0)) {
+ CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
- valid = 1;
- if (!GetConsoleScreenBufferInfo(chanInfoPtr->handle, &consoleInfo)) {
- Tcl_WinConvertError(GetLastError());
- if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "couldn't read console size: %s",
- Tcl_PosixError(interp)));
+ valid = 1;
+ if (!GetConsoleScreenBufferInfo(chanInfoPtr->handle,
+ &consoleInfo)) {
+ Tcl_WinConvertError(GetLastError());
+ if (interp != NULL) {
+ Tcl_SetObjResult(
+ interp,
+ Tcl_ObjPrintf("couldn't read console size: %s",
+ Tcl_PosixError(interp)));
+ }
+ return TCL_ERROR;
}
- return TCL_ERROR;
+ Tcl_DStringStartSublist(dsPtr);
+ sprintf(buf,
+ "%d",
+ consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1);
+ Tcl_DStringAppendElement(dsPtr, buf);
+ sprintf(buf,
+ "%d",
+ consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1);
+ Tcl_DStringAppendElement(dsPtr, buf);
+ Tcl_DStringEndSublist(dsPtr);
}
- sprintf(buf, "%d",
- consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1);
- Tcl_DStringAppendElement(dsPtr, buf);
- sprintf(buf, "%d",
- consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1);
- Tcl_DStringAppendElement(dsPtr, buf);
}
+
if (valid) {
return TCL_OK;
}
if (chanInfoPtr->flags & CONSOLE_READ_OPS) {
- return Tcl_BadChannelOption(interp, optionName, "inputmode winsize");
+ return Tcl_BadChannelOption(interp, optionName, "inputmode");
} else {
- return Tcl_BadChannelOption(interp, optionName, "");
+ return Tcl_BadChannelOption(interp, optionName, "winsize");
}
}