console_windows_test.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // +build windows
  2. package winconsole
  3. import (
  4. "fmt"
  5. "testing"
  6. )
  7. func helpsTestParseInt16OrDefault(t *testing.T, expectedValue int16, shouldFail bool, input string, defaultValue int16, format string, args ...string) {
  8. value, err := parseInt16OrDefault(input, defaultValue)
  9. if nil != err && !shouldFail {
  10. t.Errorf("Unexpected error returned %v", err)
  11. t.Errorf(format, args)
  12. }
  13. if nil == err && shouldFail {
  14. t.Errorf("Should have failed as expected\n\tReturned value = %d", value)
  15. t.Errorf(format, args)
  16. }
  17. if expectedValue != value {
  18. t.Errorf("The value returned does not match expected\n\tExpected:%v\n\t:Actual%v", expectedValue, value)
  19. t.Errorf(format, args)
  20. }
  21. }
  22. func TestParseInt16OrDefault(t *testing.T) {
  23. // empty string
  24. helpsTestParseInt16OrDefault(t, 0, false, "", 0, "Empty string returns default")
  25. helpsTestParseInt16OrDefault(t, 2, false, "", 2, "Empty string returns default")
  26. // normal case
  27. helpsTestParseInt16OrDefault(t, 0, false, "0", 0, "0 handled correctly")
  28. helpsTestParseInt16OrDefault(t, 111, false, "111", 2, "Normal")
  29. helpsTestParseInt16OrDefault(t, 111, false, "+111", 2, "+N")
  30. helpsTestParseInt16OrDefault(t, -111, false, "-111", 2, "-N")
  31. helpsTestParseInt16OrDefault(t, 0, false, "+0", 11, "+0")
  32. helpsTestParseInt16OrDefault(t, 0, false, "-0", 12, "-0")
  33. // ill formed strings
  34. helpsTestParseInt16OrDefault(t, 0, true, "abc", 0, "Invalid string")
  35. helpsTestParseInt16OrDefault(t, 42, true, "+= 23", 42, "Invalid string")
  36. helpsTestParseInt16OrDefault(t, 42, true, "123.45", 42, "float like")
  37. }
  38. func helpsTestGetNumberOfChars(t *testing.T, expected uint32, fromCoord COORD, toCoord COORD, screenSize COORD, format string, args ...interface{}) {
  39. actual := getNumberOfChars(fromCoord, toCoord, screenSize)
  40. mesg := fmt.Sprintf(format, args)
  41. assertTrue(t, expected == actual, fmt.Sprintf("%s Expected=%d, Actual=%d, Parameters = { fromCoord=%+v, toCoord=%+v, screenSize=%+v", mesg, expected, actual, fromCoord, toCoord, screenSize))
  42. }
  43. func TestGetNumberOfChars(t *testing.T) {
  44. // Note: The columns and lines are 0 based
  45. // Also that interval is "inclusive" means will have both start and end chars
  46. // This test only tests the number opf characters being written
  47. // all four corners
  48. maxWindow := COORD{X: 80, Y: 50}
  49. leftTop := COORD{X: 0, Y: 0}
  50. rightTop := COORD{X: 79, Y: 0}
  51. leftBottom := COORD{X: 0, Y: 49}
  52. rightBottom := COORD{X: 79, Y: 49}
  53. // same position
  54. helpsTestGetNumberOfChars(t, 1, COORD{X: 1, Y: 14}, COORD{X: 1, Y: 14}, COORD{X: 80, Y: 50}, "Same position random line")
  55. // four corners
  56. helpsTestGetNumberOfChars(t, 1, leftTop, leftTop, maxWindow, "Same position- leftTop")
  57. helpsTestGetNumberOfChars(t, 1, rightTop, rightTop, maxWindow, "Same position- rightTop")
  58. helpsTestGetNumberOfChars(t, 1, leftBottom, leftBottom, maxWindow, "Same position- leftBottom")
  59. helpsTestGetNumberOfChars(t, 1, rightBottom, rightBottom, maxWindow, "Same position- rightBottom")
  60. // from this char to next char on same line
  61. helpsTestGetNumberOfChars(t, 2, COORD{X: 0, Y: 0}, COORD{X: 1, Y: 0}, maxWindow, "Next position on same line")
  62. helpsTestGetNumberOfChars(t, 2, COORD{X: 1, Y: 14}, COORD{X: 2, Y: 14}, maxWindow, "Next position on same line")
  63. // from this char to next 10 chars on same line
  64. helpsTestGetNumberOfChars(t, 11, COORD{X: 0, Y: 0}, COORD{X: 10, Y: 0}, maxWindow, "Next position on same line")
  65. helpsTestGetNumberOfChars(t, 11, COORD{X: 1, Y: 14}, COORD{X: 11, Y: 14}, maxWindow, "Next position on same line")
  66. helpsTestGetNumberOfChars(t, 5, COORD{X: 3, Y: 11}, COORD{X: 7, Y: 11}, maxWindow, "To and from on same line")
  67. helpsTestGetNumberOfChars(t, 8, COORD{X: 0, Y: 34}, COORD{X: 7, Y: 34}, maxWindow, "Start of line to middle")
  68. helpsTestGetNumberOfChars(t, 4, COORD{X: 76, Y: 34}, COORD{X: 79, Y: 34}, maxWindow, "Middle to end of line")
  69. // multiple lines - 1
  70. helpsTestGetNumberOfChars(t, 81, COORD{X: 0, Y: 0}, COORD{X: 0, Y: 1}, maxWindow, "one line below same X")
  71. helpsTestGetNumberOfChars(t, 81, COORD{X: 10, Y: 10}, COORD{X: 10, Y: 11}, maxWindow, "one line below same X")
  72. // multiple lines - 2
  73. helpsTestGetNumberOfChars(t, 161, COORD{X: 0, Y: 0}, COORD{X: 0, Y: 2}, maxWindow, "one line below same X")
  74. helpsTestGetNumberOfChars(t, 161, COORD{X: 10, Y: 10}, COORD{X: 10, Y: 12}, maxWindow, "one line below same X")
  75. // multiple lines - 3
  76. helpsTestGetNumberOfChars(t, 241, COORD{X: 0, Y: 0}, COORD{X: 0, Y: 3}, maxWindow, "one line below same X")
  77. helpsTestGetNumberOfChars(t, 241, COORD{X: 10, Y: 10}, COORD{X: 10, Y: 13}, maxWindow, "one line below same X")
  78. // full line
  79. helpsTestGetNumberOfChars(t, 80, COORD{X: 0, Y: 0}, COORD{X: 79, Y: 0}, maxWindow, "Full line - first")
  80. helpsTestGetNumberOfChars(t, 80, COORD{X: 0, Y: 23}, COORD{X: 79, Y: 23}, maxWindow, "Full line - random")
  81. helpsTestGetNumberOfChars(t, 80, COORD{X: 0, Y: 49}, COORD{X: 79, Y: 49}, maxWindow, "Full line - last")
  82. // full screen
  83. helpsTestGetNumberOfChars(t, 80*50, leftTop, rightBottom, maxWindow, "full screen")
  84. helpsTestGetNumberOfChars(t, 80*50-1, COORD{X: 1, Y: 0}, rightBottom, maxWindow, "dropping first char to, end of screen")
  85. helpsTestGetNumberOfChars(t, 80*50-2, COORD{X: 2, Y: 0}, rightBottom, maxWindow, "dropping first two char to, end of screen")
  86. helpsTestGetNumberOfChars(t, 80*50-1, leftTop, COORD{X: 78, Y: 49}, maxWindow, "from start of screen, till last char-1")
  87. helpsTestGetNumberOfChars(t, 80*50-2, leftTop, COORD{X: 77, Y: 49}, maxWindow, "from start of screen, till last char-2")
  88. helpsTestGetNumberOfChars(t, 80*50-5, COORD{X: 4, Y: 0}, COORD{X: 78, Y: 49}, COORD{X: 80, Y: 50}, "from start of screen+4, till last char-1")
  89. helpsTestGetNumberOfChars(t, 80*50-6, COORD{X: 4, Y: 0}, COORD{X: 77, Y: 49}, COORD{X: 80, Y: 50}, "from start of screen+4, till last char-2")
  90. }
  91. var allForeground = []int16{
  92. ANSI_FOREGROUND_BLACK,
  93. ANSI_FOREGROUND_RED,
  94. ANSI_FOREGROUND_GREEN,
  95. ANSI_FOREGROUND_YELLOW,
  96. ANSI_FOREGROUND_BLUE,
  97. ANSI_FOREGROUND_MAGENTA,
  98. ANSI_FOREGROUND_CYAN,
  99. ANSI_FOREGROUND_WHITE,
  100. ANSI_FOREGROUND_DEFAULT,
  101. }
  102. var allBackground = []int16{
  103. ANSI_BACKGROUND_BLACK,
  104. ANSI_BACKGROUND_RED,
  105. ANSI_BACKGROUND_GREEN,
  106. ANSI_BACKGROUND_YELLOW,
  107. ANSI_BACKGROUND_BLUE,
  108. ANSI_BACKGROUND_MAGENTA,
  109. ANSI_BACKGROUND_CYAN,
  110. ANSI_BACKGROUND_WHITE,
  111. ANSI_BACKGROUND_DEFAULT,
  112. }
  113. func maskForeground(flag WORD) WORD {
  114. return flag & FOREGROUND_MASK_UNSET
  115. }
  116. func onlyForeground(flag WORD) WORD {
  117. return flag & FOREGROUND_MASK_SET
  118. }
  119. func maskBackground(flag WORD) WORD {
  120. return flag & BACKGROUND_MASK_UNSET
  121. }
  122. func onlyBackground(flag WORD) WORD {
  123. return flag & BACKGROUND_MASK_SET
  124. }
  125. func helpsTestGetWindowsTextAttributeForAnsiValue(t *testing.T, oldValue WORD /*, expected WORD*/, ansi int16, onlyMask WORD, restMask WORD) WORD {
  126. actual, err := getWindowsTextAttributeForAnsiValue(oldValue, FOREGROUND_MASK_SET, ansi)
  127. assertTrue(t, nil == err, "Should be no error")
  128. // assert that other bits are not affected
  129. if 0 != oldValue {
  130. assertTrue(t, (actual&restMask) == (oldValue&restMask), "The operation should not have affected other bits actual=%X oldValue=%X ansi=%d", actual, oldValue, ansi)
  131. }
  132. return actual
  133. }
  134. func TestBackgroundForAnsiValue(t *testing.T) {
  135. // Check that nothing else changes
  136. // background changes
  137. for _, state1 := range allBackground {
  138. for _, state2 := range allBackground {
  139. flag := WORD(0)
  140. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  141. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  142. }
  143. }
  144. // cummulative bcakground changes
  145. for _, state1 := range allBackground {
  146. flag := WORD(0)
  147. for _, state2 := range allBackground {
  148. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  149. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  150. }
  151. }
  152. // change background after foreground
  153. for _, state1 := range allForeground {
  154. for _, state2 := range allBackground {
  155. flag := WORD(0)
  156. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  157. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  158. }
  159. }
  160. // change background after change cumulative
  161. for _, state1 := range allForeground {
  162. flag := WORD(0)
  163. for _, state2 := range allBackground {
  164. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  165. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  166. }
  167. }
  168. }
  169. func TestForegroundForAnsiValue(t *testing.T) {
  170. // Check that nothing else changes
  171. for _, state1 := range allForeground {
  172. for _, state2 := range allForeground {
  173. flag := WORD(0)
  174. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  175. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  176. }
  177. }
  178. for _, state1 := range allForeground {
  179. flag := WORD(0)
  180. for _, state2 := range allForeground {
  181. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  182. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  183. }
  184. }
  185. for _, state1 := range allBackground {
  186. for _, state2 := range allForeground {
  187. flag := WORD(0)
  188. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  189. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  190. }
  191. }
  192. for _, state1 := range allBackground {
  193. flag := WORD(0)
  194. for _, state2 := range allForeground {
  195. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state1, BACKGROUND_MASK_SET, BACKGROUND_MASK_UNSET)
  196. flag = helpsTestGetWindowsTextAttributeForAnsiValue(t, flag, state2, FOREGROUND_MASK_SET, FOREGROUND_MASK_UNSET)
  197. }
  198. }
  199. }