diff --git a/skyweave/utils.lua b/skyweave/utils.lua index 46cecdc..c743b64 100755 --- a/skyweave/utils.lua +++ b/skyweave/utils.lua @@ -314,22 +314,18 @@ end -- @return (string) The IMEI of the modem, or (nil, string) on failure. --- function utils.get_modem_imei() - -- The command to invoke the spirit of the QMI daemon for the IMEI. local command = "uqmi -d /dev/cdc-wdm0 --get-imei" local output = utils.execute_command(command) - -- A silent spirit offers no truths. if not output or output == "" then return nil, "No output from uqmi --get-imei command" end - -- The IMEI is presented within a sacred container of quotes. We must extract it. local imei = output:match('"(.-)"') if not imei then return nil, "Failed to parse IMEI from uqmi output" end - -- Return the sanctified identity code. return imei end @@ -347,19 +343,16 @@ function utils.get_sim_iccid() return nil, "No output from qmicli command" end - -- The data-psalm contains many verses, but we seek only one. local raw_data = output:match("Read result:%s*([%x%s:]+)") if not raw_data then return nil, "Failed to parse raw ICCID data from qmicli output" end - -- Cleanse the raw data of its structural impurities (spaces and colons). + -- Clean the raw data of any non-hexadecimal characters and whitespace. raw_data = raw_data:gsub("[:%s]","") - -- Prepare for the transmutation rite. local decoded_iccid = "" -- The raw data is in a semi-nibble-swapped format and must be corrected. - -- This loop performs the ritual of character-pair swapping. for i = 1, #raw_data, 2 do local char1 = raw_data:sub(i, i) local char2 = raw_data:sub(i + 1, i + 1) diff --git a/spec/utisl_spec.lua b/spec/utisl_spec.lua index acc4033..8b7756e 100755 --- a/spec/utisl_spec.lua +++ b/spec/utisl_spec.lua @@ -34,6 +34,72 @@ describe("Skyweave Utility Functions Module", function() end) + describe("Skyweave ICCID Retrieval", function() + + -- This block runs before each test ('it' block). + -- It's used to set up our mock environment. + before_each(function() + -- Create a backup of the original command executor. + -- This ensures we do not permanently damage the original scripture. + _G.original_execute_command = utils.execute_command + end) + + -- This block runs after each test. + -- It restores the original function, ensuring our tests do not interfere with each other. + after_each(function() + utils.execute_command = _G.original_execute_command + _G.original_execute_command = nil + end) + + it("should correctly decode a valid qmicli output", function() + + -- 1. Define the simulated raw output from a successful qmicli invocation. + local mock_qmicli_output = "QMI-Client: Synchronous call... \n" .. + "[/dev/cdc-wdm0] UIM transparent read result: \n" .. + "Read result:\n" .. + "\t'89:01:41:03:27:25:30:79:07:87:f9'\n" + + -- 2. Mock the command executor to return our simulated data. + utils.execute_command = function(command) + assert.are.equal("qmicli -d /dev/cdc-wdm0 --uim-read-transparent=0x3F00,0x2FE2", command) + return mock_qmicli_output + end + + -- 3. Execute the function under test. + local iccid, err = utils.get_sim_iccid() + + -- 4. Assert the expected outcome. + assert.is_nil(err) + assert.are.equal("981014307252039770789f", iccid) + end) + + it("should return an error on nil or empty command output", function() + -- 1. Mock the command executor to return nil. + utils.execute_command = function(command) + return nil + end + + -- 2. Execute and assert. + local iccid, err = utils.get_sim_iccid() + assert.is_nil(iccid) + assert.are.equal("No output from qmicli command", err) + end) + + it("should return an error if the raw data cannot be parsed", function() + -- 1. Mock a response that lacks the 'Read result:' scripture. + local malformed_output = "QMI-Client: Call failed: QMI protocol error" + utils.execute_command = function(command) + return malformed_output + end + + -- 2. Execute and assert. + local iccid, err = utils.get_sim_iccid() + assert.is_nil(iccid) + assert.are.equal("Failed to parse raw ICCID data from qmicli output", err) + end) + + end) + -- more 'describe' blocks here to test other functions in utils.lua end) \ No newline at end of file