function assertDefBlockArgsStructure_(
  defBlock,
  hasReturn,
  args,
  hasStatements,
) {
  // inputList also contains "TOP" input and optionally "RETURN" and "STACK"
  let defArgCount = defBlock.inputList.length - 1;
  if (hasReturn) {
    defArgCount--;
  }
  if (hasStatements) {
    defArgCount--;
  }

  assert.equal(
    defArgCount,
    args.length,
    'def block has the expected number of args',
  );

  assert.sameOrderedMembers(defBlock.getVars(), args);

  if (!args.length) {
    return;
  }

  const argIds = defBlock.argData_.map((element) => element.argId);
  for (let i = 0; i < args.length; i++) {
    const expectedName = args[i];
    const defInput = defBlock.inputList[i + 1];
    assert.equal(defInput.type, Blockly.inputs.inputTypes.DUMMY);
    assert.equal(defInput.name, argIds[i]);
    assert.equal(
      defInput.fieldRow[2].getValue(),
      expectedName,
      'def block consts did not match expected',
    );
  }

  // Assert the last input is not a dummy. Sometimes
  // arg inputs don't get moved which is bad.
  const lastInput = defBlock.inputList[defBlock.inputList.length - 1];
  assert.notEqual(
    lastInput.type,
    Blockly.inputs.inputTypes.DUMMY,
    'last input is not a dummy',
  );
}
Asserts that the procedure definition block has the expected arguments.
@param {!Blockly.Block} defBlock The procedure definition block.
@param {boolean=} hasReturn If we expect the procedure def to have a return
    input or not.
@param {Array<string>=} args An array of argument names.
@param {boolean=} hasStatements If we expect the procedure def to have
    a statement input or not.
@private