cql_code test_cql_contract_argument_notnull_tripwires()

in sources/run_test_client.c [1620:1675]


cql_code test_cql_contract_argument_notnull_tripwires(sqlite3 *db) {
  printf("Running cql_contract_argument_notnull_tripwires test\n");
  tests++;

  jmp_buf tripwire_jmp_buf;

  // This causes `cql_contract_argument_notnull` (and its `_when_dereferenced`
  // variant) to longjmp instead of calling `cql_tripwire`.
  cql_contract_argument_notnull_tripwire_jmp_buf = &tripwire_jmp_buf;

  // Used for IN TEXT NOT NULL and INOUT TEXT NOT NULL arguments.
  cql_string_ref string = string_create();

  // Used for OUT NOT NULL arguments and bogus INOUT NOT NULL arguments.
  cql_string_ref null_string = NULL;

  // Test passing NULL when we're not supposed to. We do this one argument at a
  // time to exercise all possible code paths.
  for (int32_t position = 1; position <= 12; position++) {
    // `position_failed` will hold the position of the argument that failed,
    // counting from 1.
    int position_failed = 0;
    if (!(position_failed = setjmp(tripwire_jmp_buf))) {
      proc_with_notnull_args(
        // Arguments 1-8 have dedicated contract functions. Each case gets
        // tested twice just to pad us out to the 9-or-greater case. INOUT can
        // fail two different ways so we test both.
        position ==  1 ? NULL         : string,       // IN
        position ==  2 ? NULL         : string,       // IN
        position ==  3 ? NULL         : &null_string, // OUT
        position ==  4 ? NULL         : &null_string, // OUT
        position ==  5 ? NULL         : &string,      // INOUT
        position ==  6 ? NULL         : &string,      // INOUT
        position ==  7 ? &null_string : &string,      // INOUT
        position ==  8 ? &null_string : &string,      // INOUT
        position ==  9 ? NULL         : string,       // IN
        position == 10 ? NULL         : &null_string, // OUT
        position == 11 ? NULL         : &string,      // INOUT
        position == 12 ? &null_string : &string       // INOUT
      );
    }
    E(position != 0, "expected tripwire but did not hit one\n");
    E(position == position_failed,
      "expected tripwire for position %d but hit one for %d\n",
      position,
      position_failed);
  }

  // Allow `cql_contract_argument_notnull` to call `cql_tripwire` again.
  cql_contract_argument_notnull_tripwire_jmp_buf = NULL;

  cql_string_release(string);

  tests_passed++;
  return SQLITE_OK;
}