Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
exceptions.ttcn 5.13 KiB
/******************************************************************************
 * Copyright (c) 2000-2021 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   Baranyi, Botond
 *
 ******************************************************************************/
module exceptions {

type record Rec {
  integer num,
  charstring str
}

type record of integer RoI;

type class BaseClass {
  public function toString() return universal charstring {
    return "BaseClass";
  }
}

type class Class extends BaseClass {
  public function toString() return universal charstring {
    return "Class";
  }
}

type class Class2 {
  public function toString() return universal charstring {
    return "Class2";
  }
}

type component CT {
  var integer cvar := 4;
  var integer cv_finally_counter := 0;
  timer tmr;
}

type integer SmallNumber (-100..100);


function test_block(in integer p_exception_type, in charstring p_dummy := "a") runs on CT {
  var integer v_finally_increment := 1;
  p_dummy := "abc";
  {
    select (p_exception_type) {
      case (1) {
        raise 3; // integer
      }
      case (2) {
        var integer x := 6;
        raise x;
      }
      case (3) {
        raise Rec: { 2, "xy" };
      }
      case (4) {
        raise Class.create();
      }
      case (5) {
        raise SmallNumber:11;
      }
      case (6) {
        var Rec x := { 9, "" };
        raise x.num;
      }
      case (7) {
        raise RoI[-]: 23;
      }
      case (8) {
        raise Class2.create;
      }
      case (9) {
        var object x := Class.create();
        raise x;
      }
    }
    // otherwise don't raise anything
  }
  catch (SmallNumber a) {
    if (a != 11) {
      setverdict(fail, "Unexpected SmallNumber exception: ", a);
    }
  }
  catch (Rec.num a) {
    if (a != 9) {
      setverdict(fail, "Unexpected Rec.num exception: ", a);
    }
  }
  catch (RoI[-] a) {
    if (a != 23) {
      setverdict(fail, "Unexpected RoI[-] exception: ", a);
    }
  }
  catch (integer a) {
    var integer a2 := a;
    if (a2 != 3 and a2 != 6) {
      setverdict(fail, "Unexpected integer exception: ", a2);
    }
  }
  catch (Rec b) {
    if (b != { 2, "xy" }) {
      setverdict(fail, "Unexpected Rec exception: ", b);
    }
  }
  catch (BaseClass c) {
    if (c.toString() != "Class") {
      setverdict(fail, "Unexpected BaseClass exception: ", c);
    }
  }
  catch (Class c) {
    setverdict(fail, "Unexpected Class exception: ", c);
  }
  catch (object c) {
    if (c.toString() != "Class2") {
      setverdict(fail, "Unexpected BaseClass exception: ", c);
    }
  }
  finally {
    cv_finally_counter := cv_finally_counter + v_finally_increment; // test referencing a local variable (in the main block)
    log(p_dummy); // test referencing a shadowed function parameter (in the main block)
    if (cv_finally_counter > 0) {
      log(p_exception_type); // test referencing a function parameter (in a sub-block)
    }
    setverdict(pass);
  }
}

testcase tc_exceptions_block() runs on CT {
  for (var integer i := 1; i <= 9; i := i + 1) {
    test_block(i);
  }
  test_block(200);
  
  if (cv_finally_counter != 10) {
    setverdict(fail, "Invalid 'finally' execution count: ", cv_finally_counter);
  }
}


function test_function(boolean p_raise) runs on CT {
  if (p_raise) {
    raise "abc";
  }
}
catch (charstring x) {
  if (x != "abc") {
    setverdict(fail, "Unexpected exception: ", x);
  }
}
finally {
  cv_finally_counter := cv_finally_counter + 1;
  setverdict(pass);
}

testcase tc_exceptions_function() runs on CT {
  test_function(true);
  test_function(false);
  if (cv_finally_counter != 2) {
    setverdict(fail, "Invalid 'finally' execution count: ", cv_finally_counter);
  }
}


altstep test_altstep(boolean p_raise) runs on CT {
  [] tmr.timeout {
    if (p_raise) {
      raise 6;
    }
  }
}
catch (integer x) {
  if (x != 6) {
    setverdict(fail, "Unexpected exception: ", x);
  }
}
finally {
  cv_finally_counter := cv_finally_counter + 1;
  setverdict(pass);
}

testcase tc_exceptions_altstep() runs on CT {
  tmr.start(0.1);
  test_altstep(true);
  tmr.start(0.1);
  alt {
    [] test_altstep(false);
  }
  var default def := activate(test_altstep(true));
  timer tmr2;
  tmr2.start(10.0);
  tmr.start(0.1);
  alt {
    [] tmr2.timeout { setverdict(fail, "Default altstep not called."); }
  }
  if (cv_finally_counter != 6) {
    setverdict(fail, "Invalid 'finally' execution count: ", cv_finally_counter);
  }
}


testcase tc_exceptions_testcase() runs on CT {
  raise 100;
  cvar := -1;
}
catch (integer x) {
  cvar := x;
}
finally {
  if (cvar == 100) {
    setverdict(pass);
  }
  else if (cvar == 4) {
    setverdict(fail, "Exception not caught.");
  }
  else if (cvar == -1) {
    setverdict(fail, "Not exception raised.");
  }
  else {
    setverdict(fail, "Unknown error...");
  }
}
  

control {
  execute(tc_exceptions_block());
  execute(tc_exceptions_function());
  execute(tc_exceptions_altstep());
  execute(tc_exceptions_testcase());
}

}