OILS / osh / word_eval_test.py View on Github | oilshell.org

132 lines, 87 significant
1#!/usr/bin/env python2
2# Copyright 2016 Andy Chu. All rights reserved.
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8"""
9word_eval_test.py: Tests for word_eval.py
10"""
11from __future__ import print_function
12
13import unittest
14
15from core import error
16from core import test_lib
17from core import util
18from osh import word_eval
19from osh.cmd_parse_test import assertParseSimpleCommand
20
21
22def InitEvaluator():
23 word_ev = test_lib.InitWordEvaluator()
24 test_lib.SetLocalString(word_ev.mem, 'x', '- -- ---')
25 test_lib.SetLocalString(word_ev.mem, 'y', 'y yy')
26 test_lib.SetLocalString(word_ev.mem, 'empty', '')
27 test_lib.SetLocalString(word_ev.mem, 'binding', 'spam=eggs')
28 test_lib.SetLocalString(word_ev.mem, 'binding_with_spaces',
29 'x=green eggs and ham')
30
31 word_ev.mem.SetArgv(['x', 'foo', 'spam=eggs'])
32 return word_ev
33
34
35class RegexTest(unittest.TestCase):
36
37 def testSplitAssignArg(self):
38 CASES = [
39 ('s', ['s', None, None]),
40 ('value', ['value', None, None]),
41 ('s!', None),
42 ('!', None),
43 ('=s', None),
44 ('s=', ['s', '=', '']),
45 ('s=val', ['s', '=', 'val']),
46 ('s=+', ['s', '=', '+']),
47 ('s+=val!', ['s', '+=', 'val!']),
48 ('s+=+', ['s', '+=', '+']),
49 ]
50
51 for s, expected in CASES:
52 actual = util.simple_regex_search(word_eval.ASSIGN_ARG_RE, s)
53 if actual is None:
54 self.assertEqual(expected, actual) # no match
55 else:
56 _, var_name, _, op, value = actual
57 self.assertEqual(expected, [var_name, op, value])
58
59
60class WordEvalTest(unittest.TestCase):
61
62 def testEvalWordSequence_Errors(self):
63 CASES = [
64 'readonly a[x]=1',
65 'readonly $binding a[x]=1',
66 # There's no word elision! This will be a parse error
67 'declare $empty',
68 ]
69
70 for case in CASES:
71 print()
72 print('\t%s' % case)
73 node = assertParseSimpleCommand(self, case)
74 ev = InitEvaluator()
75 try:
76 argv = ev.EvalWordSequence2(node.words, allow_assign=True)
77 except error.FatalRuntime:
78 pass
79 else:
80 self.fail("%r should have raised ParseError", case)
81
82 def testEvalWordSequence(self):
83 node = assertParseSimpleCommand(self, 'ls foo')
84 self.assertEqual(2, len(node.words), node.words)
85 print()
86 print()
87
88 CASES = [
89 'ls [$x] $y core/a*.py',
90 'local a=1',
91
92 # What to do about these?
93 # Resolve second word then?
94 'builtin local a=1',
95 'command local a=1',
96 'typeset -"$@"',
97 # array=(b c)',
98 'local a=(1 2) "$@"', # static then dynamic
99 'readonly "$@" a=(1 2)', # dynamic then static
100 'declare -rx foo=bar spam=eggs a=(1 2)',
101 'declare $binding',
102 'declare $binding_with_spaces',
103
104 # This can be parsed, but the builtin should reject it
105 'export a=(1 2)',
106 'export A=(["k"]=v)',
107
108 # Hard test cases:
109 #
110 # command export foo=bar
111 # builtin export foo=bar
112 #
113 # b=builtin c=command e=export binding='foo=bar'
114 # $c $e $binding
115 # $b $e $binding
116 ]
117
118 for case in CASES:
119 print()
120 print('\t%s' % case)
121 node = assertParseSimpleCommand(self, case)
122 ev = InitEvaluator()
123 argv = ev.EvalWordSequence2(node.words, allow_assign=True)
124
125 print()
126 print('\tcmd_value:')
127 print(argv)
128 print()
129
130
131if __name__ == '__main__':
132 unittest.main()