portal-ruby 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,114 @@
1
+ #ifndef _PORTALR_H
2
+ #define _PORTALR_H
3
+
4
+ #include "pcm.h"
5
+ #include "pinlog.h"
6
+ #include "pin_errs.h"
7
+ #include "ruby.h"
8
+
9
+ /*
10
+ * Debug Macros
11
+ */
12
+ #ifdef _DEBUG
13
+
14
+ #define _D_ fprintf(stderr, "%s - %s:%d\n", __FUNCTION__, __FILE__, __LINE__)
15
+ #define TRACE(message) fprintf(stderr,"%s - %s:%ld %s\n", __FUNCTION__, __FILE__, __LINE__, message)
16
+ #define TRACE_FUNC(name,label,value) fprintf(stderr,"%s - %s:%ld\n %s %s %s\n", __FUNCTION__, __FILE__, __LINE__, name, label, value)
17
+ #define TRACE_INSPECT(label,obj) \
18
+ if (rb_gv_get("$DEBUG")) fprintf(stderr,"%s - %s:%ld\n %s: %s\n", __FUNCTION__, __FILE__, __LINE__, label, RSTRING(rb_funcall(obj,id_inspect,0))->ptr );
19
+
20
+ #else
21
+ #define _D_
22
+ #define TRACE(x)
23
+ #define TRACE_FUNC(name,label,value)
24
+ #define TRACE_INSPECT(label,obj)
25
+ #endif
26
+
27
+ /*
28
+ * Returns a char * using to_s
29
+ */
30
+ #define RUBY_TO_S(obj) \
31
+ ((TYPE(obj) == T_STRING) ? StringValuePtr(obj) : StringValuePtr(rb_funcall(obj, id_to_s, 0, 0)) )
32
+
33
+ /*
34
+ * Convert a Ruby value to an int
35
+ */
36
+ #define TO_INT(obj) \
37
+ ((TYPE(obj) == T_FIXNUM) ? NUM2INT(obj) : NUM2INT(rb_funcall(obj, id_to_i, 0, 0)))
38
+
39
+ #define TO_BIG(obj) \
40
+ ((TYPE(obj) == T_BIGNUM) ? NUM2DBL(obj) : NUM2DBL(rb_funcall(obj, id_to_f, 0, 0)))
41
+
42
+ /*
43
+ * Portal Data
44
+ * This data struture is created for a couple reasons. One exists in each
45
+ * instance of the Class. That is created via alloc.
46
+ *
47
+ * The Connection is instance specific.
48
+ *
49
+ * TODO: Have the connection be owned by the class in a pooled fashion such that
50
+ * an instance borrows the connection to perform an op.
51
+ */
52
+ struct pdata {
53
+ int ops;
54
+ int errors;
55
+ int in_transaction;
56
+ pcm_context_t *ctxp;
57
+ pin_flist_t *in_flistp;
58
+ pin_flist_t *out_flistp;
59
+ pin_errbuf_t ebuf;
60
+ long owner_id;
61
+ };
62
+ typedef struct pdata PortalData;
63
+
64
+ /*
65
+ * Shortcut for the following:
66
+ * pobj = Data_Make_Struct(cPortal,PortalData,0,pdata_free,pd);
67
+ */
68
+ #define PDataWrap(klass, obj, data) do { \
69
+ obj = Data_Make_Struct(klass, PortalData, 0, pdata_free, data); \
70
+ data->ctxp = NULL; \
71
+ PIN_ERR_CLEAR_ERR(&data->ebuf); \
72
+ data->ops = 0; \
73
+ data->errors = 0; \
74
+ data->in_transaction = 0; \
75
+ data->owner_id = obj; \
76
+ } while (0)
77
+
78
+ #define PDataGet(obj, datap) {\
79
+ Data_Get_Struct(obj, PortalData, datap);\
80
+ }
81
+
82
+ #define PDataClearErr(pd) PIN_ERR_CLEAR_ERR(&pd->ebuf);
83
+
84
+ /*
85
+ * Manage the conversion between hash and flist.
86
+ */
87
+ typedef struct convert_data {
88
+ pin_fld_num_t fld_num;
89
+ pin_flist_t *flistp;
90
+ pin_errbuf_t *ebufp;
91
+ } ConvertData;
92
+
93
+ #define CDataWrap(klass, obj, data) do { \
94
+ obj = Data_Make_Struct(klass, ConvertData, 0, cdata_free, data); \
95
+ } while (0)
96
+
97
+ #define CDataGet(obj, data_ptr) {\
98
+ Data_Get_Struct(obj, ConvertData, data_ptr);\
99
+ }
100
+
101
+ /*
102
+ * level is something like PIN_ERR_NOT_FOUND
103
+ * msg is written to the logfile.
104
+ */
105
+ #define PDataSetError(pd, fld, level, msg) {\
106
+ if ((!PIN_ERR_IS_ERR(pd->ebufp)) { \
107
+ pin_set_err(ebufp, PIN_ERRLOC_APP,\
108
+ PIN_ERRCLASS_SYSTEM_DETERMINATE,\
109
+ level, fld, 0, 0);\
110
+ PIN_ERR_LOG_EBUF(PIN_ERR_LEVEL_ERROR, msg, ebufp); \
111
+ }\
112
+ }
113
+
114
+ #endif
@@ -0,0 +1,47 @@
1
+ #--
2
+ # Copyright (c) 200x
3
+ #++
4
+
5
+ $:.unshift(File.dirname(__FILE__)) unless
6
+ $:.include?(File.dirname(__FILE__)) ||
7
+ $:.include?(File.expand_path(File.dirname(__FILE__)))
8
+
9
+ require 'portalext'
10
+ module Portal #:nodoc:
11
+
12
+ # Fields from pcm.h. Aquire with
13
+ # ruby -ne 'if $_ =~ /^\#define\s+(PIN_FLDT_.*)\s+(\d+)(.*)$/; puts "%-30s = %2s # %s" %[$1,$2,$3];end' pcm.h
14
+ # Reference with ::
15
+ PIN_FLDT_UNUSED = 0
16
+ PIN_FLDT_INT = 1
17
+ PIN_FLDT_UINT = 2 # /* OBSOLETE */
18
+ PIN_FLDT_ENUM = 3
19
+ PIN_FLDT_NUM = 4 # /* OBSOLETE */
20
+ PIN_FLDT_STR = 5
21
+ PIN_FLDT_BUF = 6
22
+ PIN_FLDT_POID = 7
23
+ PIN_FLDT_TSTAMP = 8
24
+ PIN_FLDT_ARRAY = 9 # /* array element */
25
+ PIN_FLDT_SUBSTRUCT = 10 # /* sub-type substructure */
26
+ PIN_FLDT_OBJ = 11 # /* whole object */
27
+ PIN_FLDT_BINSTR = 12 # /* (short) binary string data */
28
+ PIN_FLDT_ERR = 13
29
+ PIN_FLDT_DECIMAL = 14
30
+ PIN_FLDT_TIME = 15
31
+ PIN_FLDT_TEXTBUF = 16
32
+ PIN_FLDT_ERRBUF = PIN_FLDT_ERR
33
+ PIN_FLDT_LAST = 16
34
+ PIN_ERROR_LEVEL_ERROR = 1
35
+ PIN_ERROR_LEVEL_WARN = 2
36
+ PIN_ERROR_LEVEL_DEBUG = 3
37
+
38
+ end
39
+
40
+ # Requires
41
+ # eg: require 'portal/constants'
42
+
43
+ # Add all the stuff to the module
44
+ Portal.class_eval do
45
+ # include Portal::Connection
46
+ end
47
+
@@ -0,0 +1,68 @@
1
+ $server = "portal01.qa.example.com 11960"
2
+
3
+ def load_locals
4
+ load 'test/local.setup.rb' rescue nil
5
+ end
6
+
7
+ # Setup the environment for tests
8
+ case RUBY_PLATFORM
9
+ when /mswin32/
10
+ sdk = ENV["PINSDK"] || "C:/Program Files/Portal Software/PortalDevKit"
11
+ ENV["PATH"] += ";.;./lib;#{sdk}/lib"
12
+ #$:.unshift("Debug")
13
+ dir = File.dirname(__FILE__) + '/../Debug'
14
+ $:.unshift(dir) if File.exist?(dir)
15
+ else
16
+ $:.unshift("ext")
17
+ end
18
+ $:.unshift("lib")
19
+
20
+ load_locals
21
+
22
+ #File.unlink("pinlog.log") if File.exists?("pinlog.log")
23
+
24
+ class Hash
25
+ def pp(level=0)
26
+ pad = " " * level*2
27
+ max = collect{|item|item[0].to_s.size}.max
28
+ min = collect{|item|item[0].to_s.size}.min
29
+
30
+ keys.sort{|a,b|a.to_s <=> b.to_s}.each do |key|
31
+ value = self[key]
32
+ if value.class == Hash
33
+ puts "%2s %s%s =>\n"%[level,pad, key.to_s.rjust(max)]
34
+ value.pp(level+1)
35
+ else
36
+ puts "%2s %s%s => %s\n"%[level,pad, key.to_s.rjust(max),value]
37
+ end
38
+
39
+ end
40
+ end
41
+
42
+ # Cleans up the hash for before/after compares
43
+ def normalize!
44
+ each do |key,value|
45
+ value.normalize! if value.class == Hash
46
+ next if key.class == String
47
+ self.delete(key)
48
+ self[key.to_s] = value
49
+ end
50
+ end
51
+
52
+ def normalize
53
+ hash = self.dup
54
+ hash.each do |key,value|
55
+ value.normalize! if value.class == Hash
56
+ next if key.class == String
57
+ hash.delete(key)
58
+ hash[key.to_s] = value
59
+ end
60
+ end
61
+
62
+ def normalizes_to?(other)
63
+ self.normalize == other.normalize
64
+ end
65
+
66
+ end
67
+
68
+ require 'portal'
@@ -0,0 +1,10 @@
1
+ #--
2
+ # Run all the tests.
3
+ #
4
+ # Copyright (c) 200x
5
+ #++
6
+
7
+ require 'rubyunit'
8
+
9
+ Dir.chdir File.dirname( __FILE__ )
10
+ Dir["**/test_*.rb"].each { |file| load file }
@@ -0,0 +1,28 @@
1
+ # Test the conntion aspects of the project
2
+ # I run a cm_proxy on my localhost. It make the connecting a little faster.
3
+
4
+ require 'test/setup'
5
+
6
+ if __FILE__ == $0
7
+ puts "#{__FILE__}: Start."
8
+
9
+ ph = Portal::Connection.new
10
+ request = {
11
+ :PIN_FLD_POID => "0.0.0.1 /service/pcm_client 1",
12
+ :PIN_FLD_TYPE => 0,
13
+ }
14
+ points = {
15
+ 0 => { :PIN_FLD_CM_PTR => "ip #{$server}"}
16
+ }
17
+ request[:PIN_FLD_CM_PTRS] = points
18
+ puts "Connect in:\n%p\n" % [request]
19
+ out = ph.connect(request)
20
+ puts "Connect out:\n%p\n" % [out]
21
+
22
+ account = "/account 2620228098"
23
+ event = "/event 237793582760533607"
24
+ resp = ph.xop(:PCM_OP_READ_OBJ,{:PIN_FLD_POID=>"0.0.0.1 #{event}"},:return=>:flist_string)
25
+ puts "Response:\n%p\n" % [resp]
26
+
27
+ puts "#{__FILE__}: Done."
28
+ end
@@ -0,0 +1,46 @@
1
+ # Console-based tests for running from Visual Studio
2
+
3
+ require 'test/setup.rb'
4
+ require 'portal'
5
+
6
+ load 'flist.rb'
7
+
8
+ # Quick and dirty ways to pause the run untill user input
9
+ def prompt
10
+ puts "Any Key to continue"
11
+ gets
12
+ end
13
+
14
+ #
15
+ #
16
+ #
17
+ if __FILE__ == $0
18
+ puts "#{__FILE__}: Start."
19
+ #response = Portal.hash_to_flist_string(struct)
20
+ response = Portal.test_flist_to_hash struct
21
+ puts "Request: %s\n%p\nResponse:%s\n%p\n" %[struct.object_id,struct,response.object_id,response]
22
+ puts "Result: #{struct.normalize! == response.normalize! ? 'pass' : 'fail'}"
23
+ exit(1)
24
+
25
+ #1.times do
26
+ #Thread.new do
27
+ ph = Portal::Connection.new
28
+ puts "Connecting returns %p" % ph.connect(nil)
29
+ request = {:PIN_FLD_POID => "0.0.0.1 /event/billing/cycle/tax 237793582760533607"}
30
+ #response = ph.robj(request,:return=>:flist_string)
31
+
32
+ response = ph.robj("0.0.0.1 /event/billing/cycle/tax 237793582760533607")
33
+ puts "robj\n%p" % response
34
+
35
+ #puts "hash to flist string:\n%s\n" % Portal.hash_to_flist_string(response)
36
+ # p.loopback
37
+ #puts p.session
38
+ #sleep 1
39
+ #puts p.userid
40
+ #puts "%p" % p.robj(:PIN_FLD_POID => "0.0.0.1 /account 1")
41
+ #end
42
+ #end
43
+
44
+ #sleep 5
45
+ puts "#{__FILE__}: Done."
46
+ end
@@ -0,0 +1,37 @@
1
+ # Console based tests
2
+
3
+ require 'test/setup'
4
+
5
+ PIN_FLDT_STR = 5
6
+ PIN_FLDT_POID = 7
7
+
8
+ def test_one_pass
9
+ Portal.field_name(1)
10
+ end
11
+
12
+ def test_batch
13
+ 100_000.times{|i| test_one_pass }
14
+ 100_000.times{|i| test_one_pass }
15
+ 100_000.times{|i| test_one_pass }
16
+ 100_000.times{|i| test_one_pass }
17
+ end
18
+
19
+ puts "#{__FILE__}: Start."
20
+
21
+ field = :PIN_FLD_PROGRAM_NAME
22
+
23
+ puts "Any key to continue. . ."
24
+ gets
25
+
26
+ test_batch
27
+ GC.start
28
+ puts "System warmed up. Any key to continue. . ."
29
+ gets
30
+
31
+ test_batch
32
+ GC.start
33
+ puts "Note size. Any key to continue. . ."
34
+ gets
35
+
36
+
37
+ puts "#{__FILE__}: Done."
@@ -0,0 +1,173 @@
1
+ #--
2
+ # Tests for the C extension
3
+ #++
4
+
5
+ require 'test/setup'
6
+ require 'test/unit'
7
+
8
+ def prompt
9
+ puts "Any Key to continue"
10
+ gets
11
+ end
12
+ # prompt
13
+
14
+ class TestPortal < Test::Unit::TestCase
15
+ def setup
16
+ # nothing to do
17
+ end
18
+
19
+ def test_set_program_name
20
+ assert(Portal.set_program_name("A Test"))
21
+ end
22
+
23
+ def test_set_log_level
24
+ e = Portal::Error
25
+ assert_raises(e) do Portal.set_log_level(:foo) end
26
+ assert_raises(e) do Portal.set_log_level(99) end
27
+ %w(error warn debug).each do |level|
28
+ assert(Portal.set_log_level(level.upcase))
29
+ assert(Portal.set_log_level(level.to_sym))
30
+ end
31
+ assert(Portal.set_log_level(3))
32
+ end
33
+
34
+ def test_field_number
35
+ assert_equal(16, Portal.field_num("PIN_FLD_POID"))
36
+ assert_equal(16, Portal.field_num(:PIN_FLD_POID))
37
+ end
38
+
39
+ def test_field_type
40
+ assert_equal(7, Portal.field_type("PIN_FLD_POID"), "String key")
41
+ assert_equal(7, Portal.field_type(:PIN_FLD_POID), "Symbol key")
42
+ end
43
+
44
+ def test_field_name
45
+ assert_equal("PIN_FLD_ERR_BUF", Portal.field_name("1"), "Name using string")
46
+ assert_equal("PIN_FLD_ERR_BUF", Portal.field_name(1), "Name using int")
47
+ end
48
+
49
+ def test_portal_convert_str
50
+ hash = {"PIN_FLD_PROGRAM_NAME" => "string01", "PIN_FLD_NAME" => "string02"}
51
+ assert_equal(hash,Portal.test_flist_to_hash(hash))
52
+ end
53
+
54
+ # Keys are strings. Values are ints or floats for certain field types.
55
+ def create_expected_results(hash)
56
+ return hash.inject({}){|obj,memo|k,v=memo[0].to_s,memo[1].to_i;obj[k] = v;obj}
57
+ end
58
+
59
+ def ex_portal_numeric(hash)
60
+ out = create_expected_results(hash)
61
+ assert_equal(out,Portal.test_flist_to_hash(hash))
62
+ end
63
+
64
+ def test_portal_convert_enum
65
+ ex_portal_numeric({:PIN_FLD_PAY_TYPE => 10003, "PIN_FLD_DIRECTION" => "0" })
66
+ end
67
+
68
+ def test_portal_convert_int
69
+ ex_portal_numeric({"PIN_FLD_COUNT" => 1, :PIN_FLD_FLAGS => 256})
70
+ end
71
+
72
+ def test_hash_to_flist_tstamp
73
+ ex_portal_numeric({"PIN_FLD_CREATED_T" => "1", :PIN_FLD_CREATED_T => 1167900875})
74
+ end
75
+
76
+ def test_hash_to_flist_decimal
77
+ hash = {"PIN_FLD_CREDIT_LIMIT" => "1", :PIN_FLD_CREDIT_FLOOR => 8,
78
+ "PIN_FLD_CURRENT_BAL" => "1.1", :PIN_FLD_RESERVED_AMOUNT => 1.1,}
79
+ h2 = {"PIN_FLD_CREDIT_LIMIT" =>1.0,
80
+ "PIN_FLD_CURRENT_BAL" =>1.1,
81
+ "PIN_FLD_CREDIT_FLOOR" =>8.0,
82
+ "PIN_FLD_RESERVED_AMOUNT"=>1.1}
83
+ assert_passes_conversion(hash,h2)
84
+ end
85
+
86
+ def test_hash_to_flist_poid
87
+ hash = {"PIN_FLD_POID" => "0.0.0.1 /account 1 2"}
88
+ assert_passes_conversion(hash)
89
+
90
+ hash = {"PIN_FLD_POID" => "0.0.0.1 /account 1"}
91
+ good = {"PIN_FLD_POID" => "0.0.0.1 /account 1 0"}
92
+ assert_equal(good,Portal.test_flist_to_hash(hash))
93
+ end
94
+
95
+ def test_hash_to_flist_struct
96
+ hash = {
97
+ "PIN_FLD_NAME" => "Foo",
98
+ :PIN_FLD_EVENT => {
99
+ 0 => {
100
+ :PIN_FLD_AAC_SERIAL_NUM => "AAC_SERIAL_NUM"
101
+ },
102
+ },
103
+ }
104
+ assert_passes_conversion(hash)
105
+ end
106
+
107
+ # Optionally suppply an expected hash
108
+ def assert_passes_conversion(request,expected=nil)
109
+ resp = Portal.test_flist_to_hash(request)
110
+ #return assert(request.normalizes_to?(expected||resp))
111
+ n1 = expected || request.normalize
112
+ n2 = resp.normalize
113
+ if n1 != n2
114
+ puts "#{n1.inspect}"
115
+ puts "#{n2.inspect}"
116
+ assert(false)
117
+ else
118
+ assert(true)
119
+ end
120
+ end
121
+
122
+ # Test the conversion of Arrays
123
+ def test_hash_to_flist_z_array
124
+ hash = {
125
+ "PIN_FLD_NAME" => "Foo",
126
+ :PIN_FLD_ARGS => {
127
+ 1 => { "PIN_FLD_NAME" => "Furry Giant" },
128
+ 2 => {
129
+ :PIN_FLD_NAME => "Name 1",
130
+ :PIN_FLD_CREATED_T => 1,
131
+ },
132
+ 3 => {
133
+ :PIN_FLD_NAME => "Value 2",
134
+ :PIN_FLD_CREATED_T => 2,
135
+ },
136
+ },
137
+ }
138
+
139
+ #hash.pp
140
+ #puts "*" * 60
141
+ assert(resp = Portal.test_flist_to_hash(hash))
142
+ #resp.pp
143
+ end
144
+
145
+ def xtest_connect
146
+ p = Portal::Connection.new
147
+ assert(p.connect(nil))
148
+ end
149
+
150
+ end
151
+
152
+ def complex_request
153
+ {
154
+ :PIN_FLD_POID => "0.0.0.1 /payinfo/cc -1 0",
155
+ :PIN_FLD_FLAGS => 1,
156
+ :PIN_FLD_AUTHORIZATION_ID =>"perf-8391558241",
157
+ :PIN_FLD_TRANS_ID => "9880325991174598486930",
158
+ :PIN_FLD_PAYINFO_OBJ => nil,
159
+ :PIN_FLD_CC_INFO => {
160
+ "*" => {
161
+ :PIN_FLD_ADDRESS => "111 1st AVE S",
162
+ :PIN_FLD_CITY => "Renton",
163
+ :PIN_FLD_COUNTRY => "US",
164
+ :PIN_FLD_DEBIT_EXP => "10/01/2008" ,
165
+ :PIN_FLD_DEBIT_NUM => "4111111111111111" ,
166
+ :PIN_FLD_NAME => "Cary::Sheen",
167
+ :PIN_FLD_STATE => "WA",
168
+ :PIN_FLD_ZIP => "98057",
169
+ }
170
+ }
171
+ }
172
+ end
173
+