Skip to content

Commit f565cd8

Browse files
authored
zwave test: properly seed credentials test file data (#3308)
* zwave test: properly seed credentials test file data
1 parent bf8a354 commit f565cd8

2 files changed

Lines changed: 46 additions & 52 deletions

File tree

‎drivers/SmartThings/zwave-lock/src/test/test_lock_credentials_commands.lua‎

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,6 @@ local access_control_event = Notification.event.access_control
1717

1818
test.disable_startup_messages()
1919

20-
21-
if table_utils.find_all_entries_by == nil then
22-
function table_utils.find_all_entries_by(device, table_name, key, value)
23-
local entries = table_utils.get_state(device, table_name) or {}
24-
local matches = {}
25-
for _, entry in ipairs(entries) do
26-
if entry[key] == value then table.insert(matches, entry) end
27-
end
28-
return matches
29-
end
30-
end
31-
32-
3320
local zwave_lock_endpoints = {
3421
{
3522
command_classes = {
@@ -52,6 +39,15 @@ end
5239

5340
local function install_state_mocks()
5441
mock_latest_state = {}
42+
-- tables.lua calls device.log.* unconditionally and get_state guards on
43+
-- supports_capability; stub both for the pre-init seeding phase.
44+
rawset(mock_device, "log", {
45+
debug = function() end, info = function() end, warn = function() end, error = function() end,
46+
})
47+
rawset(mock_device, "supports_capability", function(_, capability)
48+
local id = type(capability) == "table" and capability.ID or capability
49+
return id == capabilities.lockUsers.ID or id == capabilities.lockCredentials.ID
50+
end)
5551
mock_device.get_latest_state = function(_, component_id, capability_id, attribute_name, default_value)
5652
local value = mock_latest_state[mock_state_key(component_id, capability_id, attribute_name)]
5753
if value == nil then
@@ -83,8 +79,8 @@ end
8379
-- ── helpers ────────────────────────────────────────────────────────────────
8480

8581
local function test_init()
86-
mock_device.persistent_store = mock_device.persistent_store or {}
87-
mock_device.transient_store = mock_device.transient_store or {}
82+
mock_device.persistent_store = {}
83+
mock_device.transient_store = {}
8884
install_state_mocks()
8985
mock_device:set_field(constants.DRIVER_STATE.SLGA_MIGRATED, true, { persist = true })
9086
test.mock_device.add_test_device(mock_device)
@@ -101,6 +97,15 @@ local function expect_set_pin_code(user_identifier, user_code)
10197
)
10298
end
10399

100+
local function expect_clear_pin_code(user_identifier)
101+
test.socket.zwave:__expect_send(
102+
UserCode:Set({
103+
user_identifier = user_identifier,
104+
user_id_status = UserCode.user_id_status.AVAILABLE,
105+
}):build_test_tx(mock_device.id)
106+
)
107+
end
108+
104109
local function queue_user_code_added(user_identifier)
105110
test.socket.zwave:__queue_receive({ mock_device.id, Notification:Report({
106111
notification_type = Notification.notification_type.ACCESS_CONTROL,
@@ -109,32 +114,27 @@ local function queue_user_code_added(user_identifier)
109114
}) })
110115
end
111116

112-
local function seed_users(entries)
113-
for _, entry in ipairs(entries) do
117+
-- Seed through table_utils.add_entry: it calls set_field(..., {persist = true}),
118+
-- which is copied to the real driver device when it is lazily created. Writing
119+
-- only to mock_latest_state / persistent_store never reaches the driver.
120+
local function seed_entries(table_name, capability_attr, key_name, entries)
121+
for i, entry in ipairs(entries) do
114122
local so_far = {}
115-
for _, e in ipairs(entries) do
116-
table.insert(so_far, e)
117-
if e == entry then break end
118-
end
119-
local event = capabilities.lockUsers.users(so_far, { visibility = { displayed = false } })
120-
mock_latest_state[mock_state_key("main", event.capability.ID, event.attribute.NAME)] = event.value.value
123+
for j = 1, i do table.insert(so_far, entries[j]) end
124+
test.socket.capability:__expect_send(
125+
mock_device:generate_test_message("main", capability_attr(so_far, { visibility = { displayed = false } })))
126+
assert(table_utils.add_entry(mock_device, table_name, entry) == constants.COMMAND_RESULT.SUCCESS,
127+
"seed " .. table_name .. ": add_entry failed for " .. key_name .. "=" .. tostring(entry[key_name]))
121128
end
122-
mock_device.persistent_store.persistedUsers = entries
123129
test.wait_for_events()
124130
end
125131

132+
local function seed_users(entries)
133+
seed_entries("users", capabilities.lockUsers.users, "userIndex", entries)
134+
end
135+
126136
local function seed_credentials(entries)
127-
for _, entry in ipairs(entries) do
128-
local so_far = {}
129-
for _, e in ipairs(entries) do
130-
table.insert(so_far, e)
131-
if e == entry then break end
132-
end
133-
local event = capabilities.lockCredentials.credentials(so_far, { visibility = { displayed = false } })
134-
mock_latest_state[mock_state_key("main", event.capability.ID, event.attribute.NAME)] = event.value.value
135-
end
136-
mock_device.persistent_store.persistedCredentials = entries
137-
test.wait_for_events()
137+
seed_entries("credentials", capabilities.lockCredentials.credentials, "credentialIndex", entries)
138138
end
139139

140140
-- ============================================================================
@@ -437,10 +437,14 @@ test.register_coroutine_test(
437437
{ capability = capabilities.lockCredentials.ID, command = "deleteAllCredentials", args = {} },
438438
})
439439

440-
test.timer.__create_and_queue_test_time_advance_timer(4, "oneshot")
440+
-- Per-credential clears fire at 2 * (i - 1) s; final cleanup at 2 * #credentials + 4 s.
441+
test.timer.__create_and_queue_test_time_advance_timer(0, "oneshot")
442+
test.timer.__create_and_queue_test_time_advance_timer(6, "oneshot")
443+
expect_clear_pin_code(1)
444+
test.mock_time.advance_time(0)
441445
test.wait_for_events()
442446

443-
test.mock_time.advance_time(4)
447+
test.mock_time.advance_time(6)
444448
test.socket.capability:__expect_send(
445449
mock_device:generate_test_message("main",
446450
capabilities.lockCredentials.credentials({}, { visibility = { displayed = false } }))
@@ -487,8 +491,6 @@ test.register_coroutine_test(
487491
test.register_coroutine_test(
488492
"deleteAllCredentials: returns busy when another operation is already in progress",
489493
function()
490-
seed_credentials({ { userIndex = 1, credentialIndex = 1, credentialType = "pin" } })
491-
492494
-- First deleteAllCredentials starts the z-wave flow (device is now busy)
493495
test.socket.capability:__queue_receive({
494496
mock_device.id,

‎drivers/SmartThings/zwave-lock/src/test/test_lock_pre_configured.lua‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,6 @@ local json = require "st.json"
1919

2020

2121
test.disable_startup_messages()
22-
if table_utils.find_all_entries_by == nil then
23-
function table_utils.find_all_entries_by(device, table_name, key, value)
24-
local entries = table_utils.get_state(device, table_name) or {}
25-
local matches = {}
26-
for _, entry in ipairs(entries) do
27-
if entry[key] == value then table.insert(matches, entry) end
28-
end
29-
return matches
30-
end
31-
end
32-
3322

3423
-- ── Shared device ──────────────────────────────────────────────────────────
3524

@@ -70,8 +59,11 @@ local function install_state_mocks()
7059
error = function() end,
7160
})
7261

73-
-- get_state guards with device:supports_capability; always return true here.
74-
rawset(mock_device, "supports_capability", function() return true end)
62+
-- get_state guards with device:supports_capability; only the seeded capabilities are supported.
63+
rawset(mock_device, "supports_capability", function(_, capability)
64+
local id = type(capability) == "table" and capability.ID or capability
65+
return id == capabilities.lockUsers.ID or id == capabilities.lockCredentials.ID
66+
end)
7567

7668
-- get_state / get_max_entries use device:get_latest_state to read
7769
-- capability attribute values from the state cache.

0 commit comments

Comments
 (0)