Permalink
Browse files

Fix test failures in previous commits.

Have to catch exceptions in the unit tests.

Also, I broke a parse error for array literals, so I reverted that
change.  Good thing I had tests to catch this!

Also, explore arithmetic and boolean parse errors.
  • Loading branch information...
Andy Chu
Andy Chu committed Aug 21, 2018
1 parent 7298396 commit c66042ca1e42809e2bcb62b77d1ef32859362d84
Showing with 107 additions and 38 deletions.
  1. +9 −6 core/completion.py
  2. +1 −1 osh/bool_parse.py
  3. +21 −13 osh/cmd_parse_test.py
  4. +5 −4 osh/word_parse.py
  5. +11 −5 osh/word_parse_test.py
  6. +60 −9 test/parse-errors.sh
View
@@ -434,7 +434,15 @@ def _GetCompletionType(w_parser, c_parser, ev, status_out):
TODO: what about hash table name?
"""
node = c_parser.ParseCommandLine()
# TODO: Fill these in
comp_type = completion_state_e.FIRST
prefix = ''
words = []
try:
node = c_parser.ParseCommandLine()
except util.ParseError as e:
return comp_type, prefix, words # EARLY RETURN
# Inspect state after parsing. Hm I'm getting the newline. Can I view the
# one before that?
@@ -502,11 +510,6 @@ def _GetCompletionType(w_parser, c_parser, ev, status_out):
# This one can be multiple lines
status_out.Write(6, 'com_node: %s', repr(com_node) if com_node else '<None>')
# TODO: Fill these in
comp_type = completion_state_e.FIRST
prefix = ''
words = []
# IMPORTANT: if the last token is Id.Ignored_Space, then we want to add a
# dummy word! empty word
View
@@ -126,7 +126,7 @@ def Parse(self):
node = self.ParseExpr()
if self.op_id != Id.Lit_DRightBracket:
self.AddErrorContext("Unexpected extra word %r", self.cur_word,
word=self.cur_word)
word=self.cur_word)
return None
return node
View
@@ -6,12 +6,11 @@
import sys
import unittest
from core import ui
from osh.meta import Id
from core import word
from core import test_lib
from osh.meta import ast
from core import word
from core import ui
from core import util
from osh.meta import ast, Id
from osh import ast_lib
from osh import parse_lib
from osh.cmd_parse import CommandParser # module under test
@@ -50,15 +49,24 @@ def _assertParseMethod(test, code_str, method, expect_success=True):
def _assertParseCommandListError(test, code_str):
arena, c_parser = InitCommandParser(code_str)
node = c_parser.ParseCommandLine()
if node:
print('UNEXPECTED:')
ast_lib.PrettyPrint(node)
test.fail("Expected %r to fail" % code_str)
try:
node = c_parser.ParseCommandLine()
except util.ParseError as e:
print(e)
return
# TODO: Don't check two kinds of failures!
if not node:
err = c_parser.Error()
#print(err)
ui.PrintErrorStack(err, arena, sys.stdout)
return
err = c_parser.Error()
#print(err)
ui.PrintErrorStack(err, arena, sys.stdout)
print('UNEXPECTED:')
ast_lib.PrettyPrint(node)
test.fail("Expected %r to fail" % code_str)
return
#
View
@@ -825,8 +825,8 @@ def _ReadArithSub2Part(self):
return None
if self.token_type != Id.Arith_RBracket:
self.AddErrorContext("Expected ], got %s", self.cur_token)
return None
p_die('Expected ], got %r', self.cur_token.val, token=self.cur_token)
right_span_id = self.cur_token.span_id
node = ast.ArithSubPart(anode)
@@ -923,8 +923,9 @@ def ReadForExpression(self):
def _ReadArrayLiteralPart(self):
self._Next(lex_mode_e.OUTER) # advance past (
self._Peek()
# Checked by caller
assert self.cur_token.id == Id.Op_LParen, self.cur_token
if self.cur_token.id != Id.Op_LParen:
p_die('Expected ( after =, got %r', self.cur_token.val,
token=self.cur_token)
# MUST use a new word parser (with same lexer).
w_parser = WordParser(self.lexer, self.line_reader)
View
@@ -16,6 +16,7 @@
from core import alloc
from core import test_lib
from core import word
from core import util
from osh.meta import ast, Id, types
from osh import ast_lib
@@ -79,12 +80,17 @@ def _assertSpanForWord(test, code_str):
def _assertReadWordFailure(test, word_str):
print('\n---', word_str)
w_parser = InitWordParser(word_str)
w = w_parser.ReadWord(lex_mode_e.OUTER)
if w:
ast_lib.PrettyPrint(w)
test.fail('Expected a parser error, got %r' % w)
else:
try:
w = w_parser.ReadWord(lex_mode_e.OUTER)
except util.ParseError as e:
print(e)
return
if not w:
print(w_parser.Error())
return
ast_lib.PrettyPrint(w)
test.fail('Expected a parser error, got %r' % w)
def _GetSuffixOp(test, w):
View
@@ -65,23 +65,70 @@ word-parse() {
_error-case 'echo ${#a.'
# for (( ))
_error-case 'for (( i = 0; i < 10; i++ ;'
# Hm not sure about this
_error-case 'for (( i = 0; i < 10; i++ /'
_error-case 'echo @(extglob|foo'
# Array literal with invalid TokenWord.
_error-case 'a=(1 & 2)'
_error-case 'a= (1 2)'
}
arith-context() {
set +o errexit
# $(( ))
_error-case 'echo $(( 1 + 2 ;'
_error-case 'echo $(( 1 + 2 );'
# Non-standard arith sub $[1 + 2]
_error-case 'echo $[ 1 + 2 ;'
# What's going on here? No location info?
_error-case 'echo $[ 1 + 2 /'
_error-case 'echo $[ 1 + 2 / 3'
# (( ))
_error-case '(( 1 + 2 /'
_error-case '(( 1 + 2 )/'
}
# for (( ))
_error-case 'for (( i = 0; i < 10; i++ ;'
# Hm not sure about this
_error-case 'for (( i = 0; i < 10; i++ /'
arith-expr() {
set +o errexit
_error-case 'echo @(extglob|foo'
# BUG: the token is off here
_error-case '$(( 1 + + ))'
# Array literal with invalid TokenWord.
_error-case 'a=(1 & 2)'
# BUG: not a great error either
_error-case '$(( 1 2 ))'
# Triggered a crash!
_error-case '$(( - ; ))'
}
bool-expr() {
set +o errexit
# Extra word
_error-case '[[ a b ]]'
_error-case '[[ a "a"$(echo hi)"b" ]]'
# Wrong error message
_error-case '[[ a == ]]'
# Invalid regex
_error-case '[[ $var =~ * ]]'
# Unbalanced parens
_error-case '[[ ( 1 == 2 - ]]'
_error-case '[[ == ]]'
_error-case '[[ ) ]]'
_error-case '[[ ( ]]'
}
quoted-strings() {
@@ -112,10 +159,14 @@ cases-in-strings() {
_error-case 'echo $( echo > >> )'
_error-case 'echo ${'
patsub
word-parse
patsub
quoted-strings
arith-context
arith-expr
bool-expr
}
# Cases in their own file

0 comments on commit c66042c

Please sign in to comment.