Skip to content

Commit

Permalink
Make changes to pass handle in python
Browse files Browse the repository at this point in the history
Make changes to pass handle in python

Signed-off-by: Elijah Swift <elijah.swift@ibm.com>
  • Loading branch information
ElijahSwiftIBM committed Feb 29, 2024
1 parent dd23a06 commit ac0bf6a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 48 deletions.
35 changes: 19 additions & 16 deletions pyracf/common/irrsmo00.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,52 +20,56 @@ static PyObject *call_irrsmo00(PyObject *self, PyObject *args, PyObject *kwargs)
const unsigned int request_xml_length;
const unsigned int result_buffer_size;
const unsigned int irrsmo00_options;
const char request_handle[64] = {0};
const char *running_userid;
const uint8_t running_userid_length;

static char *kwlist[] = {
"request_xml",
"request_xml_length",
"request_xml_len",
"result_buffer_size",
"irrsmo00_options",
"handle",
"running_userid",
"running_userid_length",
"running_userid_len",
NULL};

if (
!PyArg_ParseTupleAndKeywords(
args,
kwargs,
"y|IIIyb",
"yIII|w*yb",
kwlist,
&request_xml,
&request_xml_length,
&result_buffer_size,
&irrsmo00_options,
&request_handle,
&running_userid,
&running_userid_length))
{
return NULL;
}

PyObject * full_result;
char work_area[1024];
char req_handle[64] = {0};
running_userid_t running_userid_struct = {running_userid_length, {0}};
unsigned int alet = 0;
unsigned int acee = 0;
unsigned char result_buffer[result_buffer_size];
unsigned char * result_buffer = malloc(result_buffer_size);
memset(result_buffer, 0, result_buffer_size);
unsigned int saf_rc = 0;
unsigned int racf_rc = 0;
unsigned int racf_rsn = 0;
unsigned int result_len = result_buffer_size;
unsigned int num_parms = 17;
unsigned int fn = 1;
unsigned int fn = 1;

strncpy(
running_userid_struct.running_userid,
running_userid,
running_userid_struct.running_userid_length);

IRRSMO64(
work_area,
alet,
Expand All @@ -79,12 +83,13 @@ static PyObject *call_irrsmo00(PyObject *self, PyObject *args, PyObject *kwargs)
irrsmo00_options,
request_xml_length,
request_xml,
req_handle,
request_handle,
running_userid_struct,
acee,
result_buffer_size,
&result_len,
result_buffer);


// https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
//
// According to the Python 3 C API documentation:
Expand Down Expand Up @@ -122,12 +127,10 @@ static PyObject *call_irrsmo00(PyObject *self, PyObject *args, PyObject *kwargs)
// Py_BuildValue() will return a Tuple.

return Py_BuildValue(
"y#BBB",
result_buffer,
result_buffer_size,
saf_rc,
racf_rc,
racf_rsn);
"{s:y#,s:[B,B,B],s:w*}",
"resultBuffer", result_buffer, result_len,
"returnCodes", saf_rc, racf_rc, racf_rsn,
"handle", request_handle);
}

static char call_irrsmo00_docs[] =
Expand All @@ -138,7 +141,7 @@ static char call_irrsmo00_docs[] =
" irrsmo00_options: uint,\n"
" running_userid: bytes,\n"
" running_userid_length: uint,\n"
") -> List[bytes,int,int,int]:\n"
") -> Dict{ resultBuffers: List[bytes], returnCodes: List[int,int,int] }:\n"
"# Returns an XML result string and return and reason "
"codes from the IRRSMO00 RACF Callable Service.\n";

Expand Down
26 changes: 21 additions & 5 deletions pyracf/common/irrsmo00.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,34 @@ def call_racf(
running_userid = run_as_userid.encode("cp1047")
result = call_irrsmo00(
request_xml=request_xml,
request_xml_length=len(request_xml),
request_xml_len=len(request_xml),
result_buffer_size=self.__result_buffer_size,
irrsmo00_options=irrsmo00_options,
running_userid=running_userid,
running_userid_length=len(running_userid),
running_userid_len=len(running_userid),
)
if (
(result["returnCodes"][0] == 8)
and (result["returnCodes"][1] == 4000)
and (result["returnCodes"][2] < 100000000)
):
print(result)
result = call_irrsmo00(
request_xml=request_xml,
request_xml_len=len(request_xml),
result_buffer_size=result["returnCodes"][2],
irrsmo00_options=irrsmo00_options,
running_userid=running_userid,
running_userid_len=len(running_userid),
handle=result["handle"],
)
print(result)
# Preserve raw result XML just in case we need to create a dump.
# If the decoded result XML cannot be parsed with the XML parser,
# a dump may need to be taken to aid in problem determination.
self.__raw_result_xml = result[0]
self.__raw_result_xml = result["resultBuffer"]
# Replace any null bytes in the result XML with spaces.
result_xml = self.__null_byte_fix(result[0])
result_xml = self.__null_byte_fix(self.__raw_result_xml)
# 'irrsmo00.c' returns a raw unmodified bytes object containing a copy
# of the exact contents of the result xml buffer that the IRRSMO00
# callable service populates.
Expand All @@ -88,5 +104,5 @@ def call_racf(
# service was unable to process the request. in this case, would should
# only return the return and reasons codes for error handling downstream.
if result_xml_length == 0:
return list(result[1:4])
return result["returnCodes"]
return result_xml[:result_xml_length].decode("cp1047")
71 changes: 44 additions & 27 deletions tests/common/test_irrsmo00_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ def test_irrsmo00_null_byte_fix(
0, 0, 0, 0, 0, 0,
])
# fmt: on
call_irrsmo00_wrapper_mock.return_value = [xml_containing_null_bytes, 0, 0, 0]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": xml_containing_null_bytes,
"returnCodes": [0, 0, 0],
}
self.assertEqual(
self.irrsmo00.call_racf(b""),
self.good_xml.decode("cp1047")[: self.good_xml_null_terminator_index],
Expand All @@ -67,20 +70,21 @@ def test_irrsmo00_empty_result(
call_irrsmo00_wrapper_mock: Mock,
):
# Simulate failure due to incomplete 'IRR.IRRSMO00.PRECHECK' setup
call_irrsmo00_wrapper_mock.return_value = [
bytes([0 for i in range(256)]),
8,
200,
16,
]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": bytes([0 for i in range(256)]),
"returnCodes": [8, 200, 16],
}
self.assertEqual(self.irrsmo00.call_racf(b""), [8, 200, 16])

def test_irrsmo00_result_buffer_full_failure(
self,
call_irrsmo00_wrapper_mock: Mock,
):
# Simulate scenario where result buffer is too small.
call_irrsmo00_wrapper_mock.return_value = [self.good_xml[:32], 8, 4000, 32]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": self.good_xml[:32],
"returnCodes": [8, 4000, 100000000],
}
self.assertEqual(
self.irrsmo00.call_racf(b""), self.good_xml.decode("cp1047")[:32]
)
Expand All @@ -90,19 +94,20 @@ def test_irrsmo00_result_buffer_full_success(
call_irrsmo00_wrapper_mock: Mock,
):
# Simulate scenario where result buffer is exactly the right size.
call_irrsmo00_wrapper_mock.return_value = [
self.good_xml[: self.good_xml_null_terminator_index],
0,
0,
0,
]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": self.good_xml[: self.good_xml_null_terminator_index],
"returnCodes": [0, 0, 0],
}
self.assertEqual(
self.irrsmo00.call_racf(b""),
self.good_xml.decode("cp1047")[: self.good_xml_null_terminator_index],
)

def test_irrsmo00_normal_result(self, call_irrsmo00_wrapper_mock: Mock):
call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": self.good_xml,
"returnCodes": [0, 0, 0],
}
self.assertEqual(
self.irrsmo00.call_racf(b""),
self.good_xml.decode("cp1047")[: self.good_xml_null_terminator_index],
Expand All @@ -112,52 +117,64 @@ def test_irrsmo00_normal_result(self, call_irrsmo00_wrapper_mock: Mock):
# Test IRRSMO00 Argument Construction
# ============================================================================
def test_irrsmo00_minimum_arguments(self, call_irrsmo00_wrapper_mock: Mock):
call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": self.good_xml,
"returnCodes": [0, 0, 0],
}
self.irrsmo00.call_racf(b"some bytes")
call_irrsmo00_wrapper_mock.assert_called_with(
request_xml=b"some bytes",
request_xml_length=10,
request_xml_len=10,
result_buffer_size=16384,
irrsmo00_options=13,
running_userid=b"",
running_userid_length=0,
running_userid_len=0,
)

def test_irrsmo00_with_precheck_set_to_true(self, call_irrsmo00_wrapper_mock: Mock):
call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": self.good_xml,
"returnCodes": [0, 0, 0],
}
self.irrsmo00.call_racf(b"some bytes", precheck=True)
call_irrsmo00_wrapper_mock.assert_called_with(
request_xml=b"some bytes",
request_xml_length=10,
request_xml_len=10,
result_buffer_size=16384,
irrsmo00_options=15,
running_userid=b"",
running_userid_length=0,
running_userid_len=0,
)

def test_irrsmo00_with_run_as_userid_set(self, call_irrsmo00_wrapper_mock: Mock):
call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": self.good_xml,
"returnCodes": [0, 0, 0],
}
self.irrsmo00.call_racf(b"some bytes", run_as_userid="KRABS")
call_irrsmo00_wrapper_mock.assert_called_with(
request_xml=b"some bytes",
request_xml_length=10,
request_xml_len=10,
result_buffer_size=16384,
irrsmo00_options=13,
running_userid=b"\xd2\xd9\xc1\xc2\xe2",
running_userid_length=5,
running_userid_len=5,
)

def test_irrsmo00_with_custom_result_buffer_size(
self, call_irrsmo00_wrapper_mock: Mock
):
call_irrsmo00_wrapper_mock.return_value = [self.good_xml, 0, 0, 0]
call_irrsmo00_wrapper_mock.return_value = {
"resultBuffer": self.good_xml,
"returnCodes": [0, 0, 0],
}
irrsmo00 = IRRSMO00(result_buffer_size=32768)
irrsmo00.call_racf(b"some bytes")
call_irrsmo00_wrapper_mock.assert_called_with(
request_xml=b"some bytes",
request_xml_length=10,
request_xml_len=10,
result_buffer_size=32768,
irrsmo00_options=13,
running_userid=b"",
running_userid_length=0,
running_userid_len=0,
)

0 comments on commit ac0bf6a

Please sign in to comment.