+Before:
+ Save g:ale_fix_on_save
+ Save g:ale_enabled
+ Save g:ale_run_synchronously
+ Save g:ale_set_lists_synchronously
+ Save g:ale_buffer_info
+ Save g:ale_linters
+
+ let g:ale_buffer_info = {}
+ let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
+ let g:ale_set_lists_synchronously = 1
+ let b:ale_save_event_fired = 0
+
+ let g:buffer_result = [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 1,
+ \ 'text': 'buffer error',
+ \ 'type': 'E',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 1,
+ \ 'text': 'buffer warning',
+ \ 'type': 'W',
+ \ },
+ \]
+
+ function! LintFileCallback(buffer, output)
+ return [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 3,
+ \ 'text': 'file warning',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 3,
+ \ 'text': 'file error',
+ \ 'type': 'E',
+ \ },
+ \]
+ endfunction
+
+ function! BufferCallback(buffer, output)
+ return deepcopy(g:buffer_result)
+ endfunction
+
+ function! GetSimplerLoclist()
+ let l:loclist = []
+
+ for l:item in ale#test#GetLoclistWithoutNewerKeys()
+ call add(l:loclist, {
+ \ 'lnum': l:item.lnum,
+ \ 'col': l:item.col,
+ \ 'text': l:item.text,
+ \ 'type': l:item.type,
+ \})
+ endfor
+
+ return l:loclist
+ endfunction
+
+ call ale#linter#Define('foobar', {
+ \ 'name': 'lint_file_linter',
+ \ 'callback': 'LintFileCallback',
+ \ 'executable': has('win32') ? 'cmd' : 'echo',
+ \ 'command': 'echo',
+ \ 'lint_file': 1,
+ \})
+
+ call ale#linter#Define('foobar', {
+ \ 'name': 'buffer_linter',
+ \ 'callback': 'BufferCallback',
+ \ 'executable': has('win32') ? 'cmd' : 'echo',
+ \ 'command': 'echo',
+ \ 'read_buffer': 0,
+ \})
+
+ let g:filename = tempname()
+ call writefile([], g:filename)
+ call ale#test#SetFilename(g:filename)
+
+After:
+ if !g:ale_run_synchronously
+ call ale#engine#Cleanup(bufnr(''))
+ endif
+
+ Restore
+
+ unlet! g:ale_run_synchronously_callbacks
+ unlet! b:ale_save_event_fired
+ unlet! b:ale_enabled
+ unlet g:buffer_result
+ let g:ale_buffer_info = {}
+ call ale#linter#Reset()
+ call setloclist(0, [])
+ delfunction LintFileCallback
+ delfunction BufferCallback
+
+ if filereadable(g:filename)
+ call delete(g:filename)
+ endif
+
+ unlet g:filename
+
+Given foobar (Some imaginary filetype):
+ foo
+ bar
+ baz
+
+Execute(Running linters without 'lint_file' should run only buffer linters):
+ call ale#Queue(0)
+ call ale#test#FlushJobs()
+
+ AssertEqual [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 1,
+ \ 'text': 'buffer error',
+ \ 'type': 'E',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 1,
+ \ 'text': 'buffer warning',
+ \ 'type': 'W',
+ \ },
+ \], GetSimplerLoclist()
+
+Execute(Running linters with 'lint_file' should run all linters):
+ Assert filereadable(expand('%:p')), 'The file was not readable'
+
+ call ale#Queue(0, 'lint_file')
+ call ale#test#FlushJobs()
+
+ AssertEqual [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 1,
+ \ 'text': 'buffer error',
+ \ 'type': 'E',
+ \ },
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 3,
+ \ 'text': 'file warning',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 1,
+ \ 'text': 'buffer warning',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 3,
+ \ 'text': 'file error',
+ \ 'type': 'E',
+ \ },
+ \], GetSimplerLoclist()
+
+Execute(Linter errors from files should be kept):
+ Assert filereadable(expand('%:p')), 'The file was not readable'
+
+ call ale#Queue(0, 'lint_file')
+ call ale#test#FlushJobs()
+
+ " Change the results for the buffer callback.
+ let g:buffer_result = [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 1,
+ \ 'text': 'new buffer error',
+ \ 'type': 'E',
+ \ },
+ \]
+
+ call ale#Queue(0)
+ call ale#test#FlushJobs()
+
+ AssertEqual [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 1,
+ \ 'text': 'new buffer error',
+ \ 'type': 'E',
+ \ },
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 3,
+ \ 'text': 'file warning',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 3,
+ \ 'text': 'file error',
+ \ 'type': 'E',
+ \ },
+ \], GetSimplerLoclist()
+
+Execute(Linter errors from files should be kept when no other linters are run):
+ let g:ale_linters = {'foobar': ['lint_file_linter']}
+ Assert filereadable(expand('%:p')), 'The file was not readable'
+
+ call ale#Queue(0, 'lint_file')
+ call ale#test#FlushJobs()
+
+ AssertEqual [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 3,
+ \ 'text': 'file warning',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 3,
+ \ 'text': 'file error',
+ \ 'type': 'E',
+ \ },
+ \], GetSimplerLoclist()
+
+ call ale#Queue(0)
+
+ AssertEqual [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 3,
+ \ 'text': 'file warning',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 3,
+ \ 'text': 'file error',
+ \ 'type': 'E',
+ \ },
+ \], GetSimplerLoclist()
+
+Execute(The Save event should respect the buffer number):
+ let g:ale_linters = {'foobar': ['lint_file_linter']}
+ Assert filereadable(expand('%:p')), 'The file was not readable'
+
+ call ale#events#SaveEvent(bufnr('') + 1)
+ call ale#test#FlushJobs()
+
+ " We shouldn't get any prblems yet.
+ AssertEqual [], GetSimplerLoclist()
+
+ call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
+
+ " We should get them now we used the right buffer number.
+ AssertEqual [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 3,
+ \ 'text': 'file warning',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 2,
+ \ 'col': 3,
+ \ 'text': 'file error',
+ \ 'type': 'E',
+ \ },
+ \], GetSimplerLoclist()
+
+Execute(The Save event should set b:ale_save_event_fired to 1):
+ let g:ale_lint_on_save = 1
+ let b:ale_enabled = 1
+
+ call ale#linter#Reset()
+ call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
+
+ " This flag needs to be set so windows can be opened, etc.
+ AssertEqual 1, b:ale_save_event_fired
+
+Execute(b:ale_save_event_fired should be set to 0 when results are set):
+ let b:ale_save_event_fired = 1
+
+ call ale#engine#SetResults(bufnr(''), [])
+ call ale#test#FlushJobs()
+
+ AssertEqual 0, b:ale_save_event_fired
+
+Execute(lint_file linters should stay running after checking without them):
+ let g:ale_run_synchronously = 0
+
+ " Run all linters, then just the buffer linters.
+ call ale#Queue(0, 'lint_file')
+ call ale#Queue(0)
+
+ " The lint_file linter should still be running.
+ AssertEqual
+ \ ['lint_file_linter', 'buffer_linter'],
+ \ map(copy(g:ale_buffer_info[bufnr('')].active_linter_list), 'v:val.name')
+ " We should have 1 job for each linter.
+ AssertEqual
+ \ 2,
+ \ len(keys(get(get(ale#command#GetData(), bufnr(''), {}), 'jobs', {})))
+
+ call ale#test#WaitForJobs(2000)
+
+Execute(The save event should not lint the buffer when ALE is disabled):
+ let g:ale_enabled = 0
+ call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
+
+ AssertEqual [], GetSimplerLoclist()
+ AssertEqual 0, b:ale_save_event_fired