• No results found

Automated Test Case Generation for Function Block Diagrams using Java Path Finder and Symbolic Execution

N/A
N/A
Protected

Academic year: 2021

Share "Automated Test Case Generation for Function Block Diagrams using Java Path Finder and Symbolic Execution"

Copied!
107
0
0

Loading.... (view fulltext now)

Full text

(1)

School of Innovation Design and Engineering

aster˚

as, Sweden

Thesis for the Degree of Master of Science in Computer Science

with specialisation in Software Engineering

AUTOMATED TEST CASE GENERATION

FOR FUNCTION BLOCK DIAGRAMS USING

JAVA PATH FINDER AND SYMBOLIC EXECUTION

Sebastian Kunze

ske14002@student.mdh.se

Examiner: Assoc. Prof. Daniel Sundmark

M¨alardalen University, V¨aster˚as, Sweden

Supervisors: Dr. Adnan Causevic

M¨alardalen University, V¨aster˚as, Sweden

Eduard Paul Enoiu

(2)

istent, we focus on what does exist – buggy software”

Telles and Hsieh

(3)

I would like express my gratitude to my four supervisors: Dr. Adnan Causevic, Eduard Paul Enoiu, Prof. Dr. Gerhard Raffius and Dr.rer.nat. Ralf S. Mayer. They had been very supportive and provided valuable expertise that greatly assisted the research in the last six month.

Furthermore, I would like to thank my loved ones, who have supported me throughout entire process, both by keeping me harmonious and helping me putting pieces together.

(4)

Testing Function Block Diagram (FBD) programs for safety-critical software components is of significant importance. Their failure or malfunction may result in a serious outcome and may cause severe damage. Consequently, a certain degree of certification is required to guarantee that the provided test cases cover the logical structure of the safety-critical software components. In practise, testing FBD programs is relatively hard because it is usually performed manually and is prone to human error.

Recently, researchers devised an automated test generation tool named CompleteTest that aids control engineers to perform component testing. It analyses safety-critical software components to identify a number of tests needed to achieve maximum coverage required by the industry for operation. CompleteTest is based on a model checker that lacks support for Real and String types which are heavily used in FBD programs. Java Path Finder (JPF) is a model checker that supports different data types and provides an extension supporting symbolic execution named Symbolic Path Finder (SPF). To our knowledge, there has been little research on using symbolic execution in testing FBD programs. Hence, we compare JPF / SPF to CompleteTest and explore possibilities and limitations of symbolic execution on FBD program testing. We show how to translate two FBD programs to Java program representations suitable for model checking using JPF / SPF. In addition, we illustrate how to instrument those Java program representations for automated test case generation using JPF / SPF. The resulting test cases are compared to the test cases generated by CompleteTest evalu-ating their coverage, efficiency and effectiveness. Even though, the test cases generated by JPF / SPF turn out to be more effective and provide the same coverage as the test cases generated by CompleteTest, more work needs to be done on the efficiency of JPF / SPF optimising its search algorithm.

(5)

Abstract iii

List of Figures vi

List of Tables vii

List of Code Listings viii

1 Introduction 1

1.1 Problem Stated and Research Goals . . . 2

1.2 Research Methodology . . . 4

1.3 Expected Outcome . . . 5

1.4 Conclusion and Future Work . . . 6

1.5 Related Work . . . 7

1.6 Thesis Overview . . . 9

2 Preliminaries 10 2.1 Programmable Logic Controllers . . . 10

2.2 Function Block Diagram and IEC 61131-3 . . . 11

2.3 Software Testing . . . 12

2.4 Model Checking . . . 19

2.5 Symbolic Execution . . . 21

2.6 Java Path Finder . . . 22

2.7 Mutation Analysis . . . 27

3 Function Block Diagram Translation 29 3.1 Data Types . . . 29 3.1.1 Numeric Literals . . . 29 3.1.2 Character Literals . . . 32 3.1.3 Duration Literals . . . 35 3.1.4 Summary . . . 38 3.2 Functions . . . 39 3.2.1 Conversion Functions . . . 40 3.2.2 Numerical Functions . . . 41 3.2.3 Character Functions . . . 42 3.2.4 Duration Functions . . . 43 iv

(6)

3.2.5 Other Functions . . . 43

3.2.6 Summary . . . 43

3.3 Function Blocks . . . 44

3.3.1 Bistable Function Blocks . . . 44

3.3.2 Edge Detection Function Blocks . . . 45

3.3.3 Counter Function Blocks . . . 46

3.3.4 Timer Function Blocks . . . 47

3.3.5 Summary . . . 49

3.4 Discussion . . . 49

4 Test Case Generation 52 4.1 Model Checking Function Block Diagrams . . . 52

4.2 Example: Fan Control System . . . 53

4.2.1 Analysing Function Block Diagram . . . 53

4.2.2 Creating Java Program Representation . . . 55

4.2.3 Instrumenting Java Path Finder . . . 56

4.2.4 Deriving Test Cases . . . 58

4.2.5 Evaluating Test Cases . . . 60

4.3 Example: Complex Timer On Delay . . . 61

4.3.1 Analysing Function Block Diagram . . . 62

4.3.2 Creating Java Program Representation . . . 63

4.3.3 Instrumenting Java Path Finder . . . 64

4.3.4 Deriving Test Cases . . . 66

4.3.5 Evaluating Test Cases . . . 68

4.4 Discussion . . . 69 5 Evaluation 71 5.1 Coverage . . . 71 5.2 Efficiency . . . 73 5.3 Effectiveness . . . 74 5.4 Discussion . . . 77 6 Conclusion 79

A Using Java Path Finder ix

B Java Program Representations xi

C Symbolic Execution Tree xv

Bibliography xviii

(7)

1.1 Research Methodology . . . 5

2.1 Simple Architecture of a Programmable Logic Controller [1] . . . 11

2.2 Simple Function Block Diagram Program . . . 12

2.3 Simple Graph Abstraction of a Program . . . 13

2.4 Relationship among Graph-Based Coverage Criteria [2] . . . 15

2.5 Relationship among Logic-Based Coverage Criteria [2] . . . 19

2.6 Model Checking Process . . . 20

2.7 Software Testing versus Model Checking . . . 21

2.8 Program with Simplified Symbolic Execution Tree [3] . . . 22

4.1 Fan Control System by Bombardier . . . 55

4.2 Compressed and Analysed Symbolic Execution Tree . . . 61

4.3 Complex Timer On Delay by Bombardier . . . 63

C.1 Symbolic Execution Tree . . . xvi

C.2 Analysed Symbolic Execution Tree . . . xvii

(8)

2.1 Generated Test Cases using Predicate Coverage . . . 16

2.2 Generated Test Cases using Clause Coverage . . . 16

2.3 Generated Test Cases using Combinatorial Coverage . . . 17

2.4 Generated Test Cases using Active Clause Coverage . . . 18

3.1 Time Literals in the IEC 61131-3 standard [4] . . . 35

3.2 Data Types in the IEC 61131-3 standard [4] . . . 38

5.1 Predicate Coverage of Test Cases by CompleteTest and JPF / SPF . . 72

5.2 Number of Test Cases by ComepleteTest and JPF / SPF . . . 74

5.3 Mutation Analysis for FanControlSystem.java . . . 76

5.4 Mutation Analysis for ComplexTimerOnDelay.java . . . 76

(9)

2.1 Random.java . . . 24

2.2 Output of Java Path Finder instrumenting Random.java . . . 25

2.3 SymbolicExecution.java . . . 26

2.4 Output of Java Path Finder instrumenting SymbolicExecution.java . . . . 27

3.1 NumericLiteral.java . . . 31 3.2 CharacterLiteral.java . . . 33 3.3 DurationLiteral.java . . . 36 3.4 BistableFunctionBlock.java . . . 44 3.5 EdgeDetectionFunctionBlock.java . . . 45 3.6 CounterFunctionBlock.java . . . 46 3.7 TimerFunctionBlock.java . . . 47 4.1 FanControlSystemDriver.java . . . 56 4.2 FanControlSystemDriver.jpf . . . 58

4.3 Output of Java Path Finder instrumenting FanControlSystem.java . . . . 59

4.4 Output of CoverageAnalyser instrumenting FanControlSystem.java . . . . 60

4.5 ComplexTimerOnDelayDriver.java . . . 64

4.6 ComplexTimerOnDelayDriver.jpf . . . 65

4.7 Output of Java Path Finder instrumenting ComplexTimerOnDelay.java . 66 4.8 Output of CoverageAnalyser instrumenting ComplexTimerOnDelay.java . 67 B.1 SymbolicExecution.java . . . xi

B.2 TimerOnDelay.java . . . xiv

(10)

Introduction

Programs for safety-critical software components are often written in graphical or textual languages. They are designed by control engineers and used in Programmable Logic Controller (PLC), e.g. avionics, nuclear power plants or transportation systems. One of the languages defined by the International Electrotechnical Commission (IEC) within the IEC 31131-3 standard [4] for PLCs is Function Block Diagram (FBD). It uses a set of blocks, e.g. bitwise operations and comparison, and connects those individual blocks through lines to represent the continuous flow of information [5]. FBD is a commonly used language to design PLCs. It is used in a large number of industries with a global market of approximately $8.9 billion in 2007 [6].

Testing FBD programs for safety-critical software components is of significant import-ance [2]. Their failure or malfunction might result in a serious outcome and cause severe damage. Therefore, testing the quality and reliability of safety-critical software compon-ents is considered as the most important task within the development process [7]. To ensure an adequate quality and reliability for a safety-critical software component, a cer-tain degree of certification is required by the industry for operation. Typically, control engineers are required to validate the safety-critical software components against their specifications and to demonstrate their correctness. They must demonstrate compli-ance with strict quality and reliability requirements, including functional and structural testing [8].

Automated test case generation for PLC programs is complicated [9]. The software needs to be transformed from the graphical program code, i.e. FBD to actual program code, i.e.

(11)

C before it can be compiled and executed on the desired PLC. This is done using special tools provided by the PLC vendors. Integrating structural coverage criteria to these tools is difficult because structural coverage criteria is analysed at the actual program code, whereas tests are designed at the graphical program code [9]. Additionally, the code generation scheme is not standardised. Consequently, coverage of tests may be different from one vendor to another [10].

For this particular reason, an approach for automated test case generation [11] named

CompleteTest1 was developed previously within the Software Testing Laboratory2

at M¨alardalen University in V¨aster˚as. CompleteTest uses a model checking tool

named Uppaal3 to analyse FBD programs and generates test cases to complement

FBD program testing. It identifies a minimum number of test cases satisfying maximum structural coverage criteria required by the industry for operation [12].

An evaluation of this automated test case generation approach [13] was carried out by an extensive empirical study. It was applied to 157 real-world industrial FBD programs developed by Bombardier, a major rail vehicle manufacturer located in Sweden. The result showed that model checking is suitable for handling structural coverage criteria and acts as a useful addition to the testing process of FBD programs. Despite its success at Bombardier, the automated test case generation approach is sensitive to the tested program and depends on the number of input parameters.

1.1

Problem Stated and Research Goals

Uppaal is a model checking tool that is used to analyse the representative model of the FBD program. The model is derived automatically to simulate the program execution paths of the FBD program. Uppaal’s main limitation, when used for the automated test case generation approach, is the lack of direct support for WORD and REAL types.

Java Path Finder4 (JPF) is an another model checking tool developed by the National

Aeronautics and Space Administration (NASA). In comparison to Uppaal, JPF sup-ports additional types, e.g. Real and String, and can be used with an extension that

1

CompleteTest is available at: http://www.completetest.org/

2

Software Test Laboratory: http://www.es.mdh.se/research-groups/27-Software_Testing_ Laboratory

3

Uppaal is available at http://www.uppaal.org/

4

(12)

supports symbolic execution named Symbolic Path Finder (SPF). SPF has already been used efficiently at NASA to generate test case input [14] and has also been used success-fully to test flight software components [3].

Symbolic execution analyses a program and characterise the conditions under which each program execution path is taken [15]. An interpreter follows and determines symbolic values in terms of expressions and constraints in terms of conditions. Compared to other testing techniques, symbolic execution is more powerful than traditional execution

techniques [16]. Symbolic execution reasons branch-by-branch other than

input-by-input and has become an important technique in automated test case generation. Its major strength consists of creating test cases that satisfy certain coverage criteria while providing concrete sets of input parameters[16]. These sets of input parameters may be used to trigger a particular program execution path to confirm errors independently of the symbolic execution tool.

For this particular reason, we investigate how to translate a FBD program to a Java program representation suitable for model checking using JPF / SPF. The key challenge is to ensure that the Java program representation implements the same internal program structure as the given FBD program. Experiments will show how to instrument JPF / SPF to automate generate test cases. The generated test cases must satisfy the require-ments and regulations for safety-critical software components provided by the industry for operation. Further, we evaluate the coverage, the efficiency and the effectiveness of JPF / SPF compared to CompleteTest. This motivates the following three research questions:

Research Question 1 (RQ1) How to translate FBD programs to Java program rep-resentative suitable for model checking using JPF / SPF?

Research Question 2 (RQ2) How to instrument JPF / SPF for automated test case generation?

Research Question 3 (RQ3) How do the test cases generated by CompleteTest compare to the test cases generated by JPF / SPF in terms of coverage, efficiency and effectiveness?

(13)

1.2

Research Methodology

In 2012, a research-driven cooperation between Bombardier and M¨alardalen University

was established. This cooperation focuses on software testing and drives automated test case generation of safety-critical software components. Bombardier uses the

ex-pertise in software engineering research of M¨alardalen University to improve the state

of practise in automated test case generation of safety-critical software components in

railway control and protection applications. Likewise, M¨alardalen University uses the

industrial openness of Bombardier to disclose research results, i.e. the use of dedicated tooling platforms [17]. As illustrated in Figure 1.1, the collaboration started out with questions on how to test safety-critical software components and continues to iterate through certain steps according to the scientific method presented in [18].

At M¨alardalen University, background research on existing solutions avoids starting

from scratch. It ensures current state of the art and current state of practice according to literature and industrial studies. Based on this information, hypotheses are stated. These hypotheses related to the initial question drive research on automated test case generation of safety-critical software components.

Further, experiments are carried out to test the hypotheses. In this particular case, we translate FBD programs to Java program representatives suitable for model checking using JPF / SPF. Experiments will show how to instrument JPF / SPF to automate generate test cases. Further, we evaluate the coverage, the efficiency and the effect-iveness of JPF / SPF compared to CompleteTest. Evaluating the result will reveal whether the findings supports the initial hypotheses or not. Sometimes, troubleshooting is necessary to obtain valuable results iterating back to the experiment phase.

Finally, the evaluated results of the carried out experiment are going to be discussed and communicated within a thesis report. This result can fully or partially line up with the initial hypotheses and may require some alignment. However, the thesis may be used as significant background research for future research to iterate through the scientific method once again.

(14)

Figure 1.1. Research Methodology

1.3

Expected Outcome

First of all, we manually translate some selected FBD programs to Java program rep-resentations suitable for model checking using JPF / SPF to explore possibilities and limitations. Bombardier, a major rail vehicle manufacturer in Sweden, is going to provide some real-world industrial programs. Instrumenting JPF / SPF allows to analyse those Java program representations suitable for model checking using JPF / SPF to charac-terise the conditions under which each particular program execution path is taken. As a result, JPF / SPF is going to generate test cases including concrete input parameters to achieve maximum coverage for the translated FBD programs. Further, we compare the test cases generated by JPF / SPF to the test cases generated by CompleteTest. This evaluation is going to focus on coverage, efficiency, and effectiveness.

Code coverage is going to tell how close JPF / SPF comes to generate test cases satisfying structural coverage criteria, e.g. decision coverage (DC) or clause coverage (CC). But satisfying structural coverage criteria may not always be achievable due to the internal

(15)

for automated test case generation until full PC is reached. A time threshold may be applied, though.

Efficiency is going to tell how long it takes JPF / SPF to provide test cases that meet structural coverage criteria, e.g. DC and CC. As already mentioned before, structural coverage criteria may not always be possible. This requires a threshold to stop the search algorithm for automated test case generation. The execution time of the automated test case generation is also highly depended on the analysed program. Programs with relatively low complexity may require a significantly short execution time than programs with relatively high complexity. Therefore, selecting a representative set of Bombardier’s real-industry programs is of significant importance.

Effectiveness is going to tell how well JPF / SPF performs in detecting faults. To compare this aspect against CompleteTest, we inject faults into existing software components using mutation analysis. Mutation analysis modifies the software compon-ent in small steps. Each modified version, called mutant represcompon-ents a fault within the software component. When verified with the initial test cases, some test cases may fail due to the mutant’s modification. This is called ’killing’ mutants. Consequently, the test cases that ’kill’ the most mutants are considered as the more effective ones because they detected a larger amount of software modifications.

The results are going to be compared against the automated test case generation

ap-proach [11] carried out within the Testing Laboratory at M¨alardalen University. This

automated test case generation approach was evaluated [13] based on 157 real-world industrial programs developed by Bombardier. It showed that model checking is suit-able for handling structural coverage criteria and acts as a useful addition to the testing process of FBD programs.

1.4

Conclusion and Future Work

Two FBD programs for safety-critical software components provided by Bombardier were translated to Java program representations suitable for model checking using JPF / SPF. Instrumenting those Java program representations requires Java test drivers to simulate the cyclic execution of the function blocks, i.e. timers. Thereby, a while-loop executed the Java program representation indefinitely. Compared to CompleteTest, the test

(16)

cases generated by JPF / SPF aim to satisfy complete path coverage (CPC), but may result in an infinite number of program execution paths and needs to be terminated. Therefore, JPF / SPF in considered as less efficient because of the huge number of generated test cases for the example containing function blocks. Control engineers need to ensure the correctness of the safety-critical software component by providing expected test output to test inputs. Therefore, a larger amount of generated test cases results in a more time-consuming process to choose an appropriate subset of test cases. Even though the test cases generated by JPF / SPF are less effective, they identify more injected faults and achieve a higher mutation score compared to the test cases generated by CompleteTest.

More work needs to be done in reducing the number of test cases for cyclic executions. This may be done by either using an algorithm to obtain the minimum number of test cases satisfying the required coverage criteria after all program execution paths have been explored or by optimising the search algorithm to make it aware of the internal state of the function block while exploring all program execution paths. Additionally, Gay et al. [19] argues that the use of structural coverage criteria for safety-critical software components is questionable for the explored domain and proposes to use structural test-ing as a supplement for random testtest-ing. This may be investigated for coverage criteria using FBD programs using JPF / SPF to explore all program execution paths randomly to compare them to them carried out results. Recently, an automated framework [20] was developed that executes and evaluates a representative set of programming lan-guage concepts to highlight strength and weaknesses for symbolic execution-based test input generation tools. Their performed experiment compares five different symbolic execution-based test input generation tools and shows that JPF / SPF has issues with some conditions and loops. Therefore, it may be worth to take a closer look at the other evaluated symbolic execution-based test input generation tools that performed better than JPF / SPF, i.e. EvoSuite and Pex.

1.5

Related Work

Methods for automated test case generation using model checkers were initially proposed by Callahan et al. [21] and Engels et al. [22]. The classic approach of negating the specification of the software component to generate test cases according to the original

(17)

specification has been adapted to a variety of application and is characterised in a taxonomy by Utting et al. [23] and summarised in an survey by Fraser et al. [7]. Despite the encountered problems of Amman et al. [24] in using model checkers for automated test case generation for predicate coverage (PC), an automated test case generation approach named CompleteTest [13] was carried out recently within the Software

Testing Laboratory at M¨alardalen University. Similar to the work of Rayadurgam et al.

[25, 26], CompleteTest uses an alternative method that modifies the system model to automate generate test cases.

James C. King [27] introduced symbolic execution in 1976 as a new program analysis technique that received renewed interest in recent years due to algorithmic advances and increased availability of computational power and constraint solving technologies

[16]. P˘as˘areanu and Visser [28] provide a survey of some of the new research trends

in symbolic execution, Cadar et al. [29] review classical symbolic execution and some modern extensions and Chen et al. [30] list current challenges in the area of symbolic execution. More recently, Cseppento et al. evaluated different symbolic execution-based test tools [20].

Java Path Finder (JPF) is a model checker tool that has been used by Visser et al. [14] to automate generate test cases to achieve structural coverage criteria. It has been successfully used at Fujitsu Labs to test Web applications [31]. Previously, the symbolic execution extension of JPF named Symbolic Path Finder (SPF) was used to generate counterexamples to safety properties in concurrent programs with unspecified inputs [32]. Because JPF / SPF suffered from scalability, Staats et al. [33] worked on parallelisation of JPF / SPF. More recently, JPF / SPF was used to automate generate test cases for Android Apps by Mirzaei et al. [34] and was used to generate test cases satisfying modified condition / decision coverage (MC / DC) by Whalen et al. [35].

Testing FBD programs ranges from simulation-based approaches [36] to verifying the actual FBD program [37]. Enoiu et al. [13, 38] carried out an automated test case generation approach for railway control and protection applications and Lahtinen et al. [39, 40] developed an automatic test set generation approach for the nuclear engineering domain. Both approaches use a model checker named UPPAAL. In addition, Jee et al. [8] developed three new test coverage criteria for FBD program testing that focus on the data flow aspect of the FBD language.

(18)

In contrast, our work uses JPF / SPF to generate test cases satisfying the required coverage criteria required by the industry for operation. Additionally, we explore the capabilities of symbolic execution identifying possibilities and limitations of symbolic execution on FBD program testing

1.6

Thesis Overview

The goal of this thesis is to support control engineers who are required to validate safety-critical software components. They must demonstrate compliance with strict quality and reliability requirements provided by the industry for operation. One of those require-ments includes providing test cases that satisfy structural coverage criteria. But there has been little research on using coverage criteria for FBD programs. Previous work [13] devised an automated test case generation approach named CompleteTest that uses the model checker Uppaal to generate test cases satisfying the required coverage criteria. This automated test case generation approach aids the detection of faults in safety-critical software components, but requires FBD program specific guidance to provide applicable and efficient results. Java Path Finder (JPF) is an another model checker tool providing a extension named Symbolic Path Finder (SPF) that allows to explore all program execution paths using symbolic execution, a program analysis technique that has received renewed interest in recent years [29]. To our knowledge, there has been little research on using symbolic execution in the area of automated test case generation for FBD programs. Hence, we want to compare JPF / SPF to CompleteTest and explore its capabilities identifying possibilities and limitations of symbolic execution. The following research contributions are included in this master’s thesis:

• Guideline how to translate FBD programs to Java program representations suitable for model checking using JPF / SPF in Chapter 3.

• Instructions how to instrument JPF / SPF to generate test cases satisfying pre-dicate coverage (PC) in Chapter 4.

• Evaluation how JPF / SPF performs in terms of coverage, effectiveness and effi-ciency in Chapter 5.

(19)

Preliminaries

The following Sections give a general summary of the fundamentals required to un-derstand the outcome of the conducted research within the scope of this contribution. Section 2.2 describes Programmable Logic Controllers (PLCs) in safety-critical software components. Function Block Diagram (FBD) is a language used to implement those safety-critical software components and introduced in Section 2.2. Next, common test-ing techniques for software components are presented. Section 2.3 summarises software testing and Section 2.4 outlines model checking. A program analysis technique called symbolic execution is introduced in Section 2.5. Java Path Finder, a tool combining model checking and symbolic execution, is summarised in Section 2.6 briefly. Finally, Section 2.7 describes mutation analysis used to compare generated test cases in term of their ability to detect faults.

2.1

Programmable Logic Controllers

Programmable Logic Controllers (PLCs) are industrial computers with real-time cap-abilities that control highly complex automation processes [5]. They are optimised for control tasks in the industrial environment and consist of a Central Process Unit (CPU), a programmable memory, several bus systems and a number of inputs and outputs (I/O) interfaces as illustrated in Figure 2.1 [1]. Typically, those I/O interfaces connect the sys-tem with sensors and control the environment through motors and solenoids. Digital I/O signals are discrete and represent, e.g. a simple on and off switch, whereas analog

(20)

Figure 2.1. Simple Architecture of a Programmable Logic Controller [1]

signals are equivalent to values and reflect, e.g. a voltage representations of a temper-ature. The CPU executes a program written in one of the five languages defined by the International Electrotechnical Commission (IEC) within the IEC 61131-3 standard [4]. It monitors the input interfaces, executes the program and updates the output interfaces continuously.

PLCs are commonly used within safety-critical software components of avionics, nuclear power plants or transportation systems. The modularisation of the PLCs allows to mix and match different types of I/O devices to best suit their application. They are highly customisable and relatively cheap compared to custom-build controller design. On the downside, PLCs lack standardisation because they do not fulfil the IEC 61131-3 standard entirely. For this particular reason, each PLC usually provides a document describing which parts of the IEC 61131-3 standard are implemented and which parts of the IEC 61131-3 standard are not covered.

2.2

Function Block Diagram and IEC 61131-3

Function Block Diagram (FBD) is a graphical language that is commonly used to design PLCs [5]. FBD programs describe the relationship between several input parameters entering from the left and a number of output variables emerging from the right as

(21)

Figure 2.2. Simple Function Block Diagram Program

illustrated in Figure 2.2 [1]. A set of function, e.g. conversion, logarithmic etc., function blocks, e.g. counter, timer, etc., or self-implemented blocks are used to compute the given task of the PLC. The latter can be supplied by the manufacturer of the PLC, defined by the control engineer or predefined by a library.

FBD is one of five languages for logical or control configurations defined within the IEC 61131-3 standard [4] that was originally published by the International Electrotechnical Commission (IEC) in 1993 and revised in 2013. Other defined languages are Ladder Diagram (LD), Structured Text (ST), Instruction List (IL) and Sequential Function Chart (SFC). They can be separated into graphical (FBD, LD, ST) and textual (IL, SFC) languages.

2.3

Software Testing

Software testing takes approximately 50% of the development time and requires about 50% of the development costs [41]. It is expensive and time-consuming, but plays an important role in software development [2]. It involves executing the software component and checking the result against the expected outcome to evaluate whether the tested software component meets its specification. According to Beizer [42], software testing reduces the risk of using the software and is a mental discipline that helps to develop higher quality software. But software testing can only show the presence of failures, not their absence [2, 43].

Structural testing, also known as implementation-based testing, focuses on testing the structural elements of a given software component such as statements or decisions. It often is referred to as ’white-boy’, ’glass-box’ or ’clear-box’ testing because the software

(22)

Figure 2.3. Simple Graph Abstraction of a Program

tester needs to know how the tested software component is implemented. In addition, the software tester also needs to have the knowledge about what the tested software component is suppose to do according to its specification. Otherwise the software tester is not going to be able to verdict whether the software component works right or wrong. Depending on the chosen coverage criteria, different coverage items are analysed. De-cision coverage (DC), for example, makes sure that every deDe-cision within a software component evaluates to false and true throughout a number of test cases. These test

cases have a certain coverage score (CoverageAC) that represents how many of the

exist-ing coverage items (T estedAC(S)) have been covered (T estedAC(T, S)) and is calculated

as described in equation 2.1. CoverageAC= |T estedAC(T, S)| |ExistingAC(S)| (2.1)

Graph-Based Coverage

Graph-based coverage criteria obtain a graph abstraction of a software component to produce coverage items in terms of nodes and edges as illustrated in Figure 2.3. Test requirements are met by visiting a particular node or by traversing a particular execution path.

Node coverage (NC) or also referred to as statement coverage traverses each reachable node at least once. The graph abstraction illustrated in Figure 2.3 is covered by test cases satisfying NC if nodes 0, 1, 2, 3, 4, 5 and 6 are visited. Test cases satisfying NC

(23)

include the execution paths [0, 1, 2, 3, 6] and [0, 1, 2, 4, 5, 4, 6]. Certain execution paths, e.g. execution subpath 0, 1, may not be covered though.

Edge coverage (EC) or also referred to as branch coverage visits each edge or execution path with length up to one. Likewise, test cases satisfying EC visit nodes 0, 1, 2, 3, 4, 5 and 6 of the graph abstraction illustrated in Figure 2.3. Test cases satisfying EC include the execution paths [0, 1, 2, 3, 6] and [0, 2, 4, 5, 4, 6]. Compared to the test cases satisfying NC, the execution subpath 1, 2 is also traversed.

Edge-pair coverage (EPC) visits each execution path with length up to two. It subsumes the test cases satisfying EC because it also visits nodes 0, 1, 2, 3, 4, 5 and 6 of the graph abstraction illustrated in Figure 2.3. In addition, test cases satisfying EPC cover the execution subpaths 4, 5, 4 and 5, 4, 5. As a result, test cases satisfying EPC include the execution paths [0, 1, 2, 3, 6], [0, 1, 2, 4, 6], [0, 2, 3, 6] and [0, 2, 4, 5, 4, 5, 4, 6]. Prime path coverage (PPC) traverses each maximum simple execution path. A maximum simple execution path is not an execution subpath of any other simple exe-cution path. Expect of the start node and the end node, no nodes are allowed to be appear more than once within the execution path. Test cases satisfying PPC include the execution paths [0, 1, 2, 3, 6], [0, 1, 2, 4, 5], [0, 1, 2, 4, 6], [0, 2, 3, 6], [0, 2, 4, 5], [0, 2, 4, 6], [5, 4, 6], [4, 5, 4] and [5, 4, 5].

Complete path coverage (CPC) traverses all execution paths and subsumes all other graph-based coverage criteria. Obviously, a simple loop is going to create an in-finite number of coverage items in terms of execution paths that cannot be covered in polynomial time. Test cases satisfying CPC include the execution paths [0, 1, 2, 3, 6], [0, 1, 2, 4, 6], [0, 1, 2, 4, 5, 4, 6], [0, 1, 2, 4, 5, 4, 5, 4, 6], [0, 1, 2, 4, 5, 4, 5, 4, 5, 4, 6], etc.. Visit-ing only a subset of the execution paths may be useful to test specific software behaviour though. This is also known as specified path coverage (SPS).

Figure 2.4 gives a brief overview of different graph-based coverage criteria. Graph-based coverage criteria can further be divided into data-flow coverage criteria on the left-hand side and control-flow coverage criteria on the right-hand side. The data-flow coverage criteria are referred to as All Definitions, All Uses, and All Definition Uses Paths. For further information on data-flow coverage criteria, we refer the reader to [44]. However,

(24)

Figure 2.4. Relationship among Graph-Based Coverage Criteria [2]

test cases satisfying CPC stress the system under test the most and subsume all other graph-based coverage criteria.

Logic-Based Coverage

Logic-Based coverage criteria evaluates logical expressions and produces coverage items in terms of predicates and clauses. A predicate is an expression that evaluates to a boolean value and may contain several clauses that are separated by logical operators (∧, ∨). These clauses may consist of boolean variables and non-boolean variables that are compared using comparison operators (>, <, =, ≥, ≤, 6=) or function calls as illustrated in the equation below. Test requirements are met by evaluating the predicate or a number of clauses to false and true.

(a > b ∧ c = 10) ∨ (D ∧ p(x)) (2.2)

Predicate coverage (PC) also referred to as decision coverage evaluates whether each predicate evaluated to false and true. Test cases providing the input parameters a = 2, b = 1, c = 10, D = f alse, p(x) = f alse and a = 1, b = 2, c = 5, D = true, p(x) = true

(25)

Table 2.1. Generated Test Cases using Predicate Coverage

id clause result

a >b c=10 D p(x)

1 1 1 0 0 true

2 0 0 0 0 false

Table 2.2. Generated Test Cases using Clause Coverage

id clause result

a >b c=10 D p(x)

1 1 1 0 0 true

2 0 0 1 1 true

satisfy PC for the example within Figure 2.2 as illustrated in table 2.1, but do not exercise each individual clause.

Clause coverage (CC) evaluates whether each clause of every predicate evaluated to false and true. Compared to PC, each individual clause is exercised. The test cases for the example within Figure 2.2 illustrated in table 2.1 fail to satisfy CC because D and p(x) never evaluate to true. Instead, the test cases providing the input parameters a = 1, b = 2, c = 10, D = f alse, p(x) = f alse and a = 2, b = 1, c = 20, D = true, p(x) = true satisfy CC for the example within Figure 2.2 as illustrated in table 2.2. Combinatorial coverage (CoC) also referred to as Multiple condition coverage eval-uates each possible combination of false and true values. Thus, a predicate with n

independent clauses has 2n possible combinations of false and true input parameters.

This, however, is impractical for predicates containing more than a few independent clauses [44]. The example within Figure 2.2 contains of four individual clauses.

Con-sequently, 24 = 16 test cases are required to satisfy CoC in which the clauses a>b,

c = 10, D and p(x) evaluate to false and true for every possible combination of input parameters as illustrated in table 2.3.

Active clause coverage (ACC) also referred to as modified condition / decision coverage (MC/DC) evaluates whether each major clause determines the value of its predicate to false and true. A major clause is the clause the current test case is focusing on. All the other clauses are referred to as minor clauses. Changing the value of the major clause, changes the outcome of its predicate. Considering the example within

(26)

Table 2.3. Generated Test Cases using Combinatorial Coverage id clause result a >b c=10 D p(x) 1 1 1 1 1 true 2 1 1 1 0 true 3 1 1 0 1 true 4 1 1 0 0 true 5 1 0 1 1 true 6 1 0 1 0 false 7 1 0 0 1 false 8 1 0 0 0 false 9 0 1 1 1 true 10 0 1 1 0 false 11 0 1 0 1 false 12 0 1 0 0 false 13 0 0 1 1 true 14 0 0 1 0 false 15 0 0 0 1 false 16 0 0 0 0 false

Figure 2.2, major clause a>b generates the test cases that provides the input parameters a = 2, b = 1, c = 10, D = f alse, p(x) = f alse and a = 1, b = 2, c = 10, D = f alse, p(x) = f alse. This major clause determines the predicate to false and true for minor clause c = 10 equals true and for minor clause D and p(x) equals false. In total, eight test cases are required to satisfy ACC for the example within Figure 2.2 as shown in table 2.4. Test case one and test case three as well as test case five and test case seven are identical. Consequently, only six test cases are required to satisfying ACC including the following input parameters:

• a = 2, b = 1, c = 10, D = f alse, p(x) = f alse • a = 1, b = 2, c = 10, D = f alse, p(x) = f alse • a = 2, b = 1, c = 0, D = f alse, p(x) = f alse • a = 1, b = 2, c = 0, D = true, p(x) = true • a = 1, b = 2, c = 0, D = f alse, p(x) = true • a = 1, b = 2, c = 0, D = true, p(x) = f alse

(27)

Table 2.4. Generated Test Cases using Active Clause Coverage id clause result a >b c=10 D p(x) 1 1 1 0 0 true 2 0 1 0 0 false 3 1 1 0 0 true 4 1 0 0 0 false 5 0 0 1 1 true 6 0 0 0 1 false 7 0 0 1 1 true 8 0 0 1 0 false

Figure 2.5 gives a brief overview of the relationship among different logic-based coverage criteria. Test cases satisfying CC stress the system under test the most, but are imprac-tical when applied to a few independent clauses [44]. Logic-based coverage criteria has received a steadily growth in recent years [2] and is required by the avionics industry for operation of safety-critical software components [45]

Additionally, three variations of ACC coverage criteria are available. Compared to

ACC, they omit the fact that minor clauses need to have the same value when the major clause evaluates to false or true. These variations are referred to as general active clause coverage, correlated active clause coverage and restricted active close coverage. A complementary criteria to ACC coverage criteria evaluates that each major clause does not determine the value of its predicate and is also referred to as inactive clause coverage (ICC). Also, ICC can further be distinguished into two variations called general inactive clause coverage (GICC) and restricted inactive clause coverage (RICC). For further information on test cases satisfying GICC and RICC, we refer the reader to [44]. Test cases satisfying CC do not subsume test cases satisfying PC and vice versa. The predicate a ∧ b is satisfied for PC using two test cases providing the input parameters x = true, y = f alse and x = f alse, y = f alse. Likewise, this predicate is satisfied for CC using two test cases providing the input parameters x = true, y = f alse and x = f alse, y = true.

(28)

Figure 2.5. Relationship among Logic-Based Coverage Criteria [2]

2.4

Model Checking

Model checking is a technique to test whether a model, a representation of the implemen-ted behaviour, meets its properties, a description of the intended behaviour. Usually, these models embed some faults [15] due to human error. Model checking, however, re-veals those discrepancies between the model and the properties as illustrated in Figure 2.6. The model checker analyses the given model and returns a witness if the model satisfies the property. But it is impossible to ensure the given properties’ completeness or its correctness [46]. If the model does not satisfy the property, a counterexample is generated. The generated counterexample contains detailed information why the model did not satisfy the property and may be used to trace back the error in the model or to correct the property.

Most safety-critical software components are control-flow orientated [47] and are extrac-ted from program code. They are checked against their properties that are expressed in temporal logic. Finite-state machines are used to explore the entire state space of a the given model to show satisfaction or violations towards its properties. But models do not necessaryily have to be extracted from program code. They can also be extracted from system specifications and design [15].

Significant progress on model checking has been made over the past years [7]. Despite the constantly increasing size of models that can be handled, issues in scalability and

(29)

Figure 2.6. Model Checking Process

performance dealing with an infinite number of program execution paths remain [46]. The main challenge, however, consists in creating models from specifications. Creating those models manually is considered as a complicated and most difficult task [7].

Software Testing versus Model Checking

Software testing verifies a given software component by executing it with given input parameters to check the result against an expected outcome. Its main goals is to reduce the risk of using the software component by covering the input space [42]. To verdict whether the software component works according to its specifications, the right test input parameter and the right test oracle need to be identified. Choosing the right test input parameter depends on the selected coverage criteria as described in Section 2.3. Checking the implemented behaviour is affected by the available knowledge about the system. If the expected result of a test case has not been predefined, chances are that a plausible, but erroneous, result will be interpreted as a correct result [41].

Model checking pushes the level of automation even further by automating the design, not just the execution, of software testing [43]. It does not depend on the right test input and the right test oracle and explores all program execution paths of the software component. Figure 2.7 compares software testing to model checking in terms of exploring the program execution paths as described by Beizers [42]. Model checking also identifies

(30)

Figure 2.7. Software Testing versus Model Checking

missing program execution paths that have not been covered by the software component [41]. But model checking may run out of memory before all program execution paths are explored when used for more complex systems.

2.5

Symbolic Execution

James C. King [27] introduced symbolic execution in 1976 as a new program analysis technique that received renewed interest in recent years due to algorithmic advances and increased availability of computational power and constraint solving technologies [29]. Today, symbolic execution is used in program analysis, in automated test cases generating, and in formal verification of program correctness [15]. Compared to dynamic execution, symbolic execution represents values of program parameters as symbolic ex-pressions and resolves them later using constraint solvers. These symbolic exex-pressions are generated by analysing the internal structure of the code.

Symbolic execution reasons branch-by-branch other than input-by-input which is com-monly used in software testing. It tries to identify conditions under which each partic-ular program execution path is taken and determines whether certain path conditions are satisfiable or not. A symbolic state maps the program variables, e.g. input para-meter, internal variables, etc., to symbolic values and holds the path condition that accumulates the constraints of the associated program execution path [29]. The path condition is a boolean formula over the symbolic values, describing the constraints which the inputs must satisfy in order to follow the particular associated program execution path [3]. Constraints are then solved by using a constraint solver to generate test case input parameters that take the same program execution path as the symbolic execution. Symbolic execution, however, may result in an infinite number of program execution

(31)

Figure 2.8. Program with Simplified Symbolic Execution Tree [3]

paths for program that contain loops or recursions. Therefore, a depth-limit of program execution paths or a time threshold needs to be configured.

The program illustrated on the left side in Figure 2.8 returns the distance between two input integers a and b. Applied to common software testing techniques, a test case covers only one program execution path. Symbolic execution on the other hand, will try to cover all program execution paths as illustrated in the simplified symbolic execution tree on the right side in Figure 2.8. Symbolic execution maps the symbolic values α to a and β to b and sets the initial path condition to true. At each conditional statement, the path condition is updated with constraints on the symbolic values of the associated program execution path. If the path condition becomes false, the path is not satisfiable and symbolic execution will terminate reasoning the associated path. The simplified symbolic execution tree includes the not satisfiable path number two and an assertion violation in path four.

2.6

Java Path Finder

Java Path Finder1 (JPF) is a model checker developed by the National Aeronautics and

Space Administration (NASA) that provides a number of different extensions. The JPF core includes a Java Virtual Machine (JVM) that executes a given Java program and explores all program execution paths, checks for property violation, e.g. deadlocks, and identifies race conditions or unhandled exceptions. To test a Java program code, JPF

(32)

needs the specification of the Java program as input property and returns a report. This report includes information about whether the properties hold and provides the program execution path in case of an error.

Model checkers are susceptible to an infinite number of program execution paths [7]. Compared to other model checking tools, JPF deals with an infinite number of program execution paths using state matching and backtracking. State matching takes heap and thread-stack snapshots and checks each time JPF reaches a new program state whether it has already seen a similar program state. If this turns out to be true, JPF abandons this program execution path. Then, JPF may backtrack to a different program execution path that has not been explored yet and continues to analyse the Java program from there. This can also be achieved by re-executing the program [48].

Code listing 2.1 illustrated a simple Java program that generates two random values and performs some mathematical operations. Executing this Java program with common software testing techniques may never encounter any potential problems. Depending on the random seed 42, parameter a may evaluates to 0 and parameter may b evaluates to 2. This combination of input parameters causes a java.lang.ArithmeticException because the Java tries to divide a by b + a − 2 which, in this case, evaluates to zero. Chances to identify this specific fault are relatively low when using common software testing techniques. The result of the randomly generated numbers is going to change between two runs and every run is going to test just one single combination of parameter a and parameter b.

(33)

 

1 i m p o r t j a v a . u t i l . Random ; 2

3 p u b l i c c l a s s Rand {

4 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { 5 Random random = new Random ( 4 2 ) ; 6 7 i n t a = random . n e x t I n t ( 2 ) ; 8 System . o u t . p r i n t l n (” a=” + a ) ; 9 10 i n t b = random . n e x t I n t ( 3 ) ; 11 System . o u t . p r i n t l n (” b=” + b ) ; 12 13 i n t c = a / ( b+a −2) ; 14 System . o u t . p r i n t l n (” c=” + c ) ; 15 } 16 }   Listing 2.1. Random.java

Running the Java program illustrated in code listing 2.1 using the model checking cap-abilities of JPF explores all program execution paths. JPF stops analysing the program code as soon as it detects an error or until there are no choices left. It starts by choos-ing parameter a equals 0 and parameter b equals 0 which results in c equals 0. Then, JPF recognises that there are more choices left and backtracks to choose parameter b equals 1 which will result in c equals 0. Next, JFP will backtrack once again and choose parameter b equals 2 which will cause a java.lang.ArithmeticException because of a division by zero (b + a − 2 equals zero). After exploring all program execution paths, JPF will generate a report as illustrated in code listing 2.4. This report includes inform-ation about the chosen input parameters and provides more details on the encountered problem given by the input parameters b equals 2 and a equals 0.

(34)

  J a v a P a t h f i n d e r v7 . 0 − (C) RIACS/NASA Ames R e s e a r c h C e n t e r ================================================ s y s t e m u n d e r t e s t Rand . main ( ) ================================================ s e a r c h s t a r t e d : c o m p u t i n g c = a / ( b+a − 2 ) . . a=0 b=0 , a=0 => c=0 , b =0 , a=0 b=1 , a=0 => c=0 , b =1 , a=0 b=2 , a=0 ================================================ e r r o r 1 gov . n a s a . j p f . vm . N o U n c a u g h t E x c e p t i o n s P r o p e r t y j a v a . l a n g . A r i t h m e t i c E x c e p t i o n : d i v i s i o n by z e r o a t Rand . main ( Rand . j a v a : 1 6 ) }

 

Listing 2.2. Output of Java Path Finder instrumenting Random.java

Symbolic Path Finder

Symbolic Path Finder2 (SPF) is an extension of JPF for symbolic execution. It

com-bines symbolic execution, model checking and constraint solving for automated test case generation. JPF / SPF uses the analysis engine of JPF to check the internal structure of the code for possible errors. The values of the program code’s output variables are rep-resented as numeric constraints of the programs code’s input parameters. Later, these constraints are solved to generate concrete test case inputs parameters guaranteed to reach particular parts of the code.

Code listing 2.3 shows a simple Java program that takes two input parameters and per-forms some mathematical operations. It compares the input parameters against some constant variables and returns a numeric output variable.

2

A list of all extensions is available at http://babelfish.arc.nasa.gov/trac/jpf/wiki/projects/ start

(35)

  1 p u b l i c c l a s s S y m b o l i c E x e c u t i o n { 2 p u b l i c i n t doSomething (i n t x , i n t y ) { 3 i n t z = x + y ; 4 5 i f ( z > 0 ) { 6 z = 1 ; 7 } e l s e { 8 z = z − x ; 9 } 10 11 i f ( x < 0 ) { 12 z = z ∗ 2 ; 13 } e l s e i f ( x < 1 0 ) { 14 z = z + 2 ; 15 } e l s e { 16 z = −z ; 17 } 18 19 i f ( y < 5 ) { 20 z = z − 1 2 ; 21 } e l s e { 22 z = z − 3 0 ; 23 } 24 25 r e t u r n z ; 26 } 27 }   Listing 2.3. SymbolicExecution.java

Running the Java program illustrated in code listing 2.3 using JPF / SPF generates test cases satisfying complete path coverage. After exploring all program execution paths, JPF / SPF uses a constraint solver to generate concrete test case inputs and provides a test report as illustrated in code listing 2.4. This report contains information about the generated input parameters that guarantee that every program execution path of the Java program is reached. In addition, JPF / SPF also provides the expected outcome. This information may be used to create test cases for the software component then.

(36)

  J a v a P a t h f i n d e r c o r e s y s t e m v8 . 0 − (C) 2005 −2014 U n i t e d S t a t e s Government . A l l r i g h t s r e s e r v e d . ================================================ s y s t e m u n d e r t e s t S y m b o l i c E x e c u t i o n T e s t D r i v e r . main ( ) ================================================ ================================================ Method Summaries I n p u t s : x 1 SYMINT , y 2 SYMINT S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( − 1 , 2 ) −−> Return V a l u e : −10 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( − 4 , 5 ) −−> Return V a l u e : −28 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( − 1 , 2 ) −−> Return V a l u e : −10 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( − 4 , 5 ) −−> Return V a l u e : −28 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( 0 , 1 ) −−> Return V a l u e : −9 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( 0 , 5 ) −−> Return V a l u e : −27 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( 1 0 , − 9 ) −−> Return V a l u e : −13 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( 1 0 , 5 ) −−> Return V a l u e : −31 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( − 1 0 0 0 0 0 0 , − 1 0 0 0 0 0 0 ) −−> Return V a l u e : −2000012 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( − 1 0 0 0 0 0 0 , 5 ) −−> Return V a l u e : −20 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( 0 , − 1 0 0 0 0 0 0 ) −−> Return V a l u e : −1000010 S y m b o l i c E x e c u t i o n . d o S o m e t h i n g ( 1 0 , − 1 0 0 0 0 0 0 ) −−> Return V a l u e : 9 9 9 9 8 8  

Listing 2.4. Output of Java Path Finder instrumenting SymbolicExecution.java

2.7

Mutation Analysis

Mutation testing can be applied to various artefacts, but is primarily used as program-based method [2]. It is used as a technique to measure the quality of a set of test cases in terms of their ability to detect faults. Mutation testing modifies the software component by injecting faults into the safety-critical software component and checks whether the test cases are able to detect them. Each modified version is called a mutant and contains only a single mutation within the safety-critical software component. When verified with the initial test cases, certain test cases may fail due to the modification of the mutant. This is referred to as ’killing’ the mutant. Consequently, the test cases that detect more modifications and ’kill’ the most mutants are considered as more effective.

The key to successful mutation analysis are well defined mutation operators [2]. They are designed for each programming, specification or design language. Some mutants are equivalent to the original behaviour of the software component and cannot be ’killed’ by a test case. Detecting a modification or ’killing’ a mutant may further be refined in strongly and weakly ’killing’ a mutant. Mutants are ’killed’ strongly if the output of the mutants differs from the output of the original program. The output of weakly ’killed’

(37)

mutants do not differ from the original program but have a different internal state of execution [2].

Coverage in mutation analysis equates to detecting the injected faults of the original software component. The mutation score is defined as a value between zero and one

reflecting the number of ’killed’ mutants (K(sm)) in relation to all mutants (T (M )) as

described in equation 2.3.

M utationScore = K(sm)

(38)

Function Block Diagram

Translation

Regarding RQ1 on how to translate FBD programs to Java program representations suitable for model-checking using JPF / SPF, the following Chapter analyses the IEC 61131-3 standard in terms of data types in Section 3.1, functions in Section 3.2 and function blocks in Section 3.3. In the end, possibilities and limitations are discussed in Section 3.4.

3.1

Data Types

Values are represented in FBD programs as numeric literals, character literals or time literals and can take on one of the described data types below. Each data type specifies the range of possible variables, the operations that can be used upon, and the way specific values are stored.

3.1.1 Numeric Literals

There are numeric integer literals, e.g. +986, and numeric real literals, e.g. 3.1415926, available in the IEC 61131-3 standard. Numeric integer literals are described in the IEC 61131-3 standard as a decimal number or as a number of a particular base using the SINT, INT, DINT or LINT data type. An extended range of non-negative values may be

(39)

represented using the equivalent USINT, UINT, UDINT or ULINT data type. Numeric real literals are described as floating point numbers using the REAL and LREAL data type. Floating point numbers use a decimal point and may include an exponent to which the preceding number is multiplied to represent the desired numeric real literal. Numeric integer literals and numeric real literals may contain single underscore characters to highlighting specific aspects and may contain preceding sign to indicate whether the numeric literal is negative or positive.

Numeric integer and numeric real literals1 are represented in Java using the primitive

data types short, int, long, float and double. Single underscore characters must be re-moved though. Preceding signs for negative and positive numeric literals are interpreted in Java by default. Despite Java’s lack of support for unsigned numeric integer literals, Java covers almost the whole range of negative and positive numeric literals described in the IEC 61131-3 standard. A numeric literal is signed if it can represent both negative and positive numeric literals and is unsigned if it can only represent positive numeric literals. The Java primitive data types short, int and double data types use twice as many bits as the equivalent SINT, INT and DINT data types described in the IEC 61131-3 standard. Hence, unsigned numeric integers are not necessarily required in Java to represent the USINT, UINT and UDINT data types described in the IEC 61131-3 standard. The Java long primitive data type, however, uses the same amount of bits as the LINT data type described in the IEC 61131-3 standard. Therefore, translating an ULINT data type to an equivalent Java long primitive data type needs to be done carefully to avoid exceeding the range of positive numbers.

Numeric boolean literals1 are represented as integer literals with the value zero (0 ) or

one (1 ). Additionally, the keywords FALSE and TRUE may be used. Numeric boolean literals are interpreted in Java using the boolean primitive data type. The keywords FALSE and TRUE must be converted to the lower case representations false and true of Java. Zero (0 ) and one (1 ) values are not supported in Java and must be analysed to match the boolean primitive data type.

Numeric literals may also be represented as numbers of base two (binary), eight (octal) or sixteen (hexadecimal). The base, however, always uses the decimal notation. Binary,

e.g. 2#1110 0000 ; octal, e.g. 8#340 ; or hexadecimal literals1, e.g. 16#E0, contain the

(40)

specified base followed by a hash (#) and the actual number of the base. They are not supported in Java and must be parsed for translation to match the particular numeric literal representation in Java.

Typed literals1, e.g. INT#+986, BOOL#0 or INT#16#7FFF, must be analysed for

translation to identify the required numeric literal representation in Java. They contain the name of the elementary data type followed by a hash (#) and the actual number. Typed literals can also include duration and character literals described in Section 3.1.3 and Section 3.1.2.

Code listing 3.1 illustrates how to translate numeric literals described in the IEC 61131-3 standard to Java representation suitable for model checking using JPF / SPF. Under-score characters must be replaced for translation. Preceding symbols for negative and positive numeric literals are interpreted by default. Numeric boolean literals must be analysed for zero (0 ) and one (1 ) values and translated to FALSE and TRUE. Binary, octal and hexadecimal literals must be parsed according to their base before translation.

  1 p a c k a g e kunze . s e b . m a s t e r . t h e s i s . t r a n s l a t i o n . l i t e r a l ; 2 3 p u b l i c c l a s s N u m e r i c L i t e r a l { 4 5 p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) { 6 7 // +3.14159 2 6 8 S t r i n g n u m e r i c L i t e r a l = ” +3.1 4159 26 ”; 9 d o u b l e r e a l L i t e r a l = Double . p a r s e D o u b l e ( n u m e r i c L i t e r a l ) ; 10 System . o u t . p r i n t l n ( r e a l L i t e r a l ) ; 11 12 // 1 13 n u m e r i c L i t e r a l = ”TRUE”; 14 b o o l e a n b o o l L i t e r a l = B o o l e a n . p a r s e B o o l e a n ( n u m e r i c L i t e r a l ) ; 15 System . o u t . p r i n t l n ( b o o l L i t e r a l ) ; 16 17 // 2#1110 0 0 0 0 18 n u m e r i c L i t e r a l = ” 1 1 1 0 0 0 0 0 ”; 19 s h o r t s h o r t L i t e r a l = S h o r t . p a r s e S h o r t ( n u m e r i c L i t e r a l , 2 ) ; 20 System . o u t . p r i n t l n ( s h o r t L i t e r a l ) ; 21 22 // 8#340

(41)

23 n u m e r i c L i t e r a l = ” 340 ”; 24 i n t i n t L i t e r a l = I n t e g e r . p a r s e I n t ( n u m e r i c L i t e r a l , 8 ) ; 25 System . o u t . p r i n t l n ( i n t L i t e r a l ) ; 26 27 // 16#E0 28 n u m e r i c L i t e r a l = ”E0”; 29 l o n g l o n g L i t e r a l = Long . p a r s e L o n g ( n u m e r i c L i t e r a l , 1 6 ) ; 30 System . o u t . p r i n t l n ( l o n g L i t e r a l ) ; 31 } 32 }   Listing 3.1. NumericLiteral.java 3.1.2 Character Literals

Character literals are represented as single-byte encoded character (CHAR) or

double-byte encoded characters (WCHAR)2 in FBD programs. Single-byte encoded characters

contain zero or more characters prefixed and terminated by single quote characters (’). A hexadecimal character representation for single-byte encoded character includes a preceding dollar symbol ($) followed by two hexadecimal digits. Double-byte encoded character also contain zero or more characters. Compared to single-byte encoded char-acters, double quote characters (”) are used to prefixed and terminated the character. The hexadecimal character representation for double-byte encoded characters includes the same preceding dollar symbol ($) but is followed by four hexadecimal digits. Single-byte encoded characters and double-byte encoded characters are represented in Java using the Character data type. Differentiation between single-byte encoded charac-ters and double-byte encoded characcharac-ters does not take place because the Java Character data type is based on the Unicode specification and uses fixed-width 16-bit entities [49]. The Java Character data type may be used with character literals or with numeric hexadecimal literals. Character literals are prefixed and terminated with single quote characters. Numeric hexadecimal literal are prefixed with two-characters (0x ) followed by four hexadecimal digits. A two-character prefix followed by two hexadecimal di-gits will only set the rightmost bits of the 16 bits Java representation. This, however,

2

An overview of different single-byte encoded character and double-byte encoded characters is avail-able at [4, p. 33]

(42)

represents the single-byte encoded character behaviour described in the IEC 61131-3 standard.

In addition, variable-length single-byte characters (STRING) and variable-length double-byte characters (WSTRING) are available in the IEC 61131-3 standard. Those data types have a variable length and access single characters by using the character index in surrounding square brackets, start indexing the character string with position one. According to the IEC 61131-3 standard, assigning single-byte encoded characters to double-byte encoded characters or assigning double-byte encoded characters to single-byte encoded characters will cause an error.

Variable-length single-byte encoded characters and variable-length double-byte encoded characters are represented in Java using the Java String data type. The Java String data type also does not differentiate between single-byte encoded characters and double-byte encoded characters and is also based on the Unicode specification [50]. Accessing single character by using the character index in surrounding square brackets is not supported. But various methods, e.g. to return the index of the first occurrence of a specified character or to return the character value at a specified index, are provided and map the behaviour described in the IEC 61131-3 standard. Compared to the IEC 61131-3 standard, the starting position of a character string is zero. Assigning an single-byte encoded characters to double-byte encoded characters or assigning double-byte encoded characters to single-byte encoded characters will not trigger an error in the Java String data type.

Code listing 3.2 illustrates how to translate character literals described in the IEC 61131-3 standard to a Java representations. Java Character uses fixed-width 16-bit entities and does not differentiate between 8-bit and 16-bit characters and are prefixed and termin-ated with single quote characters. Numeric hexadecimal literal are prefixed with two-characters (0x ) followed by two or four hexadecimal digits. Indexing a variable-length single-byte encoded characters and variable-length double-byte encoded characters start with position zero. When assigning single-byte encoded characters to double-byte en-coded characters and vice versa, no error will be triggered in Java String.

 

1 p a c k a g e kunze . s e b . m a s t e r . t h e s i s . t r a n s l a t i o n . l i t e r a l ; 2

(43)

4 5 p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) { 6 7 // ’A ’ 8 C h a r a c t e r s i n g l e B y t e L i t e r a l [ ] = new C h a r a c t e r [ ] { ’A ’ } ; 9 10 // A 11 System . o u t . p r i n t l n ( s i n g l e B y t e L i t e r a l [ 0 ] . c h a r V a l u e ( ) ) ; 12 13 // ”B” 14 C h a r a c t e r d o u b l e B y t e L i t e r a l [ ] = { ’B ’ } ; 15 16 // B 17 System . o u t . p r i n t l n ( d o u b l e B y t e L i t e r a l [ 0 ] . c h a r V a l u e ( ) ) ; 18 19 // [ ’ $43 ’ , ’ $44 ’ ] 20 s i n g l e B y t e L i t e r a l = new C h a r a c t e r [ ] { 0 x43 , 0 x44 } ; 21 22 S t r i n g v a r i a b e l L e n g t h S i n g l e B y t e L i t e r a l = new S t r i n g ( ) ; 23 f o r ( C h a r a c t e r s i n g l e B y t e C h a r a c t e r : s i n g l e B y t e L i t e r a l ) { 24 v a r i a b e l L e n g t h S i n g l e B y t e L i t e r a l += s i n g l e B y t e C h a r a c t e r ; 25 } 26 27 // CD 28 System . o u t . p r i n t l n ( v a r i a b e l L e n g t h S i n g l e B y t e L i t e r a l ) ; 29 30 // [ ” $0045 ” , ” $0046 ” ] 31 d o u b l e B y t e L i t e r a l = new C h a r a c t e r [ ] { 0 x0045 , 0 x0046 } ; 32 33 S t r i n g v a r i a b l e L e n g h t D o u b l e B y t e L i t e r a l = new S t r i n g ( ) ; 34 f o r ( C h a r a c t e r d o u b l e B y t e C h a r a c t e r : d o u b l e B y t e L i t e r a l ) { 35 v a r i a b l e L e n g h t D o u b l e B y t e L i t e r a l += d o u b l e B y t e C h a r a c t e r ; 36 } 37 38 // EF 39 System . o u t . p r i n t l n ( v a r i a b l e L e n g h t D o u b l e B y t e L i t e r a l ) ; 40 } 41 }   Listing 3.2. CharacterLiteral.java

(44)

Table 3.1. Time Literals in the IEC 61131-3 standard [4]

No. Time Unit Example

1 d Days 2 h Hours 3 m Minutes 4 s Seconds 5 ms Milliseconds 6 us Microseconds 7 ns Nanoseconds 3.1.3 Duration Literals

Duration literals3 contain a prefix delimiting the literal on the left side by the keyword

TIME# or T#. This delimiter is not case-sensitive and can be written in lower-case or upper-case letters. In addition, the keyword ( LTIME#) or LT# may be used for 64-bit numeric duration literals. Duration literals can be represented as any combination of day, minutes, seconds and fractions of a second for positive and negative durations, e.g. T#5d14h12m18s3.5ms. Underscore characters can be used to separate those time units from each other, e.g. t#5d 14h 12m 18s 3.5ms. The least significant unit of duration can be written in floating point notation, but without exponents, e.g. LT#14.7s. The most significant unit of duration can be written in overflow notation, e.g. t#25h. Time units are also not case sensitive and also can be written in upper-case and lower-case letters. Table 3.1 provides an overview of all available time units described in the IEC 61131-3 standard, which may be used in any possible combination for duration literals. Additionally, keyword for time and date literals are described in the IEC 61131-3 stand-ard. They contain a prefix delimiting the literal on left by the keyword DATE, D, TIME OF DAY, TOD, DATE AND TIME and DT. Equivalent keyword for a 64-bit representation are available as well including LDATE, LD, LTIME OF DAY, LTOD, LDATE AND TIME and LDT. Date literals contain the year, month and day of the time, e.g. DATE#1984-06-25, and time literals contain the hour, minute and second of the day, e.g. TIME OF DAY#15:36:55.36. The combination of a date and a time literal contains the year, month, day, hour and second, e.g. DATE AND TIME#1984-06-25-15:36:55.360227400. Colons and dashes are used to separate the different time

Figure

Figure 1.1. Research Methodology
Figure 2.1. Simple Architecture of a Programmable Logic Controller [1]
Figure 2.2. Simple Function Block Diagram Program
Figure 2.3. Simple Graph Abstraction of a Program
+7

References

Related documents

ses som en förklaring än en beskrivning av synergier. 20) menar att synergier är ett medel för att nå målet, det vill säga lönsamhet. Fastän lönsamhet inte framgår

Brooks R with the EuroQol group (1996) EuroQol: the current state of play. Katsuura A, Hukuda S, Saruhashi Y et al. Kyphotic malalignement after anterior cervical fusion is one of

Walters’ critical study focuses on LGBTQ movement in the USA, its current agenda, its rep- resentation in the media and visual culture as well as on the ambivalence of

Barnskötarna i studien ger även uttryck för att införandet av undervisningsbegreppet och förskollärarens förtydligade ansvar gällande detta, har lett till att deras

Med tanke på hur det socialdemokratiska Malmö såg ut som vi övertog ansvaret för, har vi självfallet inte kunnat komma längst pä alla områden när det gäller att

Men påven framhärdar i sitt nej till abort och preventivmedel, till alla de ideologiska, sociologiska, befolk- ningspolitiska krafter, som vill öppna nya fålt för

Network Based Approach, Adaptive Test case Prioritization, History-based cost-cognizant test case prioritization technique, Historical fault detection

Results are then presented to practitioners in the company during phase 2 round of semi-structured interviews. RQ 1 results are presented to know the validity and also add