Include: include/setup.vader

Execute (neomake#signs#RedefineErrorSign):
  Save g:neomake_verbose
  let g:neomake_verbose = 3

  new
  file file1
  let bufnr = bufnr('%')
  let maker = neomake#utils#MakerFromCommand(
    \ 'echo file1: E: error without line; echo file1:2: W: warning')
  call extend(maker, {
        \ 'name': 'custom_maker',
        \ 'errorformat': '%E%f:%l: %t: %m,%E%f: %t: %m',
        \ 'append_file': 0,
        \ }, 'error')

  call neomake#Make(1, [maker])
  NeomakeTestsWaitForFinishedJobs
  AssertNeomakeMessage 'Placing sign: sign place 5000 line=2 name=neomake_file_warn buffer='.bufnr('%').'.'

  AssertNeomakeMessage '\vCould not place signs for 1 entries without line number: \[.*\].', 3

  " Test #736.
  call neomake#signs#RedefineErrorSign({'text': 'X', 'texthl': 'ErrorMsg'})
  let sign = substitute(neomake#utils#redir('sign list neomake_file_err'), '\v^[\n]*', '', '')
  AssertEqual split(sign), ['sign', 'neomake_file_err', 'text=X', 'texthl=ErrorMsg']
  AssertEqual neomake#signs#by_lnum(bufnr('%')), {'2': [[5000, 'neomake_file_warn']]}

  call neomake#Make(1, [maker])
  NeomakeTestsWaitForFinishedJobs
  " AssertNeomakeMessage 'Reusing sign: id=5000, type=neomake_file_warn, lnum=2.'
  AssertNeomakeMessage 'Reused 1 signs.', 3, {'bufnr': bufnr}
  AssertNeomakeMessage 'Cleaning 0 old signs.', 3, {'bufnr': bufnr}
  AssertEqual neomake#signs#by_lnum(bufnr('%')), {'2': [[5000, 'neomake_file_warn']]}

  call neomake#signs#Reset(bufnr, 'file')
  call neomake#signs#CleanAllOldSigns('file')
  AssertNeomakeMessage 'Cleaning 1 old signs.', 3
  AssertEqual neomake#signs#by_lnum(bufnr), {}
  bwipe

Execute (Placing signs in project mode):
  new
  let maker = neomake#utils#MakerFromCommand('echo 1:1: W: warning')
  call extend(maker, {
        \ 'name': 'custom_maker',
        \ 'errorformat': '%E%f:%l: %t: %m',
        \ }, 'error')
  file 1
  let bufnr = bufnr('%')
  call neomake#Make(0, [maker])
  NeomakeTestsWaitForFinishedJobs
  AssertNeomakeMessage 'Placing sign: sign place 5000 line=1 name=neomake_project_warn buffer='.bufnr.'.'
  bd

  call neomake#signs#Reset(bufnr, 'project')
  call neomake#signs#CleanAllOldSigns('project')
  AssertNeomakeMessage 'Cleaning 1 old signs.', 3, {'bufnr': bufnr}
  AssertEqual neomake#signs#by_lnum(bufnr), {}
  exe 'bwipe' bufnr

Execute (Signs are not re-used / wiped across modes):
  new
  let bufnr = bufnr('%')
  AssertEqual neomake#signs#by_lnum(bufnr), {}
  call neomake#signs#PlaceSigns(bufnr('%'),
  \ [{'type': 'E', 'bufnr': bufnr('%'), 'lnum': 1}], 'file')
  call neomake#signs#PlaceSigns(bufnr('%'),
  \ [{'type': 'W', 'bufnr': bufnr('%'), 'lnum': 1}], 'project')

  AssertNeomakeMessage 'Placing sign: sign place 5000 line=1 name=neomake_file_err buffer='.bufnr.'.'
  AssertNeomakeMessage 'Placing sign: sign place 5001 line=1 name=neomake_project_warn buffer='.bufnr.'.'
  call neomake#signs#ResetProject()
  AssertNeomakeMessage 'Cleaning 1 old signs.', 3, {'bufnr': bufnr}
  call neomake#signs#CleanAllOldSigns('project')
  AssertNeomakeMessage 'Removing signs: {file: {}, project: {}}.'

  AssertEqual neomake#signs#by_lnum(bufnr), {'1': [[5000, 'neomake_file_err']]}
  call neomake#signs#RedefineSign('neomake_file_warn', {})
  bwipe

Execute (Signs are wiped when buffer gets wiped):
  new
  call neomake#signs#PlaceSigns(bufnr('%'),
  \ [{'type': 'E', 'bufnr': bufnr('%'), 'lnum': 1}], 'file')
  bwipe
  " Should not cause 'E158: Invalid buffer name'
  call neomake#signs#RedefineSign('neomake_file_err', {})

Execute (neomake#signs#by_lnum):
  new
  let bufnr = bufnr('%')
  exe 'sign place 5000 name=neomake_file_err line=1 buffer='.bufnr
  exe 'sign place 5001 name=neomake_file_warn line=2 buffer='.bufnr
  exe 'sign place 5002 name=neomake_file_info line=3 buffer='.bufnr
  AssertEqual neomake#signs#by_lnum(bufnr('%')), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5002, 'neomake_file_info']]}

  " Visible (last placed sign) is first in list.
  exe 'sign place 5003 name=neomake_file_info line=1 buffer='.bufnr
  AssertEqual neomake#signs#by_lnum(bufnr('%')), {
  \ '1': [[5003, 'neomake_file_info'], [5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5002, 'neomake_file_info']]}
  bwipe

Execute (neomake#signs#by_lnum for invalid bufnr):
  AssertEqual neomake#signs#by_lnum(9999), {}
  AssertEqual neomake#signs#by_lnum('9999'), {}

Execute (neomake#signs#PlaceSigns):
  new
  let bufnr = bufnr('%')
  let entries = [
  \ {'lnum': 1, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'I', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr('%')), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5002, 'neomake_file_info']]}

  let entries = [
  \ {'lnum': 1, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'I', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'E', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5002, 'neomake_file_err']]}

  let entries = [
  \ {'lnum': 2, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 4, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 4, 'type': 'I', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_err']],
  \ '3': [[5002, 'neomake_file_warn']],
  \ '4': [[5003, 'neomake_file_err']]}

  call neomake#signs#Reset(bufnr, 'file')
  call neomake#signs#CleanOldSigns(bufnr, 'file')
  AssertEqual neomake#signs#by_lnum(bufnr), {}
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '2': [[5000, 'neomake_file_err']],
  \ '3': [[5001, 'neomake_file_warn']],
  \ '4': [[5002, 'neomake_file_err']]}

  let entries = [
  \ {'lnum': 4, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'I', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '2': [[5000, 'neomake_file_err']],
  \ '3': [[5001, 'neomake_file_warn']],
  \ '4': [[5002, 'neomake_file_err']]}

  let entries = [
  \ {'lnum': 4, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 5, 'type': 'I', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '2': [[5000, 'neomake_file_err']],
  \ '3': [[5001, 'neomake_file_warn']],
  \ '4': [[5002, 'neomake_file_err']],
  \ '5': [[5003, 'neomake_file_info']]}

  call neomake#signs#Reset(bufnr, 'file')
  call neomake#signs#CleanOldSigns(bufnr, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr), {}
  bwipe

Execute (neomake#signs#PlaceSigns with E and I (E after I)):
  new
  file foo
  bwipe
  Save g:neomake_place_signs_count
  let g:neomake_place_signs_count = 1

  new
  let bufnr = bufnr('%')
  let entries = [
  \ {'lnum': 1, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'I', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'E', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr('%')), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5002, 'neomake_file_err']]}
  bwipe

Execute (neomake#signs#PlaceSigns with E and I (E before I)):
  Save g:neomake_place_signs_count
  let g:neomake_place_signs_count = 1

  new
  let bufnr = bufnr('%')
  let entries = [
  \ {'lnum': 1, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'I', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr('%')), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5002, 'neomake_file_err']]}
  bwipe

Execute (neomake#signs#PlaceSigns handles multiple signs per line):
  Save g:neomake_place_signs_count
  let g:neomake_place_signs_count = -1

  new
  let bufnr = bufnr('%')
  let entries = [
  \ {'lnum': 1, 'type': 'E', 'bufnr': bufnr},
  \ {'lnum': 2, 'type': 'W', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'I', 'bufnr': bufnr},
  \ {'lnum': 3, 'type': 'E', 'bufnr': bufnr}]
  call neomake#signs#PlaceSigns(bufnr, entries, 'file')

  AssertEqual neomake#signs#by_lnum(bufnr('%')), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5002, 'neomake_file_err']]}
  bwipe

Execute (Signs get handled across multiple get_list_entries jobs):
  new
  let bufnr = bufnr('%')
  let maker1 = {'_idx': 'maker1'}
  function! maker1.get_list_entries(jobinfo) abort dict
    return map(copy(g:neomake_test_entries[self._idx]),
    \ "extend(v:val, {'bufnr': bufnr('%')}, 'keep')")
  endfunction
  let maker2 = copy(maker1)
  let maker2._idx = 'maker2'
  let g:neomake_test_entries = {
  \ 'maker1': [{'type': 'E', 'lnum': 1, 'text': 'error'}],
  \ 'maker2': [{'type': 'W', 'lnum': 2, 'text': 'warning'}]}

  call neomake#Make(1, [maker1])
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']]}

  call neomake#Make(1, [maker1, maker2])
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']]}

  call neomake#Make(1, [maker1])
  AssertNeomakeMessage 'Cleaning 1 old signs.', 3, {'bufnr': bufnr}
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']]}

  call neomake#Make(1, [maker1, maker2])
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_warn']]}
  bwipe

Execute (next sign_id based on max):
  new
  let bufnr = bufnr('%')
  exe 'sign place 5002 line=1 name=neomake_file_warn buffer='.bufnr
  exe 'sign place 5001 line=2 name=neomake_file_warn buffer='.bufnr
  call neomake#signs#PlaceSigns(bufnr, [{'lnum': 3, 'type': 'W'}], 'file')
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5002, 'neomake_file_warn']],
  \ '2': [[5001, 'neomake_file_warn']],
  \ '3': [[5003, 'neomake_file_warn']]}
  bwipe

Execute (file mode signs get placed when job finishes):
  if NeomakeAsyncTestsSetup()
    new
    file signs.test
    let bufnr = bufnr('%')
    let options = {
    \ 'errorformat': '%f:%l:%t:%m',
    \ 'mapexpr': "bufname('%').':'.v:val"}
    let maker1 = NeomakeTestsCommandMaker('maker1', 'echo 1:I:msg1; echo 3:W:msg2')
    call extend(maker1, options)
    let maker2 = NeomakeTestsCommandMaker('maker2', 'sleep .1; echo 1:W:msg3; echo 2:E:msg4')
    call extend(maker2, options)

    call neomake#Make(1, [maker1, maker2])
    NeomakeTestsWaitForNextFinishedJob

    AssertEqual neomake#signs#by_lnum(bufnr), {
    \ '1': [[5000, 'neomake_file_info']],
    \ '3': [[5001, 'neomake_file_warn']]}
    NeomakeTestsWaitForFinishedJobs
    AssertEqual neomake#signs#by_lnum(bufnr), {
    \ '1': [[5000, 'neomake_file_warn']],
    \ '2': [[5002, 'neomake_file_err']],
    \ '3': [[5001, 'neomake_file_warn']]}
    bwipe
  endif

Execute (project mode signs get placed when job finishes):
  if NeomakeAsyncTestsSetup()
    new
    file signs1.test
    let bufnr1 = bufnr('%')
    new
    file signs2.test
    let bufnr2 = bufnr('%')
    let maker1 = NeomakeTestsCommandMaker('maker1',
    \ 'echo signs1.test:1:I:msg1; echo signs2.test:3:W:msg2')
    let maker1.errorformat = '%f:%l:%t:%m'
    let maker2 = NeomakeTestsCommandMaker('maker2',
    \ 'sleep .1; echo signs1.test:1:W:msg3; echo signs2.test:2:E:msg4')
    let maker2.errorformat = '%f:%l:%t:%m'

    call neomake#Make(0, [maker1, maker2])
    NeomakeTestsWaitForNextFinishedJob

    AssertEqual neomake#signs#by_lnum(bufnr1), {
    \ '1': [[5000, 'neomake_project_info']]}
    AssertEqual neomake#signs#by_lnum(bufnr2), {
    \ '3': [[5000, 'neomake_project_warn']]}
    NeomakeTestsWaitForFinishedJobs
    AssertEqual neomake#signs#by_lnum(bufnr1), {
    \ '1': [[5000, 'neomake_project_warn']]}
    AssertEqual neomake#signs#by_lnum(bufnr2), {
    \ '2': [[5001, 'neomake_project_err']],
    \ '3': [[5000, 'neomake_project_warn']]}

    " Verify sign handling with a file mode maker on top.
    let maker = {'_bufnr': bufnr1}
    function maker.get_list_entries(...)
      return [{'bufnr': self._bufnr, 'lnum': 1, 'type': 'E'}]
    endfunction
    CallNeomake {'file_mode': 1, 'enabled_makers': [maker]}
    AssertNeomakeMessage 'Placing sign: sign place 5001 line=1 name=neomake_file_err buffer='.bufnr1.'.'
    if has('patch-8.1.0384') || has('netbeans_intg')
      AssertEqual neomake#signs#by_lnum(bufnr1), {
      \ '1': [[5001, 'neomake_file_err'], [5000, 'neomake_project_warn']]}
    endif
    call neomake#signs#ResetFile(bufnr1)
    call neomake#signs#CleanAllOldSigns('file')
    AssertEqual neomake#signs#by_lnum(bufnr1), {
    \ '1': [[5000, 'neomake_project_warn']]}
    bwipe
    bwipe
  endif

Execute (Highlights for signs get (re-)defined on ColorScheme event):
  if exists('g:colors_name')
    let colorscheme = g:colors_name
    let had_colorscheme = 1
  else
    let colorscheme = 'default'
    let had_colorscheme = 0
  endif
  let orig = neomake#utils#redir('hi NeomakeErrorSignDefault')
  exe 'colorscheme' colorscheme
  let new = neomake#utils#redir('hi NeomakeErrorSignDefault')
  if had_colorscheme
    AssertEqual orig, new
  else
    Assert stridx(new, 'cleared') == -1, 'highlight is not cleared.'
  endif

Execute (neomake#signs#PlaceSigns keeps sign moved by lnum):
  new
  let bufnr = bufnr('%')
  function! s:place_sign(lnum)
    let bufnr = bufnr('%')
    call neomake#signs#PlaceSigns(bufnr, [
    \ {'lnum': a:lnum, 'type': 'E', 'bufnr': bufnr}], 'file')
  endfunction

  call s:place_sign(1)
  AssertNeomakeMessage 'Placing sign: sign place 5000 line=1 name=neomake_file_err buffer='.bufnr.'.'
  AssertEqual neomake#signs#by_lnum(bufnr), {'1': [[5000, 'neomake_file_err']]}

  normal! O
  AssertEqual neomake#signs#by_lnum(bufnr), {'2': [[5000, 'neomake_file_err']]}

  call neomake#signs#Reset(bufnr, 'file')
  call s:place_sign(2)
  " AssertNeomakeMessage 'Reusing sign: id=5000, type=neomake_file_err, lnum=2.'
  AssertNeomakeMessage 'Reused 1 signs.', 3, {'bufnr': bufnr}
  call neomake#signs#CleanOldSigns(bufnr, 'file')
  AssertNeomakeMessage 'Cleaning 0 old signs.', 3, {'bufnr': bufnr}

  call neomake#signs#Reset(bufnr, 'file')
  AssertEqual neomake#signs#by_lnum(bufnr), {'2': [[5000, 'neomake_file_err']]}
  call neomake#signs#CleanOldSigns(bufnr, 'file')
  AssertNeomakeMessage 'Cleaning 1 old signs.', 3, {'bufnr': bufnr}
  AssertEqual neomake#signs#by_lnum(bufnr), {}
  bwipe!

Execute (CleanOldSigns removes unplaced sign from s:placed_signs):
  new
  let bufnr = bufnr('%')

  let s:call_count = 0
  let maker = {}
  function maker.get_list_entries(...)
    let s:call_count += 1
    let bufnr = bufnr('%')
    let entries = [
      \ {'lnum': 1, 'text': '1', 'bufnr': bufnr, 'type': 'E'},
      \ ]
    if s:call_count != 2
      let entries += [
        \ {'lnum': 2, 'text': '2', 'bufnr': bufnr, 'type': 'E'},
        \ ]
    endif
    return entries
  endfunction

  normal! 3o

  CallNeomake 1, [maker]
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_err']],
  \ }

  CallNeomake 1, [maker]
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']],
  \ }
  AssertNeomakeMessage 'Cleaning 1 old signs.', 3, {'bufnr': bufnr}

  CallNeomake 1, [maker]
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_err']],
  \ '2': [[5001, 'neomake_file_err']],
  \ }
  " AssertNeomakeMessage 'Reusing sign: id=5000, type=neomake_file_err, lnum=1.', 3
  AssertNeomakeMessage 'Reused 1 signs.', 3
  AssertNeomakeMessage 'Placing sign: sign place 5001 line=2 name=neomake_file_err buffer='.bufnr.'.'
  bwipe!

Execute (neomake#signs#PlaceSigns handles lowercase and fallback entry type):
  new
  let bufnr = bufnr('%')
  call neomake#signs#PlaceSigns(bufnr, [
  \ {'type': 'w', 'bufnr': bufnr, 'lnum': 1},
  \ {'type': 'i', 'bufnr': bufnr, 'lnum': 2},
  \ {'type': 'm', 'bufnr': bufnr, 'lnum': 3},
  \ {'type': 'e', 'bufnr': bufnr, 'lnum': 4},
  \ {'type': 'x', 'bufnr': bufnr, 'lnum': 5},
  \ ], 'file')

  AssertNeomakeMessage 'Placing sign: sign place 5000 line=1 name=neomake_file_warn buffer='.bufnr.'.'
  AssertNeomakeMessage 'Placing sign: sign place 5001 line=2 name=neomake_file_info buffer='.bufnr.'.'
  AssertNeomakeMessage 'Placing sign: sign place 5002 line=3 name=neomake_file_msg buffer='.bufnr.'.'
  AssertNeomakeMessage 'Placing sign: sign place 5003 line=4 name=neomake_file_err buffer='.bufnr.'.'
  AssertNeomakeMessage 'Placing sign: sign place 5004 line=5 name=neomake_file_err buffer='.bufnr.'.'
  AssertEqual neomake#signs#by_lnum(bufnr), {
  \ '1': [[5000, 'neomake_file_warn']],
  \ '2': [[5001, 'neomake_file_info']],
  \ '3': [[5002, 'neomake_file_msg']],
  \ '4': [[5003, 'neomake_file_err']],
  \ '5': [[5004, 'neomake_file_err']],
  \ }
  bwipe

Execute (Signs should be placed with QuickfixCmdPost already (loclist)):
  new

  let s:calls = []
  function OnQuickfixCmdPost()
    call add(s:calls, neomake#signs#by_lnum(bufnr('%')))
  endfunction

  augroup neomake_tests
    autocmd QuickfixCmdPost laddexpr call OnQuickfixCmdPost()
  augroup END

  CallNeomake 1, [g:error_maker]

  let signs = neomake#signs#by_lnum(bufnr('%'))
  AssertEqual signs, {'1': [[5000, 'neomake_file_err']]}

  if has('patch-8.0.1040')  " 'efm' in setqflist/getqflist
    AssertEqual s:calls, []
  else
    AssertEqual s:calls, [signs]
  endif
  bwipe
  delfunction OnQuickfixCmdPost

Execute (Signs should be placed with QuickfixCmdPost already (qflist)):
  new

  let s:calls = []
  function OnQuickfixCmdPost()
    call add(s:calls, neomake#signs#by_lnum(bufnr('%')))
  endfunction

  augroup neomake_tests
    autocmd QuickfixCmdPost caddexpr call OnQuickfixCmdPost()
  augroup END

  CallNeomake 0, [g:error_maker]

  let signs = neomake#signs#by_lnum(bufnr('%'))
  AssertEqual signs, {'1': [[5000, 'neomake_project_err']]}

  if has('patch-8.0.1040')  " 'efm' in setqflist/getqflist
    AssertEqual s:calls, []
  else
    AssertEqual s:calls, [signs]
  endif
  bwipe
  delfunction OnQuickfixCmdPost

Execute (neomake#signs#PlaceSigns: prevents re-used signs from being cleaned):
  new
  let bufnr = bufnr('%')

  call neomake#signs#PlaceSigns(bufnr('%'),
  \ [{'type': 'E', 'bufnr': bufnr('%'), 'lnum': 1}], 'file')
  AssertNeomakeMessage 'Placing sign: sign place 5000 line=1 name=neomake_file_err buffer='.bufnr.'.'

  call neomake#signs#Reset(bufnr, 'file')

  call neomake#signs#PlaceSigns(bufnr('%'),
  \ [{'type': 'W', 'bufnr': bufnr('%'), 'lnum': 1}], 'file')
  AssertNeomakeMessage 'Upgrading sign for lnum=1: sign place 5000 name=neomake_file_warn buffer='.bufnr.'.'

  call neomake#signs#Reset(bufnr, 'file')

  AssertNeomakeMessage 'Cleaning 0 old signs.', 3
  bwipe

Execute (Uses base sign id with only other signs):
  new
  sign define testsign
  exe 'sign place 99 line=1 name=testsign buffer='.bufnr('%')
  AssertEqual neomake#signs#by_lnum(bufnr('%')), {'1': [[99, 'testsign']]}

  let maker = {}
  function! maker.get_list_entries(...)
    return [{'lnum': 2, 'bufnr': bufnr('%')}]
  endfunction
  CallNeomake 1, [maker]
  AssertEqual neomake#signs#by_lnum(bufnr('%')), {
  \ '1': [[99, 'testsign']],
  \ '2': [[5000, 'neomake_file_warn']],
  \ }
  sign undefine testsign
  bwipe!