Defining fields and variables
You can define fields in any structured type—structs, actors, scenarios or modifiers—to specify the attributes or characteristics of that type. During the generation test phase, before executing the test, Foretify selects a value from the range of legal values for each field. You can constrain the range of legal values for a field to suit the purposes of a particular test.
Variables are similar to fields, except that Foretify does not select a value for them during generation. Instead, you can use a method to assign a value to it during the execution of a test. Foretify supports three types of methods:
- Expression methods simply assign the value of any legal OSC2 expression to the variable.
- Native methods are written in OSC2 and can manipulate lists, perform certain mathematical calculations and so on.
- External methods can access more complex functions written in an external language such as C++.
Below are some examples of how to define fields and variables. For a precise description of the declaration syntax, see Fields and variables.
Example scalar field
The following example shows an actor with two fields of type speed. The first field is named current_speed and holds a value specifying the current speed. The name current_speed is preceded by var, which prevents it from receiving a value during generation. Most likely it is assigned various values while a scenario is running. The second field is named max_speed and it has a soft constraint. It receives a value during generation of 120 kph, unless it is constrained or assigned otherwise.
actor my_car:
# Current car speed
var current_speed: speed
# Car max_speed
max_speed: speed with:
keep(soft it == 120kph)
See complete example.
Example list field
extend traffic:
var my_cars: list of vehicle
See complete example.
Example list field with constraints
actor my_car_convoy:
first_car: vehicle
cars: list of vehicle
# the list will have between 2 and 10 items
# the first item is first_car
keep(soft cars.size() <= 10)
keep(soft cars.size() >= 2)
keep(cars[0] == first_car) # list indexing
See complete example.
Example string field
The default value of a field of type string is null (empty string).
struct data:
name: string with:
keep(it == "John Smith")
See complete example.
Example field in actor or struct
The following example shows a field of type my_car with the name car1 instantiated in the traffic actor. The constraint on car1’s max_speed field overrides the earlier soft constraint on the same field.
extend traffic:
car1: my_car with:
keep(it.max_speed == 60kph)
See complete example.
Example field in scenario
This example shows a struct field storm_data instantiated in a scenario called environment.snowstorm. Constraints are set on storm_data’s two fields, and the wind_velocity field is monitored for coverage.
enum storm_type: [rain, ice, snow]
struct storm_data:
storm: storm_type
wind_velocity: speed
scenario environment.snowstorm:
storm_data: storm_data with:
keep(it.storm == snow)
keep(soft it.wind_velocity >= 30kph)
cover(wind_velocity, expression: it.wind_velocity, unit: kph)
See complete example.
Example field with sampling
This code samples the value of car1.speed at the end event of the get_ahead phase of the cut_in scenario.
extend sut.cut_in:
var speed_car1_get_ahead_end := sample(car1.state.speed, @get_ahead.end) with:
cover(speed_car1_get_ahead_end,
text: "Speed of car1 at get_ahead end (in kph)", unit: kph,
range: [10..130], every: 10)
See complete example.
To see how to use sample, see the sample-exp parameter in the Fields and variables section.
Example field without explicit type
The data type of the field must be specified unless the type can be determined from a value assigned to it. For example, the declaration in the example below defines a field named legal_speed of type speed. For the second declaration, too_fast is determined to be of type bool (Boolean).
scenario vehicle.my_scenario1:
legal_speed: speed
var too_fast:= true
See complete example.
Example variable declaration with new
struct my_ints:
x: int
y: int
extend top.main:
var z: my_ints = new
do call logger.log_info("z.x = $(z.x), z.y = $(z.y)")