fluent-plugin-simplearithmetic 0.0.1.pre → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +69 -11
- data/fluent-plugin-simplearithmetic.gemspec +1 -1
- data/lib/fluent/plugin/out_simple_arithmetic.rb +33 -3
- data/test/helper.rb +1 -1
- data/test/plugin/test_out_simple_arithmetic.rb +216 -0
- metadata +6 -6
- data/test/plugin/test_out_simplearithmetic.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9896bc5f77125536a6e6efec0c519947c8b8c487
|
4
|
+
data.tar.gz: 0416741cba7d514ed3bdaf97f063ad03a3d87f33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f18b7a4f4f43996d715a41231946bf83eecf67a2af69d096e82a5f72d60a7e0946c62a9a3c88482fc635b3dbd57d0905f95ba3718fdf6d35c89a2d7e4089ed7
|
7
|
+
data.tar.gz: 2574ec4b858814077aa20b9ceb44a4d8f95588fc233ee661229495035394aec602132399e88e2cc35446071eec68ead80be5151540a34d2beb1070a044646f0f
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ Suppose you have a message like:
|
|
24
24
|
}
|
25
25
|
```
|
26
26
|
|
27
|
-
Now you can calculate with this
|
27
|
+
Now you can calculate with this configuration:
|
28
28
|
|
29
29
|
```
|
30
30
|
<match arithmetic.test>
|
@@ -32,7 +32,7 @@ Now you can calculate with this `td-agent.conf`:
|
|
32
32
|
tag calculated.test
|
33
33
|
|
34
34
|
<formulas>
|
35
|
-
total_price apple * 200
|
35
|
+
total_price apple * 200 + orange * 100
|
36
36
|
|
37
37
|
# Calculation order is from up to down.
|
38
38
|
budget 2000 - total_price
|
@@ -55,31 +55,89 @@ Calculated results will be:
|
|
55
55
|
"orange": 3,
|
56
56
|
"time_start": "2001-02-03T04:05:06Z",
|
57
57
|
"time_finish": "2001-02-03T04:06:12Z",
|
58
|
-
"total_price":
|
59
|
-
"budget":
|
58
|
+
"total_price": 1700,
|
59
|
+
"budget": 300,
|
60
60
|
"time_elapsed": 66.0
|
61
61
|
}
|
62
62
|
```
|
63
63
|
|
64
|
+
If some fields are already defined before calculation, these fields will be overwritten.
|
65
|
+
|
64
66
|
|
65
67
|
## Configuration
|
66
68
|
|
69
|
+
### tag
|
70
|
+
The tag prefix for emitted event messages. Default is `simple_arithmetic`.
|
67
71
|
|
68
72
|
### undefined_variables
|
69
|
-
1. `nil`
|
70
73
|
|
71
|
-
|
74
|
+
A message such like `{'a': 20, 'x': 50}` with the formulas:
|
75
|
+
|
76
|
+
```
|
77
|
+
<formulas>
|
78
|
+
c a + b
|
79
|
+
</formulas>
|
80
|
+
```
|
81
|
+
|
82
|
+
When undefined_variables is `undefined` (default) you get `{'a': 20, 'x': 50}`. Field `'c'` will not be defined.
|
83
|
+
|
84
|
+
When `nil` you get `{'a': 20, 'c': nil, 'x': 50}`.
|
85
|
+
|
72
86
|
|
73
87
|
### how_to_process_error
|
74
|
-
1. `nil`
|
75
88
|
|
76
|
-
|
89
|
+
A message such like `{'a': 20, 'b': "string"}` with the formulas:
|
77
90
|
|
78
|
-
|
91
|
+
```
|
92
|
+
<formulas>
|
93
|
+
c a + b
|
94
|
+
</formulas>
|
95
|
+
```
|
79
96
|
|
97
|
+
In ruby, this calculation will be raise an error:
|
80
98
|
|
81
|
-
|
82
|
-
|
99
|
+
```
|
100
|
+
irb(main):052:0* a = 20
|
101
|
+
=> 20
|
102
|
+
irb(main):053:0> b = "String"
|
103
|
+
=> "String"
|
104
|
+
irb(main):054:0> c = a + b
|
105
|
+
TypeError: String can't be coerced into Fixnum
|
106
|
+
from (irb):54:in `+'
|
107
|
+
from (irb):54
|
108
|
+
from /opt/td-agent/embedded/bin/irb:11:in `<main>'
|
109
|
+
```
|
110
|
+
|
111
|
+
When how_to_process_error is `nil` you get `{'a': 20, 'b': "string", 'c': nil}`.
|
112
|
+
|
113
|
+
When `undefined`, you get `{'a': 20, 'b': "string"}`. If an error is raised in the calculation, the field will not be defined.
|
114
|
+
|
115
|
+
When `error_string` (default), you get: `{'a': 20, 'b': "String", 'c'=>"String can't be coerced into Fixnum"}`. An error message will be assigned to the field.
|
116
|
+
|
117
|
+
### replace_hyphen, replace_dollar
|
118
|
+
|
119
|
+
All formulas will be evaluated as ruby sentences. Some json fields will not be fitted as ruby variables. For example,
|
120
|
+
|
121
|
+
```
|
122
|
+
<formulas>
|
123
|
+
var-1 a + b
|
124
|
+
var$2 c * d
|
125
|
+
</formulas>
|
126
|
+
```
|
127
|
+
|
128
|
+
will raise an syntax error in the initialize process of fluentd.
|
129
|
+
|
130
|
+
To get rid of this case, you can set `replace_hyphen` and `replace_dollar` in the configuration and formulas.
|
131
|
+
|
132
|
+
```
|
133
|
+
replace_hyphen __H__
|
134
|
+
replace_dollar __D__
|
135
|
+
|
136
|
+
<formulas>
|
137
|
+
var__H__1 a + b
|
138
|
+
var__D__2 c * d
|
139
|
+
</formulas>
|
140
|
+
```
|
83
141
|
|
84
142
|
|
85
143
|
## Copyright
|
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |spec|
|
5
5
|
spec.name = "fluent-plugin-simplearithmetic"
|
6
|
-
spec.version = "0.0.1
|
6
|
+
spec.version = "0.0.1"
|
7
7
|
spec.authors = ["Takahiro Kamatani"]
|
8
8
|
spec.email = ["buhii314@gmail.com"]
|
9
9
|
spec.description = %q{Fluent plugin to calculate messages.}
|
@@ -11,6 +11,9 @@ module Fluent
|
|
11
11
|
# 'nil', 'undefined', 'error_string'
|
12
12
|
config_param :how_to_process_error, :string, :default => 'error_string'
|
13
13
|
|
14
|
+
config_param :replace_hyphen, :string, :default => '__HYPHON__'
|
15
|
+
config_param :replace_dollar, :string, :default => '__DOLLAR__'
|
16
|
+
|
14
17
|
attr_accessor :_formulas
|
15
18
|
|
16
19
|
def initialize
|
@@ -41,10 +44,9 @@ module Fluent
|
|
41
44
|
|
42
45
|
# Create functions
|
43
46
|
@_formulas = []
|
44
|
-
|
45
47
|
def create_func(var, expr)
|
46
48
|
begin
|
47
|
-
f_argv = expr.scan(/[a-zA-Z][\w\d
|
49
|
+
f_argv = expr.scan(/[a-zA-Z\_][\w\d\.\_]*/).uniq.select{|x| not x.start_with?('Time.iso8601')}
|
48
50
|
f = eval('lambda {|' + f_argv.join(',') + '| ' + expr + '}')
|
49
51
|
return [f, f_argv]
|
50
52
|
rescue SyntaxError
|
@@ -61,6 +63,10 @@ module Fluent
|
|
61
63
|
@_formulas.push [var, f_argv, formula]
|
62
64
|
}
|
63
65
|
}
|
66
|
+
if @_formulas.empty?
|
67
|
+
raise Fluent::ConfigError, "No formulas found"
|
68
|
+
end
|
69
|
+
|
64
70
|
end
|
65
71
|
|
66
72
|
def has_all_keys?(record, argv)
|
@@ -80,7 +86,30 @@ module Fluent
|
|
80
86
|
return formula.call(*argv)
|
81
87
|
end
|
82
88
|
|
89
|
+
# functions for symbols
|
90
|
+
def replace_symbols(record)
|
91
|
+
# 'var-1' -> 'var__HYPHEN__1'
|
92
|
+
new_record = {}
|
93
|
+
record.each_pair {|key, value|
|
94
|
+
new_key = key.gsub('-', @replace_hyphen).gsub('$', @replace_dollar)
|
95
|
+
new_record[new_key] = value
|
96
|
+
}
|
97
|
+
return new_record
|
98
|
+
end
|
99
|
+
|
100
|
+
def restore_symbols(record)
|
101
|
+
# 'var__HYPHEN__1' -> 'var-1'
|
102
|
+
new_record = {}
|
103
|
+
record.each_pair {|key, value|
|
104
|
+
new_key = key.gsub(@replace_hyphen, '-').gsub(@replace_dollar, '$')
|
105
|
+
new_record[new_key] = value
|
106
|
+
}
|
107
|
+
new_record
|
108
|
+
end
|
109
|
+
|
83
110
|
def calculate(record)
|
111
|
+
record = replace_symbols(record)
|
112
|
+
|
84
113
|
@_formulas.each {|var, f_argv, formula|
|
85
114
|
if not has_all_keys?(record, f_argv)
|
86
115
|
if @undefined_variables == 'nil'
|
@@ -100,7 +129,8 @@ module Fluent
|
|
100
129
|
end
|
101
130
|
end
|
102
131
|
}
|
103
|
-
|
132
|
+
|
133
|
+
restore_symbols(record)
|
104
134
|
end
|
105
135
|
|
106
136
|
def emit(tag, es, chain)
|
data/test/helper.rb
CHANGED
@@ -0,0 +1,216 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class SimpleArithmeticOutputTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Fluent::Test.setup
|
7
|
+
end
|
8
|
+
|
9
|
+
CONFIG = %[
|
10
|
+
type simple_arithmetic
|
11
|
+
tag calculated.test
|
12
|
+
undefined_variables nil
|
13
|
+
how_to_process_error error_string
|
14
|
+
|
15
|
+
<formulas>
|
16
|
+
x3 x1 * 100 - x2
|
17
|
+
var1 Time.iso8601(t1) - Time.iso8601(t2)
|
18
|
+
var2 x3 - var1
|
19
|
+
</formulas>
|
20
|
+
]
|
21
|
+
|
22
|
+
def create_driver(conf = CONFIG, tag='test.input')
|
23
|
+
Fluent::Test::OutputTestDriver.new(Fluent::SimpleArithmeticOutput, tag).configure(conf)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_configure
|
27
|
+
# No formulas
|
28
|
+
assert_raise(Fluent::ConfigError) {
|
29
|
+
d = create_driver('')
|
30
|
+
}
|
31
|
+
# No formulas
|
32
|
+
assert_raise(Fluent::ConfigError) {
|
33
|
+
d = create_driver %[
|
34
|
+
<formulas>
|
35
|
+
|
36
|
+
</formulas>
|
37
|
+
]
|
38
|
+
}
|
39
|
+
# Syntax error
|
40
|
+
assert_raise(Fluent::ConfigError) {
|
41
|
+
d = create_driver %[
|
42
|
+
<formulas>
|
43
|
+
var1 var2 * var3 +
|
44
|
+
</formulas>
|
45
|
+
]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_replace_functions
|
50
|
+
d1 = create_driver %[
|
51
|
+
replace_hyphen __H__
|
52
|
+
replace_dollar __D__
|
53
|
+
<formulas>
|
54
|
+
var__H__1 __H__2 * var__D__3
|
55
|
+
__D__3 __D__1 + __D__2
|
56
|
+
</formulas>
|
57
|
+
]
|
58
|
+
assert_equal '__H__', d1.instance.replace_hyphen
|
59
|
+
assert_equal '__D__', d1.instance.replace_dollar
|
60
|
+
d1.run do
|
61
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
62
|
+
d1.emit({'-2'=>10, 'var$3'=>20}, time)
|
63
|
+
d1.emit({'$1'=>10, '$2'=>20}, time)
|
64
|
+
end
|
65
|
+
assert_equal d1.emits[0][2], {"-2"=>10, "var$3"=>20, "var-1"=>200}
|
66
|
+
assert_equal d1.emits[1][2], {"$1"=>10, "$2"=>20, "$3"=>30}
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_undefined_variables
|
70
|
+
# undefined_variables must be either `nil` or `undefined`
|
71
|
+
assert_raise(Fluent::ConfigError) {
|
72
|
+
d = create_driver %[
|
73
|
+
undefined_variables non_existent_config
|
74
|
+
<formulas>
|
75
|
+
a b + c
|
76
|
+
</formulas>
|
77
|
+
]
|
78
|
+
}
|
79
|
+
|
80
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
81
|
+
|
82
|
+
# nil
|
83
|
+
d1 = create_driver %[
|
84
|
+
undefined_variables nil
|
85
|
+
<formulas>
|
86
|
+
a b + c
|
87
|
+
</formulas>
|
88
|
+
]
|
89
|
+
d1.run do
|
90
|
+
d1.emit({'b'=>10, 'c'=>20}, time)
|
91
|
+
d1.emit({'b'=>10, 'non-related'=>100}, time)
|
92
|
+
end
|
93
|
+
assert_equal d1.emits[0][2], {'a'=>30, 'b'=>10, 'c'=>20}
|
94
|
+
assert_equal d1.emits[1][2], {'a'=>nil, 'b'=>10, 'non-related'=>100}
|
95
|
+
|
96
|
+
# undefined
|
97
|
+
d2 = create_driver %[
|
98
|
+
undefined_variables undefined
|
99
|
+
<formulas>
|
100
|
+
a b + c
|
101
|
+
</formulas>
|
102
|
+
]
|
103
|
+
d2.run do
|
104
|
+
d2.emit({'b'=>10, 'c'=>20}, time)
|
105
|
+
d2.emit({'b'=>10, 'non-related'=>100}, time)
|
106
|
+
end
|
107
|
+
assert_equal d2.emits[0][2], {'a'=>30, 'b'=>10, 'c'=>20}
|
108
|
+
assert_equal d2.emits[1][2], {'b'=>10, 'non-related'=>100}
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_how_to_process_error
|
112
|
+
# undefined_variables must be either `nil` or `undefined`, `error_string`
|
113
|
+
assert_raise(Fluent::ConfigError) {
|
114
|
+
d = create_driver %[
|
115
|
+
how_to_process_error non_existent_config
|
116
|
+
<formulas>
|
117
|
+
a b + c
|
118
|
+
</formulas>
|
119
|
+
]
|
120
|
+
}
|
121
|
+
|
122
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
123
|
+
|
124
|
+
# nil
|
125
|
+
d1 = create_driver %[
|
126
|
+
how_to_process_error nil
|
127
|
+
<formulas>
|
128
|
+
a b + c
|
129
|
+
</formulas>
|
130
|
+
]
|
131
|
+
d1.run do
|
132
|
+
d1.emit({'b'=>10, 'c'=>20}, time)
|
133
|
+
d1.emit({'b'=>10, 'c'=>'string'}, time)
|
134
|
+
end
|
135
|
+
assert_equal d1.emits[0][2], {'a'=>30, 'b'=>10, 'c'=>20}
|
136
|
+
assert_equal d1.emits[1][2], {'a'=>nil, 'b'=>10, 'c'=>'string'}
|
137
|
+
|
138
|
+
# undefined
|
139
|
+
d2 = create_driver %[
|
140
|
+
how_to_process_error undefined
|
141
|
+
<formulas>
|
142
|
+
a b + c
|
143
|
+
</formulas>
|
144
|
+
]
|
145
|
+
d2.run do
|
146
|
+
d2.emit({'b'=>10, 'c'=>20}, time)
|
147
|
+
d2.emit({'b'=>10, 'c'=>'string'}, time)
|
148
|
+
end
|
149
|
+
assert_equal d2.emits[0][2], {'a'=>30, 'b'=>10, 'c'=>20}
|
150
|
+
assert_equal d2.emits[1][2], {'b'=>10, 'c'=>'string'}
|
151
|
+
|
152
|
+
# error_string
|
153
|
+
d3 = create_driver %[
|
154
|
+
how_to_process_error error_string
|
155
|
+
<formulas>
|
156
|
+
a b + c
|
157
|
+
</formulas>
|
158
|
+
]
|
159
|
+
d3.run do
|
160
|
+
d3.emit({'b'=>10, 'c'=>20}, time)
|
161
|
+
d3.emit({'b'=>10, 'c'=>'string'}, time)
|
162
|
+
end
|
163
|
+
assert_equal d3.emits[0][2], {'a'=>30, 'b'=>10, 'c'=>20}
|
164
|
+
assert_equal d3.emits[1][2], {'a'=>"String can't be coerced into Fixnum",
|
165
|
+
'b'=>10, 'c'=>'string'}
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_plus_num_and_string
|
169
|
+
def calculated(record)
|
170
|
+
record['a'] = record['b'] + record['c']
|
171
|
+
record
|
172
|
+
end
|
173
|
+
data = [
|
174
|
+
{'b'=>10, 'c'=>20},
|
175
|
+
{'b'=>'Dr. Strangelove or: ',
|
176
|
+
'c'=>'How I Learned to Stop Worrying and Love the Bomb'},
|
177
|
+
]
|
178
|
+
|
179
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
180
|
+
|
181
|
+
d = create_driver %[
|
182
|
+
<formulas>
|
183
|
+
a b + c
|
184
|
+
</formulas>
|
185
|
+
]
|
186
|
+
d.run do
|
187
|
+
data.each {|record|
|
188
|
+
d.emit(record, time)
|
189
|
+
}
|
190
|
+
end
|
191
|
+
data.each_with_index {|record, index|
|
192
|
+
assert_equal d.emits[index][2], calculated(data[index])
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_iso8601
|
197
|
+
d = create_driver %[
|
198
|
+
<formulas>
|
199
|
+
time_diff Time.iso8601(time_finish) - Time.iso8601(time_start)
|
200
|
+
</formulas>
|
201
|
+
]
|
202
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
203
|
+
d.run do
|
204
|
+
d.emit(
|
205
|
+
{
|
206
|
+
'time_start' => '2001-02-03T04:05:06Z',
|
207
|
+
'time_finish' => '2001-02-03T04:06:12Z',
|
208
|
+
}, time)
|
209
|
+
end
|
210
|
+
assert_equal d.emits[0][2], {
|
211
|
+
'time_start' => '2001-02-03T04:05:06Z',
|
212
|
+
'time_finish'=> '2001-02-03T04:06:12Z',
|
213
|
+
'time_diff'=> 66.0}
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-simplearithmetic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takahiro Kamatani
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -53,7 +53,7 @@ files:
|
|
53
53
|
- fluent-plugin-simplearithmetic.gemspec
|
54
54
|
- lib/fluent/plugin/out_simple_arithmetic.rb
|
55
55
|
- test/helper.rb
|
56
|
-
- test/plugin/
|
56
|
+
- test/plugin/test_out_simple_arithmetic.rb
|
57
57
|
homepage: https://github.com/buhii/fluent-plugin-simplearithmetic
|
58
58
|
licenses:
|
59
59
|
- Apache License, Version 2.0
|
@@ -69,9 +69,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
69
|
version: '0'
|
70
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- - "
|
72
|
+
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
74
|
+
version: '0'
|
75
75
|
requirements: []
|
76
76
|
rubyforge_project:
|
77
77
|
rubygems_version: 2.2.2
|
@@ -80,4 +80,4 @@ specification_version: 4
|
|
80
80
|
summary: Fluent plugin to calculate messages.
|
81
81
|
test_files:
|
82
82
|
- test/helper.rb
|
83
|
-
- test/plugin/
|
83
|
+
- test/plugin/test_out_simple_arithmetic.rb
|
@@ -1,60 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
require 'helper'
|
3
|
-
|
4
|
-
class SimpleArithmeticOutputTest < Test::Unit::TestCase
|
5
|
-
def setup
|
6
|
-
Fluent::Test.setup
|
7
|
-
end
|
8
|
-
|
9
|
-
CONFIG = %[
|
10
|
-
type simple_arithmetic
|
11
|
-
tag calculated.test
|
12
|
-
undefined_variables nil # nil, undefined
|
13
|
-
how_to_process_error error_string # nil, undefined, error_string
|
14
|
-
|
15
|
-
<formulas>
|
16
|
-
x3 x1 * 100 - x2
|
17
|
-
var1 Time.iso8601(t1) - Time.iso8601(t2)
|
18
|
-
var2 x3 - var1
|
19
|
-
</formulas>
|
20
|
-
]
|
21
|
-
|
22
|
-
def create_driver(conf = CONFIG, tag='test.input')
|
23
|
-
Fluent::Test::OutputTestDriver.new(Fluent::SimpleArithmeticOutput, tag).configure(conf)
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_configure
|
27
|
-
assert_raise(Fluent::ConfigError) {
|
28
|
-
d = create_driver('')
|
29
|
-
}
|
30
|
-
# no variables for calculation
|
31
|
-
assert_raise(Fluent::ConfigError) {
|
32
|
-
d = create_driver %[
|
33
|
-
<formulas>
|
34
|
-
|
35
|
-
</formulas>
|
36
|
-
]
|
37
|
-
}
|
38
|
-
# Syntax Error
|
39
|
-
assert_raise(Fluent::ConfigError) {
|
40
|
-
d = create_driver %[
|
41
|
-
<formulas>
|
42
|
-
var_undefined
|
43
|
-
</formulas>
|
44
|
-
]
|
45
|
-
}
|
46
|
-
d = create_driver %[
|
47
|
-
<formulas>
|
48
|
-
var1 var2 * var3
|
49
|
-
</formulas>
|
50
|
-
]
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_create_formula
|
54
|
-
d = create_driver
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_write
|
58
|
-
d = create_driver
|
59
|
-
end
|
60
|
-
end
|