- Which test set best detects asymmetric handling of the negative limit as well as off-by-one errors at both numeric boundaries?
Answer: -2147483649, -2147483648, 2147483647, and 2147483648
When testing a numeric range parser, you want to probe both sides of each boundary — one value just outside the limit (should be rejected) and one value just inside (should be accepted). For a 32-bit signed integer, the valid range is [−2147483648, 2147483647], and the two boundaries behave asymmetrically: the negative extreme has a larger absolute value than the positive extreme, which is a common source of bugs.
The ideal test set needs four values: the out-of-range value just below the minimum, the minimum itself, the maximum itself, and the out-of-range value just above the maximum. That's exactly what D gives you: -2147483649 (reject — one below the floor), -2147483648 (accept — the floor itself), 2147483647 (accept — the ceiling itself), and 2147483648 (reject — one above the ceiling). This directly tests both off-by-one edges and the asymmetric negative boundary.
A is wrong because it tests two values inside the valid range on the positive side (2147483646 and 2147483647) and two inside on the negative side, missing any out-of-bounds probe entirely — you'd never catch a parser that accepts 2147483648.
B is wrong because it tests general interior values (-1, 0) rather than boundary conditions; it would pass even a parser with completely wrong limits.
C is wrong because it omits the minimum value -2147483648 itself, meaning you can't confirm the floor is actually accepted — only that values near it behave correctly.
As a strategy, always think in pairs at each boundary: one value just outside and one just inside. If a test set is missing either half of a boundary pair, it can't catch off-by-one errors there. - Which collection of inputs most systematically tests size boundaries and duplicate-run placement without relying only on typical mixed data?
Answer: Empty; singleton; all equal; all distinct; duplicates only at the beginning; and duplicates only at the end
When testing a function that removes adjacent duplicates from a sorted vector, you need to think like a boundary analyst: cover edge cases by size (empty, tiny, large) and by position (where duplicate runs appear). A systematic test suite addresses both dimensions independently, not just typical "realistic" inputs.
Option C does this most thoroughly. It starts with an empty vector (zero-element edge case) and a singleton (one-element case, where no removal should occur). Then it adds all-equal elements (the extreme case where everything is a duplicate) and all-distinct elements (the opposite extreme, where nothing is removed). Crucially, it then isolates duplicate placement: duplicates only at the beginning tests whether the function correctly handles early removal without corrupting the rest of the vector, and duplicates only at the end tests whether the algorithm terminates cleanly after a removal. Together, these six cases form a clean, independent grid of size and position variations.
Option A is close but substitutes "alternating duplicate pairs" and "middle duplicates" for the more isolated boundary positions. It misses the beginning-only and end-only placement tests, so duplicate-run placement isn't fully isolated. Option B skips the empty vector entirely — a critical omission, since empty input is the most common source of off-by-one crashes. It also doubles up on all-equal vectors without adding positional variety. Option D includes two singletons, which is redundant (one singleton already covers that boundary), and uses a vague "mixed larger vector" that conflates multiple conditions rather than isolating them.
Your takeaway: when a question asks about systematic test design, look for the answer that independently varies each relevant dimension — size and placement — rather than the one that simply lists the most vectors or the most "realistic" data.
- Which suite provides the most systematic boundary coverage?
Answer: Empty/absent; singleton/present; singleton/absent; and a multi-element vector with the first, last, below-minimum, and above-maximum targets
When testing a binary-search function, you should think systematically about boundary categories: cardinality boundaries (empty, singleton, multi-element), position boundaries (first element, last element, interior), and search boundaries (below minimum, above maximum, absent interior). A strong test suite hits all of these without redundancy.
Answer B covers every critical boundary cleanly. It starts with the empty vector (cardinality floor), then validates the singleton in both its present and absent states (cardinality edge with both outcomes), and finally stress-tests a multi-element vector with the first element (left position boundary), last element (right position boundary), a target below the minimum (left search boundary), and a target above the maximum (right search boundary). Nothing important is missing, and nothing is duplicated.
Answer A falls short because its multi-element cases include only an "interior absent" target instead of below-minimum and above-maximum searches. This leaves the out-of-range search boundaries completely untested — a classic blind spot for binary search bugs involving the comparison logic at the array edges.
Answer C drops the singleton/absent case entirely, replacing it with a second singleton/present test. That's redundant: two present-singleton tests add no new information, and you lose coverage of the scenario where the only element doesn't match the target — an important cardinality-edge case.
Answer D skips the empty-vector case altogether. The empty input is a critical cardinality boundary; binary search must handle it without undefined behavior or incorrect results, so omitting it is a meaningful gap regardless of how thorough the other cases are.
As a study strategy: mentally categorize test cases into cardinality, position, and search boundary groups — the best suite has at least one representative from each, with no duplicate coverage.
- Which pair of tests targets two distinct boundary-related defects in the implementation?
Answer: (-2, -1) and (INT_MAX - 1, INT_MAX)
When testing arithmetic implementations, you should hunt for two distinct bug categories: incorrect truncation behavior and integer overflow. The formula a+⌊2b−a⌋ always truncates toward negative infinity, but C++ truncates toward zero — these diverge only when the division result is negative. Separately, a + b can silently overflow when both values are large.
B is correct because it targets both defects independently. For (-2, -1): the correct midpoint is −2+⌊21⌋=−2+0=−2, but (-2 + -1) / 2 = -3 / 2 = -1 in C++ (truncates toward zero, not floor) — wrong answer, exposing the truncation bug. For (INT_MAX - 1, INT_MAX): both values are near the signed integer ceiling, so a + b overflows, producing undefined behavior — exposing the overflow bug. Two distinct defects, two targeted tests.
A is wrong because (0, 1) and (10, 20) involve only non-negative values where floor and truncation-toward-zero agree, and the sums are nowhere near overflow. Neither defect is triggered.
C is wrong because (-1, 1) does catch the truncation issue (correct: −1, computed: 0), but (INT_MIN, INT_MAX) doesn't isolate overflow cleanly — a + b = 0 here, accidentally producing the right answer and masking the bug rather than exposing it.
D is wrong for the same reason as A — all values are non-negative and small, so neither truncation nor overflow defects are reached.
A good test strategy: always pair a sign-related edge case with an extreme-magnitude edge case when validating arithmetic functions. - Which set of February dates exercises every decision boundary in the leap-year rule and also checks the ordinary end of February?
Answer: 1900-02-29, 2000-02-29, 2023-02-28, and 2023-02-29
When testing a leap-year rule, you need to think in terms of decision boundaries — the specific conditions that flip the rule's outcome. The Gregorian leap-year logic has three boundaries: divisible by 4 (leap), divisible by 100 (not leap), and divisible by 400 (leap again). Good test coverage means hitting each boundary with a case that passes it and one that fails it, plus verifying normal behavior.
Answer B gives you exactly this coverage. 1900-02-29 is invalid because 1900 is divisible by 100 but not 400 — it exercises the century-exception boundary. 2000-02-29 is valid because 2000 is divisible by 400 — it exercises the 400-year override. 2023-02-29 is invalid because 2023 isn't divisible by 4 at all — it exercises the basic non-leap case. 2023-02-28 is valid and exercises the ordinary end-of-February behavior. Together, these four cases touch every logical branch.
Answer A fails because 1900-02-28 just tests a valid non-leap-year date — that's redundant with checking 1900-02-29, and A never tests an ordinary (non-century) non-leap year like 2023.
Answer C is missing 1900-02-29, so the century-exception boundary (divisible by 100, not 400) is never tested. You'd never know if the validator incorrectly allows Feb 29 in 1900.
Answer D omits 2023-02-28, so ordinary end-of-February validity goes unchecked — that's the "normal behavior" baseline the question specifically asks for.
As a strategy, always map out every if/else branch in a rule before choosing test cases. Each distinct condition needs at least one true and one false input.
- Which minimal suite best distinguishes underflow during initialization, underflow after reaching index zero, and a successful search at index zero?
Answer: Search an empty vector; search an absent target in a singleton; and search its present element in that singleton
When testing a loop that decrements a std::size_t index, you need to think about where unsigned integer underflow can strike. Because std::size_t is unsigned, subtracting from zero wraps around to a huge positive value rather than going negative — meaning i >= 0 is always true, and the loop never terminates naturally. This bug can manifest in two distinct places: during initialization (v.size() - 1 when v is empty gives SIZE_MAX) and after processing index zero (--i wraps around instead of making i negative). A good test suite isolates each failure mode separately.
Option A is correct because it targets all three distinct behaviors. An empty vector triggers underflow at initialization — v.size() - 1 immediately wraps. Searching for an absent target in a singleton forces the loop to process index zero and then call --i, triggering underflow after the loop body executes. Finally, searching for a present element in that same singleton hits index zero and returns successfully before decrementing — confirming the success path works without triggering the second underflow.
Option B skips both underflow scenarios entirely; it only tests whether the function finds present elements, missing the core bug. Option C never tests the empty-vector initialization underflow, leaving one failure mode completely uncovered. Option D tests only successful searches, which may never expose the decrement underflow at all since the function returns before --i wraps.
As a strategy, when you see a loop with std::size_t and a >= 0 condition, immediately ask: "What happens at empty input, at the boundary after index zero, and at a valid boundary hit?" Each scenario maps to a separate bug — and your test suite should mirror that structure one-to-one.
- Which set of valid calls most directly exercises all three structurally different cases in which one or more indices equal an outer boundary?
Answer: eraseRange(0, 0), eraseRange(0, 4), and eraseRange(4, 4)
When testing boundary conditions for a range function, you want to think structurally: what are the distinct ways indices can touch the outer boundaries (0 and 4)? For a vector of size 4, the meaningful boundary cases are: (1) both indices at the left boundary, (2) both indices at the right boundary, and (3) the range spanning the entire container. These three cases stress-test whether the implementation correctly handles empty ranges at each end and a full-range erasure.
Answer A — eraseRange(0, 0), eraseRange(0, 4), eraseRange(4, 4) — covers exactly these three structurally distinct cases: an empty range pinned to the left boundary, the complete range touching both boundaries simultaneously, and an empty range pinned to the right boundary. This set is the correct answer because no other option captures all three with such directness.
Answer B uses only interior-adjacent indices like (0,1), (1,3), and (3,4) — none of these are empty ranges, and none isolate a single outer boundary, so they miss the boundary-empty-range cases entirely.
Answer C includes two empty ranges ((0,0) and (1,1)), but (1,1) is interior, not a boundary case. It also uses (3,4) instead of anything that touches the right boundary index 4 with an empty range — so the right-boundary empty case is absent.
Answer D skips the left-boundary empty case (0,0) entirely. It exercises the right side and the full range, but leaves one of the three structural cases untested.
The strategy here: whenever a question asks about "boundary cases," map out the structural roles each boundary plays — left-empty, right-empty, and spanning — then check which answer hits all of them directly.
- Which operation sequence most completely tests full-capacity behavior, index wraparound, retained order after wrapping, and the empty transition?
Answer: Enqueue A, B, C; attempt to enqueue D; dequeue A; enqueue D; dequeue B, C, D; then attempt one more dequeue
When testing a circular queue, you need to verify four distinct behaviors: rejecting an enqueue when full, wrapping array indices correctly, preserving FIFO order after the wrap occurs, and rejecting a dequeue when empty. The challenge is finding a single sequence that exercises all four — not just a subset.
Option D does exactly this. You fill the queue (A, B, C), then attempt to enqueue D, which should fail — testing the full-capacity rejection. Next, you dequeue A, which advances the front index. Enqueueing D now succeeds, and critically, D lands at the array slot previously occupied by A — this is the index wraparound. Dequeuing B, C, D in that order confirms FIFO order is preserved after wrapping. The final dequeue attempt on an empty queue tests the empty-state rejection. All four criteria are met.
Option A skips the full-capacity rejection entirely — it never attempts to enqueue into a full queue, so you never verify that the queue correctly refuses the operation. Option B covers full-capacity rejection and the empty transition, but it never wraps indices: you fill, reject, then drain sequentially without any index wraparound occurring. Option C tests wraparound in a minimal way but never fills the queue to capacity, so full-capacity rejection is untested.
A useful strategy: map out the internal front and rear indices on paper as you trace each sequence. A sequence only tests wraparound if rear (or front) actually resets to index 0 after reaching the array's end — look for that moment explicitly when evaluating these questions.
- Which test set is most likely to expose both ordinary rounding-boundary defects and unsigned overflow in this implementation?
Answer: (0, 4), (8, 4), (9, 4), and (SIZE_MAX, 2)
When testing integer arithmetic functions, you need two distinct failure modes in mind: boundary rounding (does the ceiling division round correctly at exact multiples and just beyond?) and unsigned overflow (does adding k - 1 to a near-maximum n wrap around silently?).
For rounding boundaries with k = 4, the critical inputs are n = 0 (zero items → zero batches), n = 8 (exact multiple → no rounding needed), and n = 9 (one past a multiple → must round up). These three together probe the "no remainder," "exact boundary," and "remainder exists" cases. Option C includes all three with k = 4.
For overflow, the danger is n + k - 1 wrapping when n is near SIZE_MAX. With (SIZE_MAX, 2) from option C, the addition becomes SIZE_MAX + 1, which wraps to 0 for std::size_t, producing a catastrophically wrong result — exactly the defect you want to expose.
Option A uses (SIZE_MAX, 1), which makes n + k - 1 = SIZE_MAX + 0 = SIZE_MAX — no overflow occurs, so the overflow bug is not triggered. That's the critical flaw in A.
Option B contains no extreme values at all, so it completely misses unsigned overflow and only partially probes rounding.
Option D swaps in SIZE_MAX - 1 with k = 2, giving SIZE_MAX - 1 + 1 = SIZE_MAX — again, no actual wraparound, so the overflow defect survives undetected.
C is correct because it uniquely combines full rounding-boundary coverage and a (n, k) pair that genuinely triggers unsigned wraparound.
Study tip: When evaluating test suites for unsigned integer arithmetic, always ask — does any input actually cause the overflow, not just approach it?
- Which test set most systematically detects either independent boundary-comparison defect while also verifying the immediately adjacent out-of-range values?
Answer: 99, 100, 999, and 1000
When testing boundary conditions, the goal is to catch off-by-one errors — bugs where a developer writes > instead of >=, or < instead of <=. To detect these independently at both boundaries, you need values that straddle each boundary: one value just outside the valid range and one value just inside it.
For a function accepting [100, 999], the critical boundary pairs are:
- Lower boundary: 99 (just outside) and 100 (just inside)
- Upper boundary: 999 (just inside) and 1000 (just outside)
If a developer wrote x > 100 instead of x >= 100, the value 100 would be incorrectly rejected — and 99 confirms the rejection still works one step below. The same logic applies at the upper end with 999 and 1000. This is exactly what answer A (99, 100, 999, 1000) provides: both boundary-straddling pairs, one at each end.
Answer B (100, 101, 998, 999) tests values well inside the valid range and completely misses the out-of-range values 99 and 1000 — it cannot detect any boundary defect. Answer C (99, 100, 998, 999) correctly handles the lower boundary but replaces 1000 with 998, which is deep inside the valid range and cannot expose an upper-boundary comparison error. Answer D (100, 101, 999, 1000) correctly handles the upper boundary but replaces 99 with 101, missing the lower boundary's out-of-range check entirely.
As a general strategy: boundary testing always requires pairs — one value on each side of every boundary. If a test set is missing either the inside or outside value at a boundary, it cannot independently detect a defect there.