Katkat

Debug and Extend a Device Registry: Status Validation, Active Counts, Bulk Updates

OnepaySoftware Engineer · Technical Screen

Last updated

A progressive coding exercise on a device registry: find the bug behind a failing test where a device's status must be allowed for its type, then add validated registration, per-type counts of active devices that omit zeros, and a bulk status update based on maintenance time and failure count. It tests code reading and business logic.

You are handed a small existing Python module that manages a registry of devices, together with its tests. The exercise has several small steps that build on each other: read the existing code, use a failing test to find a bug, then add follow-up features. It is business-logic implementation rather than algorithm design, so clear structure, validation and tests matter more than clever data structures.

The original code was not shared. The module below is a representative reconstruction of the reported bug: a device may be stored only if its status is one that a configuration map allows for that device's type.

ALLOWED_STATUSES = {
 "sensor": {"ACTIVE", "INACTIVE", "MAINTENANCE"},
 "camera": {"ACTIVE", "INACTIVE", "FAULTY"},
 "gateway": {"ACTIVE", "MAINTENANCE", "FAULTY"},
}

class Device:
 def __init__(self, device_id, device_type, status, registered_at):
 self.device_id = device_id
 self.device_type = device_type
 self.status = status
 self.registered_at = registered_at
 self.last_maintenance_at = registered_at
 self.failure_count = 0

class DeviceRegistry:
 def __init__(self):
 self.devices = {} # device_id -> Device

 def is_valid_status(self, device_type, status):
 for statuses in ALLOWED_STATUSES.values():
 if status in statuses:
 return True
 return False

 def add_device(self, device):
 if not self.is_valid_status(device.device_type, device.status):
 return False
 self.devices[device.device_id] = device
 return True

The failing test:

def test_add_device_rejects_status_not_allowed_for_type():
 registry = DeviceRegistry()
 camera = Device("cam-1", "camera", "MAINTENANCE", 100)
 assert registry.add_device(camera) is False
 assert "cam-1" not in registry.devices

Assume other code, not shown, updates last_maintenance_at and failure_count as maintenance and failures are recorded.

Clarifying Questions

  • Should invalid input be reported by returning False, by raising an exception, or by returning an error that names the failed check?
  • Are device types and statuses case-sensitive, and can the allowed-status map change while the registry is running?
  • Is the registry used from more than one thread?
  • Do callers or tests depend on any ordering of returned collections?

Part 1 — Find and fix the bug

Explain why the test fails, fix the bug with a minimal change, and describe which other invalid inputs the same bug lets through.

What This Part Should Cover

  • The root cause, traced from the failing assertion back to the check
  • A minimal fix and the other invalid inputs the defect accepted
  • Regression tests for the fixed behavior

Part 2 — Register a new device

Add register_device(device_id, device_type, status, registered_at). At minimum it must reject a device ID that is already registered, a device type that is not in the map, a status that the map does not allow for that type, and a negative registration time. Otherwise it creates and stores the device. Decide what it returns or raises on each failure, and what else it should validate.

Clarifying Questions for this Part

  • Should a duplicate ID whose fields are identical to the stored device count as a harmless retry or as an error?
  • Is the registration time an integer timestamp, and is a time in the future acceptable?

What This Part Should Cover

  • Every reported check (duplicate ID, legal type, status allowed for the type, non-negative time) and the order they run in
  • Atomicity: a rejected call leaves the registry unchanged
  • An error-reporting contract that callers and tests can rely on

Part 3 — Count active devices by type

Add count_active_by_type(), which returns a mapping from device type to the number of devices whose status is ACTIVE. A type with no active devices must not appear in the result.

What This Part Should Cover

  • Correct omission of types with zero active devices
  • Time complexity, and whether maintaining live counters is worth it
  • Deterministic output that tests can compare

Part 4 — Bulk status update

Add a method that updates the status of every device that matches rules based on its last maintenance time and its failure count, and returns how many devices it updated. The exact thresholds, target statuses and precedence were not reported, so settle them through the clarifying questions below before implementing.

Clarifying Questions for this Part

  • What are the thresholds (time since last maintenance, number of failures), and are they parameters or constants?
  • Which status does each condition move a device to, and which condition wins when both apply?
  • Does a device that is already in its target status count as updated?
  • Which current statuses are eligible; for example, should an INACTIVE device be touched at all?

What This Part Should Cover

  • Explicit, testable rules, including the precedence between the two conditions
  • Respecting the allowed statuses per type during the update
  • An updated count that includes only real changes

Hints

Hint 1

Follow the unused argument: Compare what `is_valid_status` does with its `device_type` argument with the way `ALLOWED_STATUSES` is keyed.

Hint 2

A rejection leaves no trace: Think about the order of the checks so that a rejected call never modifies the registry, and about inputs that could raise inside your own validation before it reports anything.

Hint 3

Where the keys come from: Decide whether to start from the list of known types or from the devices themselves, given that zero counts must be left out.

Hint 4

Collisions between rules: Consider a device that matches both conditions, and a device whose target status is not allowed for its type by `ALLOWED_STATUSES`.

Follow-up questions

  • How would you make `register_device` safe if two threads register the same ID at the same moment?
  • If the allowed-status map is loaded from configuration and a status is removed, what should happen to devices that currently hold it?
  • How would you keep an audit history of status changes, including those made by the bulk update?