1{-# LANGUAGE MultiParamTypeClasses #-}
2{-# LANGUAGE FlexibleInstances #-}
3{- Generate some input bytes and delays between blocks of input bytes. Verify the events produced
8import Verify.Graphics.Vty.Output
10import Data.List (intersperse)
12import Graphics.Vty hiding (resize)
13import Graphics.Vty.Input.Events
14import Graphics.Vty.Input.Internal
15import Graphics.Vty.Input.Terminfo
17import Control.Applicative
18import Control.Concurrent
19import Control.Exception
20import Control.Lens ((^.))
26import System.Console.Terminfo
28import System.Posix.Terminal (openPseudoTerminal)
29import System.Posix.Types
32import Test.Framework.Providers.SmallCheck
35import Test.SmallCheck.Series
39-- processing a block of 16 chars is the largest I can do without taking too long to run the test.
46forEachOf :: (Show a, Testable m b) => [a] -> (a -> b) -> Property m
47forEachOf l = over (generate (\n -> take n l))
50 = Bytes String -- | input sequence encoded as a string. Regardless, the input is read a byte at a time.
51 | Delay Int -- | microsecond delay
54type InputSpec = [InputEvent]
56type ExpectedSpec = [Event]
58synthesize_input :: InputSpec -> Fd -> IO ()
59synthesize_input input out_handle = forM_ input f >> (void $ fdWrite out_handle "\xFFFD")
61 f (Bytes str) = void $ fdWrite out_handle str
62 f (Delay t) = threadDelay t
64min_detectable_delay :: Int
65min_detectable_delay = 4000
71test_key_delay = min_detectable_delay * 4
73test_esc_sample_delay :: Int
74test_esc_sample_delay = min_detectable_delay * 2
76gen_events_using_io_actions :: Int -> IO () -> IO () -> IO ()
77gen_events_using_io_actions max_duration input_action output_action = do
78 let max_duration' = max min_timout max_duration
79 read_complete <- newEmptyMVar
80 write_complete <- newEmptyMVar
81 _ <- forkOS $ input_action `finally` putMVar write_complete ()
82 _ <- forkOS $ output_action `finally` putMVar read_complete ()
83 Just () <- timeout max_duration' $ takeMVar write_complete
84 Just () <- timeout max_duration' $ takeMVar read_complete
87compare_events :: (Show a1, Show a, Eq a1) => a -> [a1] -> [a1] -> IO Bool
88compare_events input_spec expected_events out_events = compare_events' expected_events out_events
90 compare_events' [] [] = return True
91 compare_events' [] out_events' = do
92 printf "extra events %s\n" (show out_events') :: IO ()
94 compare_events' expected_events' [] = do
95 printf "events %s were not produced for input %s\n" (show expected_events') (show input_spec) :: IO ()
96 printf "expected events %s\n" (show expected_events) :: IO ()
97 printf "received events %s\n" (show out_events) :: IO ()
99 compare_events' (e : expected_events') (o : out_events')
100 | e == o = compare_events' expected_events' out_events'
102 printf "%s expected not %s for input %s\n" (show e) (show o) (show input_spec) :: IO ()
103 printf "expected events %s\n" (show expected_events) :: IO ()
104 printf "received events %s\n" (show out_events) :: IO ()
107assert_events_from_syn_input :: ClassifyTable -> InputSpec -> ExpectedSpec -> IO Bool
108assert_events_from_syn_input table input_spec expected_events = do
109 let max_duration = sum [t | Delay t <- input_spec] + min_detectable_delay
110 event_count = length expected_events
111 (write_fd, read_fd) <- openPseudoTerminal
112 (set_term_attr,_) <- attributeControl read_fd
114 input <- initInputForFd def table read_fd
115 events_ref <- newIORef []
116 let write_wait_close = do
117 synthesize_input input_spec write_fd
118 threadDelay min_detectable_delay
120 threadDelay min_detectable_delay
124 let read_events = read_loop event_count
125 read_loop 0 = return ()
127 e <- readChan $ input^.event_channel
128 modifyIORef events_ref ((:) e)
130 gen_events_using_io_actions max_duration write_wait_close read_events
131 out_events <- reverse <$> readIORef events_ref
132 compare_events input_spec expected_events out_events
134newtype InputBlocksUsingTable event
135 = InputBlocksUsingTable ([(String,event)] -> [(String, event)])
137instance Show (InputBlocksUsingTable event) where
138 show (InputBlocksUsingTable _g) = "InputBlocksUsingTable"
140instance Monad m => Serial m (InputBlocksUsingTable event) where
142 n :: Int <- localDepth (const max_table_size) series
143 return $ InputBlocksUsingTable $ \table -> concat (take n (selections table))
146 selections (x:xs) = let z = selections xs in [x] : (z ++ map ((:) x) z)
148verify_visible_syn_input_to_event :: Property IO
149verify_visible_syn_input_to_event = forAll $ \(InputBlocksUsingTable gen) -> monadic $ do
150 let table = visible_chars
151 input_seq = gen table
152 events = map snd input_seq
153 keydowns = map (Bytes . fst) input_seq
154 input = intersperse (Delay test_key_delay) keydowns ++ [Delay test_key_delay]
155 assert_events_from_syn_input universal_table input events
157verify_caps_syn_input_to_event :: Property IO
158verify_caps_syn_input_to_event = forAll $ \(InputBlocksUsingTable gen) ->
159 forEachOf terminals_of_interest $ \term_name -> monadic $ do
160 term <- setupTerm term_name
161 let table = caps_classify_table term keys_from_caps_table
162 input_seq = gen table
163 events = map snd input_seq
164 keydowns = map (Bytes . fst) input_seq
165 input = intersperse (Delay test_key_delay) keydowns ++ [Delay test_key_delay]
166 assert_events_from_syn_input table input events
168verify_special_syn_input_to_event :: Property IO
169verify_special_syn_input_to_event = forAll $ \(InputBlocksUsingTable gen) -> monadic $ do
170 let table = special_support_keys
171 input_seq = gen table
172 events = map snd input_seq
173 keydowns = map (Bytes . fst) input_seq
174 input = intersperse (Delay test_key_delay) keydowns ++ [Delay test_key_delay]
175 assert_events_from_syn_input universal_table input events
177verify_full_syn_input_to_event :: Property IO
178verify_full_syn_input_to_event = forAll $ \(InputBlocksUsingTable gen) ->
179 forEachOf terminals_of_interest $ \term_name -> monadic $ do
180 term <- setupTerm term_name
181 let table = classify_table_for_term term_name term
182 input_seq = gen table
183 events = map snd input_seq
184 keydowns = map (Bytes . fst) input_seq
185 input = intersperse (Delay test_key_delay) keydowns ++ [Delay test_key_delay]
186 assert_events_from_syn_input table input events
188verify_full_syn_input_to_event_2x :: Property IO
189verify_full_syn_input_to_event_2x = forAll $ \(InputBlocksUsingTable gen) ->
190 forEachOf terminals_of_interest $ \term_name -> monadic $ do
191 term <- setupTerm term_name
192 let table = classify_table_for_term term_name term
193 input_seq = gen table
194 events = concatMap ((\s -> [s,s]) . snd) input_seq
195 keydowns = map (Bytes . (\s -> s ++ s) . fst) input_seq
196 input = intersperse (Delay test_key_delay) keydowns ++ [Delay test_key_delay]
197 assert_events_from_syn_input table input events
201 [ testProperty "synthesized typing of single visible chars translates to expected events"
202 verify_visible_syn_input_to_event
203 , testProperty "synthesized typing of keys from capabilities tables translates to expected events"
204 verify_caps_syn_input_to_event
205 , testProperty "synthesized typing of hard coded special keys translates to expected events"
206 verify_special_syn_input_to_event
207 , testProperty "synthesized typing of any key in the table translates to its paired event"
208 verify_full_syn_input_to_event
209 , testProperty "synthesized typing of 2x any key in the table translates to 2x paired event"
210 verify_full_syn_input_to_event_2x
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list