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

133 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 # var name, op, value
40 ('s', ['s', '', '']),
41 ('value', ['value', '', '']),
42 ('s!', None),
43 ('!', None),
44 ('=s', None),
45 ('s=', ['s', '=', '']),
46 ('s=val', ['s', '=', 'val']),
47 ('s=+', ['s', '=', '+']),
48 ('s+=val!', ['s', '+=', 'val!']),
49 ('s+=+', ['s', '+=', '+']),
50 ]
51
52 for s, expected in CASES:
53 actual = util.RegexSearch(word_eval.ASSIGN_ARG_RE, s)
54 if actual is None:
55 self.assertEqual(expected, actual) # no match
56 else:
57 _, var_name, _, op, value = actual
58 self.assertEqual(expected, [var_name, op, value])
59
60
61class WordEvalTest(unittest.TestCase):
62
63 def testEvalWordSequence_Errors(self):
64 CASES = [
65 'readonly a[x]=1',
66 'readonly $binding a[x]=1',
67 # There's no word elision! This will be a parse error
68 'declare $empty',
69 ]
70
71 for case in CASES:
72 print()
73 print('\t%s' % case)
74 node = assertParseSimpleCommand(self, case)
75 ev = InitEvaluator()
76 try:
77 argv = ev.EvalWordSequence2(node.words, allow_assign=True)
78 except error.FatalRuntime:
79 pass
80 else:
81 self.fail("%r should have raised ParseError", case)
82
83 def testEvalWordSequence(self):
84 node = assertParseSimpleCommand(self, 'ls foo')
85 self.assertEqual(2, len(node.words), node.words)
86 print()
87 print()
88
89 CASES = [
90 'ls [$x] $y core/a*.py',
91 'local a=1',
92
93 # What to do about these?
94 # Resolve second word then?
95 'builtin local a=1',
96 'command local a=1',
97 'typeset -"$@"',
98 # array=(b c)',
99 'local a=(1 2) "$@"', # static then dynamic
100 'readonly "$@" a=(1 2)', # dynamic then static
101 'declare -rx foo=bar spam=eggs a=(1 2)',
102 'declare $binding',
103 'declare $binding_with_spaces',
104
105 # This can be parsed, but the builtin should reject it
106 'export a=(1 2)',
107 'export A=(["k"]=v)',
108
109 # Hard test cases:
110 #
111 # command export foo=bar
112 # builtin export foo=bar
113 #
114 # b=builtin c=command e=export binding='foo=bar'
115 # $c $e $binding
116 # $b $e $binding
117 ]
118
119 for case in CASES:
120 print()
121 print('\t%s' % case)
122 node = assertParseSimpleCommand(self, case)
123 ev = InitEvaluator()
124 argv = ev.EvalWordSequence2(node.words, allow_assign=True)
125
126 print()
127 print('\tcmd_value:')
128 print(argv)
129 print()
130
131
132if __name__ == '__main__':
133 unittest.main()