portal-ruby 0.0.2

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.
@@ -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
+