]> git.lizzy.rs Git - micro.git/blob - cmd/micro/micro_test.go
delete minor unreachable code caused by log.Fatal (#2507)
[micro.git] / cmd / micro / micro_test.go
1 package main
2
3 import (
4         "fmt"
5         "io/ioutil"
6         "log"
7         "os"
8         "testing"
9
10         "github.com/go-errors/errors"
11         "github.com/stretchr/testify/assert"
12         "github.com/zyedidia/micro/v2/internal/action"
13         "github.com/zyedidia/micro/v2/internal/buffer"
14         "github.com/zyedidia/micro/v2/internal/config"
15         "github.com/zyedidia/micro/v2/internal/screen"
16         "github.com/zyedidia/tcell/v2"
17 )
18
19 var tempDir string
20 var sim tcell.SimulationScreen
21
22 func init() {
23         screen.Events = make(chan tcell.Event, 8)
24 }
25
26 func startup(args []string) (tcell.SimulationScreen, error) {
27         var err error
28
29         tempDir, err = ioutil.TempDir("", "micro_test")
30         if err != nil {
31                 return nil, err
32         }
33         err = config.InitConfigDir(tempDir)
34         if err != nil {
35                 return nil, err
36         }
37
38         config.InitRuntimeFiles()
39         err = config.ReadSettings()
40         if err != nil {
41                 return nil, err
42         }
43         err = config.InitGlobalSettings()
44         if err != nil {
45                 return nil, err
46         }
47
48         s, err := screen.InitSimScreen()
49         if err != nil {
50                 return nil, err
51         }
52
53         defer func() {
54                 if err := recover(); err != nil {
55                         screen.Screen.Fini()
56                         fmt.Println("Micro encountered an error:", err)
57                         // backup all open buffers
58                         for _, b := range buffer.OpenBuffers {
59                                 b.Backup()
60                         }
61                         // Print the stack trace too
62                         log.Fatalf(errors.Wrap(err, 2).ErrorStack())
63                 }
64         }()
65
66         err = config.LoadAllPlugins()
67         if err != nil {
68                 screen.TermMessage(err)
69         }
70
71         action.InitBindings()
72         action.InitCommands()
73
74         err = config.InitColorscheme()
75         if err != nil {
76                 return nil, err
77         }
78
79         b := LoadInput(args)
80
81         if len(b) == 0 {
82                 return nil, errors.New("No buffers opened")
83         }
84
85         action.InitTabs(b)
86         action.InitGlobals()
87
88         err = config.RunPluginFn("init")
89         if err != nil {
90                 return nil, err
91         }
92
93         s.InjectResize()
94         handleEvent()
95
96         return s, nil
97 }
98
99 func cleanup() {
100         os.RemoveAll(tempDir)
101 }
102
103 func handleEvent() {
104         screen.Lock()
105         e := screen.Screen.PollEvent()
106         screen.Unlock()
107         if e != nil {
108                 screen.Events <- e
109         }
110         DoEvent()
111 }
112
113 func injectKey(key tcell.Key, r rune, mod tcell.ModMask) {
114         sim.InjectKey(key, r, mod)
115         handleEvent()
116 }
117
118 func injectMouse(x, y int, buttons tcell.ButtonMask, mod tcell.ModMask) {
119         sim.InjectMouse(x, y, buttons, mod)
120         handleEvent()
121 }
122
123 func injectString(str string) {
124         // the tcell simulation screen event channel can only handle
125         // 10 events at once, so we need to divide up the key events
126         // into chunks of 10 and handle the 10 events before sending
127         // another chunk of events
128         iters := len(str) / 10
129         extra := len(str) % 10
130
131         for i := 0; i < iters; i++ {
132                 s := i * 10
133                 e := i*10 + 10
134                 sim.InjectKeyBytes([]byte(str[s:e]))
135                 for i := 0; i < 10; i++ {
136                         handleEvent()
137                 }
138         }
139
140         sim.InjectKeyBytes([]byte(str[len(str)-extra:]))
141         for i := 0; i < extra; i++ {
142                 handleEvent()
143         }
144 }
145
146 func openFile(file string) {
147         injectKey(tcell.KeyCtrlE, rune(tcell.KeyCtrlE), tcell.ModCtrl)
148         injectString(fmt.Sprintf("open %s", file))
149         injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)
150 }
151
152 func createTestFile(name string, content string) (string, error) {
153         testf, err := ioutil.TempFile("", name)
154         if err != nil {
155                 return "", err
156         }
157
158         if _, err := testf.Write([]byte(content)); err != nil {
159                 return "", err
160         }
161         if err := testf.Close(); err != nil {
162                 return "", err
163         }
164
165         return testf.Name(), nil
166 }
167
168 func TestMain(m *testing.M) {
169         var err error
170         sim, err = startup([]string{})
171         if err != nil {
172                 log.Fatalln(err)
173         }
174
175         retval := m.Run()
176         cleanup()
177
178         os.Exit(retval)
179 }
180
181 func TestSimpleEdit(t *testing.T) {
182         file, err := createTestFile("micro_simple_edit_test", "base content")
183         if err != nil {
184                 t.Error(err)
185                 return
186         }
187         defer os.Remove(file)
188
189         openFile(file)
190
191         var buf *buffer.Buffer
192         for _, b := range buffer.OpenBuffers {
193                 if b.Path == file {
194                         buf = b
195                 }
196         }
197
198         if buf == nil {
199                 t.Errorf("Could not find buffer %s", file)
200                 return
201         }
202
203         injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)
204         injectKey(tcell.KeyUp, 0, tcell.ModNone)
205         injectString("first line")
206
207         // test both kinds of backspace
208         for i := 0; i < len("ne"); i++ {
209                 injectKey(tcell.KeyBackspace, rune(tcell.KeyBackspace), tcell.ModNone)
210         }
211         for i := 0; i < len(" li"); i++ {
212                 injectKey(tcell.KeyBackspace2, rune(tcell.KeyBackspace2), tcell.ModNone)
213         }
214         injectString("foobar")
215
216         injectKey(tcell.KeyCtrlS, rune(tcell.KeyCtrlS), tcell.ModCtrl)
217
218         data, err := ioutil.ReadFile(file)
219         if err != nil {
220                 t.Error(err)
221                 return
222         }
223
224         assert.Equal(t, "firstfoobar\nbase content\n", string(data))
225 }
226
227 func TestMouse(t *testing.T) {
228         file, err := createTestFile("micro_mouse_test", "base content")
229         if err != nil {
230                 t.Error(err)
231                 return
232         }
233         defer os.Remove(file)
234
235         openFile(file)
236
237         // buffer:
238         // base content
239         // the selections need to happen at different locations to avoid a double click
240         injectMouse(3, 0, tcell.Button1, tcell.ModNone)
241         injectKey(tcell.KeyLeft, 0, tcell.ModNone)
242         injectMouse(0, 0, tcell.ButtonNone, tcell.ModNone)
243         injectString("secondline")
244         // buffer:
245         // secondlinebase content
246         injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)
247         // buffer:
248         // secondline
249         // base content
250         injectMouse(2, 0, tcell.Button1, tcell.ModNone)
251         injectMouse(0, 0, tcell.ButtonNone, tcell.ModNone)
252         injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)
253         // buffer:
254         //
255         // secondline
256         // base content
257         injectKey(tcell.KeyUp, 0, tcell.ModNone)
258         injectString("firstline")
259         // buffer:
260         // firstline
261         // secondline
262         // base content
263         injectKey(tcell.KeyCtrlS, rune(tcell.KeyCtrlS), tcell.ModCtrl)
264
265         data, err := ioutil.ReadFile(file)
266         if err != nil {
267                 t.Error(err)
268                 return
269         }
270
271         assert.Equal(t, "firstline\nsecondline\nbase content\n", string(data))
272 }
273
274 var srTestStart = `foo
275 foo
276 foofoofoo
277 Ernleȝe foo æðelen
278 `
279 var srTest2 = `test_string
280 test_string
281 test_stringtest_stringtest_string
282 Ernleȝe test_string æðelen
283 `
284 var srTest3 = `test_foo
285 test_string
286 test_footest_stringtest_foo
287 Ernleȝe test_string æðelen
288 `
289
290 func TestSearchAndReplace(t *testing.T) {
291         file, err := createTestFile("micro_search_replace_test", srTestStart)
292         if err != nil {
293                 t.Error(err)
294                 return
295         }
296         defer os.Remove(file)
297
298         openFile(file)
299
300         injectKey(tcell.KeyCtrlE, rune(tcell.KeyCtrlE), tcell.ModCtrl)
301         injectString(fmt.Sprintf("replaceall %s %s", "foo", "test_string"))
302         injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)
303
304         injectKey(tcell.KeyCtrlS, rune(tcell.KeyCtrlS), tcell.ModCtrl)
305
306         data, err := ioutil.ReadFile(file)
307         if err != nil {
308                 t.Error(err)
309                 return
310         }
311
312         assert.Equal(t, srTest2, string(data))
313
314         injectKey(tcell.KeyCtrlE, rune(tcell.KeyCtrlE), tcell.ModCtrl)
315         injectString(fmt.Sprintf("replace %s %s", "string", "foo"))
316         injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)
317         injectString("ynyny")
318         injectKey(tcell.KeyEscape, 0, tcell.ModNone)
319
320         injectKey(tcell.KeyCtrlS, rune(tcell.KeyCtrlS), tcell.ModCtrl)
321
322         data, err = ioutil.ReadFile(file)
323         if err != nil {
324                 t.Error(err)
325                 return
326         }
327
328         assert.Equal(t, srTest3, string(data))
329 }
330
331 func TestMultiCursor(t *testing.T) {
332         // TODO
333 }
334
335 func TestSettingsPersistence(t *testing.T) {
336         // TODO
337 }
338
339 // more tests (rendering, tabs, plugins)?