Interview Questions1
Interview Questions1
E-mail: [email protected]
Topics Included:
1. Programming Language Concepts
2. Testing skills (unit, S/w Integration, HSI
etc)
3. Process Skills (DO178B)
4. Avionics basis Questions
Prepared by: Rana Mehul
E-mail: [email protected]
Answer: A local variable that does not cease to exist upon termination of the block
in which it can be accessed, but instead retains its most recent value until the next
execution of this block. It is strored in data segment.
Example:
void count(void) {
static int count1 = 0;
int count2 = 0;
count1++;
count2++;
printf("\nValue of count1 is %d Value of count2 is %d", count1,count2);
}
main()
{
count();
count();
count();
}
(data_type) operand
Example 1:
Consider the code:
float a = 5.25;
int b = (int)a; /*Explicit casting from float to int.
The value of b here is 5*/
Example 2:
Consider the code:
char c = ’A’;
int x = (int)c; /*Explicit casting from char to int.
The value of x here is 65: the ASCII code of ‘A’*/
The C preprocessor provides four separate facilities that you can use as you see fit:
Inclusion of header files. These are files of declarations that can be substituted
into your program.
Macro expansion. You can define macros, which are abbreviations for arbitrary
fragments of C code, and then the C preprocessor will replace the macros with
their definitions throughout the program.
Conditional compilation. Using special preprocessing directives, you can include
or exclude parts of the program according to various conditions.
Line control. If you use a program to combine or rearrange source files into an
intermediate file which is then compiled, you can use line control to inform the
compiler of where each source line originally came from.
Ans: The function main( ) invokes other functions within it.It is the first function to
be called when the program starts execution.
Prepared by: Rana Mehul
E-mail: [email protected]
It is the starting function
Recursive call is allowed for main( ) also.
It has two arguments 1)argument count and 2) argument vector (represents
strings passed).
Ans: An argument is an entity used to pass the data from calling function to the
called function.
Formal arguments are the arguments available in the function definition.They are
preceded by their own data types.Actual arguments are available in the function
call.
The arguments listed in function definition are known as formal arguments. And
the arguments passed to function while invoking it, are known as actual
arguments.
For e.g:
-----------
int foo(int a, int b)
{
return (a+b);
}
int main(void)
{
int var1 = 10, var2 = 10;
int result;
result = foo(var1, var2);
return 0;
}
in the above case, var1 & var2 are actual arguments and "a" and "b" are formal
arguments.
Structure Union
i. Access Members
We can access all the members of Only one member of union can be accessed
iii. Initialization
All members of structure can be Only the first member of a union can be
initialized initialized.
iv. Keyword
v. Syntax
---------- ----------
---------- ----------
}struct_var_nm; }union_var_nm;
Prepared by: Rana Mehul
E-mail: [email protected]
vi. Example
}it; }it;
auto
register
static
extern
{
int Count;
auto int Month;
}
The example above defines two variables with the same storage class. auto can only be
used within functions, i.e. local variables.
register is used to define local variables that should be stored in a register instead of
RAM. This means that the variable has a maximum size equal to the register size (usually
one word) and cant have the unary '&' operator applied to it (as it does not have a
memory location).
Prepared by: Rana Mehul
E-mail: [email protected]
{
register int Miles;
}
Register should only be used for variables that require quick access - such as counters. It
should also be noted that defining 'register' goes not mean that the variable will be stored
in a register. It means that it MIGHT be stored in a register - depending on hardware and
implimentation restrictions.
static is the default storage class for global variables. The two variables below (count and
road) both have a static storage class.
{
printf("%d\n", Road);
}
static variables can be 'seen' within all functions in this source file. At link time, the static
variables defined here will not be seen by the object modules that are brought in.
static can also be defined within a function. If this is done the variable is initalised at run
time but is not reinitalized when the function is called. This inside a function static
variable retains its value during vairous calls.
void func(void);
main()
{
while (count--)
{
func();
}
i is 6 and count is 9
i is 7 and count is 8
i is 8 and count is 7
i is 9 and count is 6
i is 10 and count is 5
i is 11 and count is 4
i is 12 and count is 3
i is 13 and count is 2
i is 14 and count is 1
i is 15 and count is 0
NOTE : Here keyword void means function does not return anything and it does not take
any parameter. You can memoriese void as nothing. static variables are initialized to 0
automatically.
There is one more very important use for 'static'. Consider this bit of code.
char *func(void);
main()
{
char *Text1;
Text1 = func();
}
char *func(void)
{
char Text2[10]="martin";
return(Text2);
}
Now, 'func' returns a pointer to the memory location where 'text2' starts BUT text2 has a
Prepared by: Rana Mehul
E-mail: [email protected]
storage class of 'auto' and will disappear when we exit the function and could be
overwritten but something else. The answer is to specify
The storage assigned to 'text2' will remain reserved for the duration if the program.
extern is used to give a reference of a global variable that is visible to ALL the program
files. When you use 'extern' the variable cannot be initalized as all it does is point the
variable name at a storage location that has been previously defined.
When you have multiple files and you define a global variable or function which will be
used in other files also, then extern will be used in another file to give reference of
defined variable or function. Just for understanding extern is used to decalre a global
variable or function in another files.
File 1: main.c
int count=5;
main()
{
write_extern();
}
File 2: write.c
void write_extern(void);
void write_extern(void)
{
printf("count is %i\n", count);
}
This fill produce write program which can be executed to produce result.
Prepared by: Rana Mehul
E-mail: [email protected]
Count in 'main.c' will have a value of 5. If main.c changes the value of count - write.c
will see the new value
Ans: malloc() : malloc create the single block of given size by user
calloc() : calloc creates multiple blocks of given size
* Both return void pointer(void *)so boh requires type casting
examples:
For malloc()
int *p;
p=(int*)malloc(sizeof(int)*5)
Above syntax tells that malloc occupies the 10 bytes memeory and assign the
address of first byte to P
For calloc()
int *p;
p=(int*)calloc(5,sizeof(int)*5)
Above syntax tells that calloc occupies 5 blocks each of the 10 bytes memeory
and assign the address of first byte of first block to P
Also, malloc() takes only one argument i.e. size in bytes to be allocated while calloc()
takes two arguments viz., total number of data and size of each data.
#include<stdio.h>
long factorial(int);
main()
{
Prepared by: Rana Mehul
E-mail: [email protected]
int num;
long f;
if(num<0)
printf("NEGATIVE NUMBERS ARE NOT ALLOWED");
else
{
f = factorial(num);
printf("%d!=%ld",num,f);
}
return(0);
}
long factorial(int n)
{
if(n==0)
return(1);
else
return(n*factorial(n-1));
}
Ans2: #include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char arr[100];
strrev(arr);
getch();
return 0;
}
Ans3:
#include<stdio.h>
#include<string.h>
void reverse(char*);
main()
{
char string[100];
printf("Enter a string\n");
gets(string);
reverse(string);
return 0;
}
length = strlen(string);
begin = string;
Prepared by: Rana Mehul
E-mail: [email protected]
end = string;
begin++;
end--;
}
}
#include <stdio.h>
void f(){
printf("Executing f\n");
return;
}
int main(){
f();
printf("Back from f\n");
}
Executing f
Back from f
void f(){
printf("Executing f\n");
exit(0);
}
int main(){
f();
printf("Back from f\n");
}
Executing f
Also notice that the parameter of exit() is an integer (it's the return status of the process
that the launcher process can get; the conventional usage is 0 for success or any other
value for an error).
The parameter of the return statement is whatever the return type of the function is. If the
function returns void, you can omit the return at the end of the function.
12. What is the difference between declaring a variable and defining a variable?
Ans: Declaration of a variable in C hints the compiler about the type and size of the
variable in compile time. No space is reserved in memory for any variable in case of
declaration.
e.g. : int a;
Here variable ‘a‘ is declared of data type ‗int‘
Defining a variable means declaring it and also allocating space to hold it.
We can say ― Definition = Declaration + Space reservation‖
e.g. : int a = 10; /* Here variable‘a‘ is described as an int to the compiler and
memory is allocated to hold value 10.*\
Examples:
int *ptr;
int (*ptr)();
int (*ptr)[2];
int a=5;
int * ptr;
ptr=&a;
Explanation:
About variable a:
1. Name of variable : a
2. Value of variable which it keeps: 5
3. Address where it has stored in memory : 1025 (assume)
Pictorial representation:
int a=50;
int *ptr1;
int **ptr2;
ptr1=&a;
ptr2=&pt1;
Explanation:
About variable a:
1. Name of variable : a
2. Value of variable which it keeps: 50
3. Address where it has stored in memory : 5000 (assume)
Note:
*&p=p
&*p=p
Simple example:
#include<stdio.h>
int main(){
int x=25;
int *ptr=&x; //statement one
int **temp=&ptr; //statement two
printf(―%d %d %d‖.x.*ptr,**temp);
return 0;
}
Output: 25 25 25
Explanation:
**temp= **(&ptr)=*(*&ptr)=*ptr=*(&x)=*&x=x=25
Prepared by: Rana Mehul
E-mail: [email protected]
a+b*c
In a language that supports operator overloading, and assuming the '*' operator has
higher precedence than '+', this is effectively a more concise way of writing:
The remaining two areas of system memory is where storage may be allocated by the
compiler for data storage. The stack is where memory is allocated for automatic
variables within functions. A stack is a Last In First Out (LIFO) storage device where
new storage is allocated and deallocated at only one ``end'', called the Top of the
stack. This can be seen in Figure.
Prepared by: Rana Mehul
E-mail: [email protected]
When a program begins executing in the function main(), space is allocated on the stack
for all variables declared within main(), as seen in Figure (a). If main() calls a function,
func1(), additional storage is allocated for the variables in func1() at the top of the
stack as shown in Figure (b). Notice that the parameters passed by main() to func1() are
also stored on the stack. If func1() were to call any additional functions, storage would
be allocated at the new Top of stack as seen in the figure. When func1() returns, storage
for its local variables is deallocated, and the Top of the stack returns to to position shown
in Figure (c). If main() were to call another function, storage would be allocated for that
function at the Top shown in the figure. As can be seen, the memory allocated in the
stack area is used and reused during program execution. It should be clear that memory
allocated in this area will contain garbage values left over from previous usage.
The heap segment provides more stable storage of data for a program; memory allocated
in the heap remains in existence for the duration of a program. Therefore, global variables
(storage class external), and static variables are allocated on the heap. The memory
allocated in the heap area, if initialized to zero at program start, remains zero until the
program makes use of it. Thus, the heap area need not contain garbage.
Function Task
malloc Allocates memory requests size of bytes and returns a pointer to the Ist byte
of allocated space
calloc Allocates space for an array of elements initializes them to zero and returns
a pointer to the memory
void main(void)
{
int a[4] = {1, 2, 9, 17};
int index, value;
printf("\nArray:\n");
print_array(a, 10);
value = 1;
index = find_index(a, 4, value);
if (index == -1)
{
printf("The value %d was not found.\n", value);
}
else
{
printf("The value %d was found at %d\n", value, index);
}
value = 9;
index = find_index(a, 4, value);
if (index == -1)
{
printf("The value %d was not found.\n", value);
}
else
{
printf("The value %d was found at %d\n", value, index);
Prepared by: Rana Mehul
E-mail: [email protected]
}
value = 17;
index = find_index(a, 4, value);
if (index == -1)
{
printf("The value %d was not found.\n", value);
}
else
{
printf("The value %d was found at %d\n", value, index);
}
}
Ans: If a header file happens to be included twice, the compiler will process its contents
twice. This is very likely to cause an error, e.g. when the compiler sees the same structure
definition twice. Even if it does not, it will certainly waste time.
The standard way to prevent this is to enclose the entire real contents of the file in a
conditional, like this:
/* File foo. */
#ifndef FILE_FOO_SEEN
#define FILE_FOO_SEEN
#endif /* !FILE_FOO_SEEN */
Prepared by: Rana Mehul
E-mail: [email protected]
This construct is commonly known as a wrapper #ifndef. When the header is included
again, the conditional will be false, because FILE_FOO_SEEN is defined. The preprocessor
will skip over the entire contents of the file, and the compiler will not see it twice.
The malloc() function allocates num bytes of storage space and returns a pointer to the
first byte.
int **create(int m, n)
{
int **p, i;
calloc() function
Remember that size_t is a synonym for unsigned on most compilers. The argument
num is the number of objects to allocate, and size is the size (in bytes) of each
object. If allocation is successful, all the allocated memory is cleared (set to 0), and
the function returns a pointer to the first byte
#include <stdlib.h>
#include <stdio.h>
main()
Prepared by: Rana Mehul
E-mail: [email protected]
{
unsigned num;
int *ptr;
if (ptr != NULL)
puts("Memory allocation was successful.");
else
puts("Memory allocation failed.");
return(0);
}
realloc() function
The realloc() function changes the size of a block of memory that was previously
allocated with malloc() or calloc(). The function prototype is
main()
{
char buf[80], *message;
/* Input a string. */
Prepared by: Rana Mehul
E-mail: [email protected]
puts(message);
free() function: When you allocate memory with either malloc() or calloc(), it is
taken from the dynamic memory pool that is available to your program. This pool is
sometimes called the heap, and it is finite. When your program finishes using a
particular block of dynamically allocated memory, you should deallocate, or free, the
memory to make it available for future use. To free memory that was allocated
dynamically, use free(). Its prototype is
The free() function releases the memory pointed to by ptr. This memory must have
been allocated with malloc(), calloc(), or realloc().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BLOCKSIZE 30000
main()
{
void *ptr1, *ptr2;
/* Allocate one block. */
ptr1 = malloc(BLOCKSIZE);
if (ptr1 != NULL)
printf("\nFirst allocation of %d bytes successful.",BLOCKSIZE);
else
{
printf("\nAttempt to allocate %d bytes failed.\n",BLOCKSIZE);
exit(1);
}
ptr2 = malloc(BLOCKSIZE);
if (ptr2 != NULL)
{
/* If allocation successful, print message and exit. */
ptr2 = malloc(BLOCKSIZE);
if (ptr2 != NULL)
printf("\nAfter free(), allocation of %d bytes
successful.\n", BLOCKSIZE);
return(0);
}
Variable B3 B2 B1 B0
X 1 1 0 0
Y 1 0 1 0
Z = X &Y 1 0 0 0
Example:
Variable B3 B2 B1 B0
X 1 1 0 0
Y 1 0 1 0
Z=X|Y 1 1 1 0
Bitwisr XOR ( ^ ) : The bitwise-exclusive-OR operator compares each bit of its first
operand to the corresponding bit of its second operand. If one bit is 0 and the other bit is
Prepared by: Rana Mehul
E-mail: [email protected]
1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to
0.
Variable B3 B2 B1 B0
X 1 1 0 0
Y 1 0 1 0
Z=X^Y 0 1 1 0
Bitwise NOT (~) : There's only one unary bitwise operator, and that's bitwise NOT.
Bitwise NOT flips all of the bits.
Variable B3 B2 B1 B0
X 1 1 0 0
Y = (~X) 0 0 1 1
Ans: C, in particular, was created to make it easier to write operating systems. Rather
than write UNIX in assembly, which is slow process and not very portable (because
assembly is specific to an ISA), the goal was to have a language that provided good
control-flow, some abstractions (structures, function calls), and could be efficiently
compiled and run quickly.
Writing operating systems requires the manipulation of data at addresses, and this
requires manipulating individual bits or groups of bits.
That's where two sets of operators are useful: bitwise operators and bitshift operators.
Bitwise operators allow you to read and manipulate bits in variables of certain types.
Loading - Using a Loader program to load the executable code into CPU for
execution.
Here is a simple table showing input and output of each step in the compilation
and execution process:
24. Difference between typedef & #include preprocessor & side effects
Ans:
A typedef declaration lets you define your own identifiers that can be used in place of
type specifiers such as int, float, and double. A typedef declaration does not reserve
storage.
When an object is defined using a typedef identifier, the properties of the defined object
are exactly the same as if the object were defined by explicitly listing the data type
associated with the identifier.
The following statements declare LENGTH as a synonym for int and then use this typedef
to declare length, width, and height as integer variables:
#include <stdio.h>
Prepared by: Rana Mehul
E-mail: [email protected]
it is treated as a system-defined file, and the preprocessor searches for the file in a
manner defined by the preprocessor
#include "payroll.h"
the preprocessor treats it as a user-defined file, and searches for the file in a manner
defined by the preprocessor.
Declarations that are used by several files can be placed in one file and included with
#include in each file that uses them.
Structure Declaration:
The employee structure has three members: name, id, and class. The name member is a 20-
element array, and id and class are simple members with int and long type, respectively. The
identifier employee is the structure identifier.
This example defines three structure variables: student, faculty, and staff. Each structure has the
same list of three members. The members are declared to have the structure type employee,
defined in the previous example.
Union Declaration:
This example defines a union variable with sign type and declares a variable named number
that has two members: svar, a signed integer, and uvar, an unsigned integer. This declaration
allows the current value of number to be stored as either a signed or an unsigned value.
Enumeration:
Enumeration Declaration:
The value 0 is associated with saturday by default. The identifier sunday is explicitly set to 0.
The remaining identifiers are given the values 1 through 5 by default.
In this example, a value from the set DAY is assigned to the variable today.
Example:
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
Prepared by: Rana Mehul
E-mail: [email protected]
printf(―swapped values are a=%d and b=%d‖,x,y);
}
Void main()
{
int a = 7, b=4;
printf("Original values are a = %d and b = %d", a, b);
swap(a,b);
}
Output:
Original values are a = 7 and b = 4
swapped values are a = 4 and b = 7.
This happens because when function swap() is invoked, the values of a and b gets copied
on to x and y. The function actually swaps x and y while the original variables a and b
remains intact.
Call by Reference: In this method, the addresses of actual arguments in the calling function are
copied into formal arguments of the called function. This means that using these addresses, we
would have an access to the actual arguments and hence we would be able to manipulate them.
C does not support Call by reference. But it can be simulated using pointers.
Example:
void swap(int *x, int *y)
{
int t;
t = *x; /* assign the value at address x to t */
*x = *y; /* put the value at y into x */
*y = t; /* put the value at to y */
}
int main() {
int m = 10, n = 20;
printf("Before executing swap m=%d n=%d\n", m, n);
swap(&m, &n);
printf("After executing swap m=%d n=%d\n", m, n);
return 0;
}
Output:
Before executing swap m=10 n=20
After executing swap m=20 n=10
Explanation:
In the main function, address of variables m, n are sent as arguments to the function 'swap'. As
swap function has the access to address of the arguments, manipulation of passed arguments
inside swap function would be directly reflected in the values of m, n.
29. What is the difference between pointer to constant and constant pointer. write
down the same..
Ans:
Pointer to constant:
This is a pointer which points to a constant variable assigned to that pointer. Another
pointer can also be assigned to the same constant variable to point to.
Example :
char Const a;
char *p,*q;
p=&a;
q=&a;
Constant Pointer:
It is a pointer which points to the same memory location or to same address and whatever
value the variable which is pointed by the pointer holds.
Example :
char a;
char const *p;
p=&a;
Here variable ‗a‘ is a memory location having an address and that variable contains
some character data. This pointer ―p‖ points to the same address ( a ) however the value
in variable ‗a‘ changes.
Searching techniques:
Prepared by: Rana Mehul
E-mail: [email protected]
Binary Search
Hash tables method
31. What are macros? What are the advantages and disadvantages?
Ans:
Macros are preprocessor statements which will have specific set of instructions which are
repeated in source code for several times and which wil be replaced at every call made.
Advantages:
It saves a lot of time that is spent by the compiler for invoking / calling the
functions and hence increases the speed of the execution.
Any modification to instructions in macro reflects in every call.
Reduce source code length.
Disadvantage:
The disadvantage of the macro is the size of the program. The reason is,
the pre-processor will replace all the macros in the program by its real definition
prior to the compilation process of the program.
Prepared by: Rana Mehul
E-mail: [email protected]
Testing skills (unit, S/w Integration, HSI etc)
This method of test can be applied to all levels of software testing: unit, qintegration,
functional, system and acceptance. It typically comprises most if not all testing at higher
levels, but can also dominate unit testing as well.
White-box testing (also known as clear box testing, glass box testing, transparent box
testing, and structural testing) is a method of testing software that tests internal structures
or workings of an application, as opposed to its functionality (i.e. black-box testing). In
white-box testing an internal perspective of the system, as well as programming skills,
are required and used to design test cases. The tester chooses inputs to exercise paths
through the code and determine the appropriate outputs. This is analogous to testing
nodes in a circuit, e.g. in-circuit testing (ICT).
While white-box testing can be applied at the unit, integration and system levels of the
software testing process, it is usually done at the unit level. It can test paths within a unit,
paths between units during integration, and between subsystems during a system level
Prepared by: Rana Mehul
E-mail: [email protected]
test. Though this method of test design can uncover many errors or problems, it might not
detect unimplemented parts of the specification or missing requirements.
Low-level testing : To verify the implementation of the software low level requirements.
** Low level testing Focus on and consider the following:
• Demonstrate that each software component complies with its low-level requirements
• Algorithms failing to satisfy software requirements
• Incorrect loop operations and logic decisions
• Various input data conditions including:
–Failure to process legitimate combinations of input conditions
–Incorrect responses to missing or corrupted input data
• Incorrect fault handling (overflows, underflows), pointer problems, and so on
• Incorrect sequences of operation
• Algorithm precision, accuracy or performance
Robustness testing:
Robustness testing or abnormal range testing includes but is not limited to
• equivalence class testing using invalid classes
• boundary value analysis testing using invalid boundaries
• system restart (or start up) under abnormal conditions
• corrupt input data
• loop termination (looping on out of range values)
• excessive timeloading
• time constants that are shortened and/or extended
• attempt to provoke invalid state transitions
Equivalence partitioning:
(
Equivalence partitioning also called Equivalence Class Partitioning or ECP is a )
software testing technique that divides the input data of a software unit into partitions of
data from which test cases can be derived. In principle, test cases are designed to cover
Prepared by: Rana Mehul
E-mail: [email protected]
each partition at least once. This technique tries to define test cases that uncover classes
of errors, thereby reducing the total number of test cases that must be developed.
In rare cases equivalence partitioning is also applied to outputs of a software
component, typically it is applied to the inputs of a tested component. The equivalence
partitions are usually derived from the requirements specification for input attributes that
influence the processing of the test object. An input has certain ranges which are valid
and other ranges which are invalid. Invalid data here does not mean that the data is
incorrect, it means that this data lies outside of specific partition
Error Guessing:
In error guessing, a test designer summarizes, both by intuition and experience, certain
probable types of errors and then writes test cases to expose these errors.
Typical errors include divide by zero, null pointers, or invalid parameters.
Error guessing has no explicit rules for testing;test cases can be designed
depending on the situation, either drawing from functional documents or when an
unexpected/undocumented error is found while testing operations.
Control coupling
The manner or degree by which one software component influences the execution of
another software component.
With the current testing approach widely being followed across the aerospace
industry, Hardware-Software integration tests are performed at prototype level and once
the requirements are stable, requirement based tests (RBT) are formally performed to
show compliance as per DO178B - review of requirements, design and code along with
RBT (involves various level of tests -bloack box, white box, unit/module/isolation tests
as appropriate). Performing Software-Software Integration tests upon these verification
evidence already generated adds on to time and cost of the project.
Data Coupling & Control Coupling objective can be achieved with following
activities:
a) Architecture&Design Reviews to check the data flow between components.
Prepared by: Rana Mehul
E-mail: [email protected]
b) Source Code reviews/analysis to check Calling sequences,Data read-write access,
worst case execution time.
c) Memory map file anyalsis to check the robust memory management.
d) SIT (for uncovered HLR's during HSIT) to check the data flow and control flow b/w
compoents implementing uncovered requirements from HSIT.
e) Module testing to check the parameter passing (using stub check parameter on entry
concepts in LDRA ,RTRT,,,etc), external function calling sequence(using Stub order
concept in LDRA,RTRT ...etc) and global data intialisation.
7. Given a software code how we can perform Data Coupling and Control coupling
manually?
Ans:
In the C language control coupling manifests in one of three ways:
(2) Global data set or used by the function whose value is determined at compile-time or
Prepared by: Rana Mehul
E-mail: [email protected]
as part of system configuration.
• In the case of global configuration data (case 2); analysis should determine the
equivalency classes of all potential configurations. Structural coverage analysis should be
executed under all equivalency classes.
(3) Global data set or used by the function which represents the current state of execution
of the system.
• In the case of global state data (case 3); analysis should determine the potential states
(or their equivalency classes). Structural coverage analysis through instrumentation
should determine if all states have been entered and all legal transitions between states
have been exercised.
An Approach
Perform a review of the flight software to confirm data coupling and control coupling
among the software components.
To satisfy the control coupling objective, use the structural coverage results to provide
evidence that all functions were executed through high-level test cases. For functions that
could not be exercised by high-level tests, develop additional functional analyses and add
to the Software Verification Cases and Procedures (SVCP). The intent is to provide
confidence that the requirements-based testing has completely exercised the code
structure.
To satisfy the data coupling objective, this analysis includes functional parameters, global
variables, external data, stored data, and resource contention. Analyze the SVCP and
associate test code to confirm the verification coverage of the data coupling in the code.
As with the control coupling, structural coverage results can used to provide evidence
that the data coupling through parameters was covered.
STLC determines what test activities should be carried out and when should they be
completed.
Prepared by: Rana Mehul
E-mail: [email protected]
Requirement Stage
This is the initial stage of the software testing life cycle process. In this phase the
developers take part in analyzing the requirements for designing a product. The role of
software testers is also necessary in this phase as they can think from the 'users' point of
view which the developers may not. Thus a team of developers, testers and users can be
formed, to analyze the requirements of the product. Formal meetings of the team can be
held in order to document the requirements which can further be used as software
requirements specification or SRS.
Test Planning
Test planning means to predetermine a plan well in advance to reduce further risks. A
well-designed test plan document plays an important role in achieving a process-oriented
approach. Once the requirements of the project are confirmed, a test plan is documented.
The test plan structure is as follows:
Test Analysis
Once the test plan documentation is done, the next stage is to analyze what types of
software testing should be carried out at the various stages of SDLC.
Test Design
Test design is done based on the requirements of the project documented in the SRS. This
phase decides whether manual or automated testing is to be done. In automation testing,
different paths for testing are to be identified first and writing of scripts has to be done if
required. An end-to-end checklist that covers all the features of the project is necessary in
the test design process.
Prepared by: Rana Mehul
E-mail: [email protected]
Test Verification and Construction
In this phase, the test plan, test design and automated test script are completed. Stress and
performance testing plans are also completed at this stage. When the development team is
done with a unit of code, the testing team is required to help them in testing that unit and
report any bug in the product, if found. Integration testing and bug reporting is done in
this phase of software testing life cycle.
Test Execution
Planning and execution of various test cases is done in this phase. Once the unit testing is
completed, the functionality of the tests is done in this phase. At first, top-level testing is
done to find out the top-level failures and bugs are reported immediately to the
development team to get the required workaround. Test reports have to be documented
properly and the bugs have to be reported to the development team.
Result Analysis
After the successful execution of the test case, the testing team has to retest it to compare
the expected values with the actual values, and declare the result as pass/fail.
Bug Tracking
This is one of the important stages as the Defect Profile Document (DPD) has to be
updated for letting the developers know about the defect. Defect Profile Document
contains the following
Post Implementation
Once the test results are evaluated, the recording of errors that occurred during the
various levels of the software testing life cycle, is done. Creating plans for improvement
and enhancement is an ongoing process. This helps to prevent similar problems from
occurring in the future projects. In short, planning for improvement of the testing process
for future applications is done in this phase.
In the figure shown below all the defect reports move through a series of clearly
identified states.
1. A defect is in open state when the tester finds any variation in the test results during
testing, peer tester reviews the defect report and a defect is opened.
2. Now the project team decides whether to fix the defect in that release or to postpone it
for future release. If the defect is to be fixed, a developer is assigned the defect and
defect moves to assigned state.
Prepared by: Rana Mehul
E-mail: [email protected]
3. If the defect is to be fixed in later releases it is moved to deferred state.
4. Once the defect is assigned to the developer it is fixed by developer and moved to
fixed state, after this an e-mail is generated by the defect tracking tool to the tester
who reported the defect to verify the fix.
5. The tester verifies the fix and closes the defect, after this defect moves to closed state.
6. If the defect fix does not solve the issue reported by tester, tester re-opens the defect
and defect moves to re-opened state. It is then approved for re-repair and again
assigned to developer.
7. If the project team defers the defect it is moved to deferred state, after this project
team decides when to fix the defect. It is re-opened in other development cycles and
moved to re-opened state. It is then assigned to developer to fix it.
10. What is a dead code and deactivated code. How will you identify the dead code?
Ans:
Dead code is an executable Object Code (or data) which exists as a result of a software
development error but cannot be executed (code) or used (data) in any operational
configuration of the target computer environment. It is not traceable to a system or
software requirement.
Example
int f (int x, int y)
{
int z=x+y;
return x*y;
}
In the above example the sum of x and y is computed but never used. It is thus dead code
and can be removed.
if (debug){
//do something...
}
}
In the above example "do something" is never executed, and so it is dead code.
Deactivated code - Executable object code (or data) which by design is either (a) not
intended to be executed (code) or used (data), for example, a part of a previously
Prepared by: Rana Mehul
E-mail: [email protected]
developed software component, or (b) is only executed (code) or used (data) in certain
configurations of the target computer environment, for example, code that is enabled by a
hardware pin selection or software programmed options.
//For EPIC-TOLD
#ifdef _EPIC_TOLD
enum fmsActivationData
{
PERF_DATA_PAGE = 0,
CLIMB_PAGE = 1,
DESCENT_PAGE = 2,
FLIGHT_PLAN_PAGE = 3,
DEPART_RWY_PAGE = 4,
ARRIVAL_RWY_PAGE = 5
};
enum toldActivationData
{
TOINIT_1_PAGE = 0,
LDINIT_1_PAGE = 1
};
#endif
Example:
An illustative list (but not a complete list) will make the point of what is usually
considered derived requirements:
1. hardware dependent features such as frequency, big endien- little endien
considerations, code to trap hardware failures, code to implement SEU avoidance etc if
they are not already specified in the high level requirements- I have personally seen a
case where hardware controller was switched and the nuclear reactor software almost
caused a meltdown!
2. defensive programming in order to avoid computational errors, processor errors, avoid
what has already been published as processor errata as applicable, known linker and
compiler deficiencies etc
3. design specific decisions such as backup, redundancy and partitioning. it is important
to examine how these features work with respect to system safety. For example what
state will be backup system be when the system is up after a primary system failure.
4. domain specific knowledge of previously observed failures - this is a tricky one since a
lot of companies keep track of the type of possible errors when their system interacts with
the other avionics and this is often their domain knowledge. A new company will have to
build up this knowledge by experience and by hiring experienced personnel.
5. aircraft specific "personality" features - how does a particular aircraft contribute to the
physics of the problem. This is usually implemented as configuration parameters - then
this is not considered to be derived requirements. but in some cases there is elaborate
code.
Suppose you are building a flight display. A top level requirement may be to display
altitude both as a graphic and numerically. Now, if you decide to implement the graphical
software via OpenGL, a derived requirement may be to have a glBegin() function. It
doesn't trace directly to the altitude requirement, but can when coupled with the decision
to use OpenGL.
At a low level, the same principle applies. Suppose you have a requirements on when
landing wheels can and cannot be retracted. Now you decide to implement this code as a
state machine. A low level derived requirement could then be the need to have a state
variable to control the state machine.
Each level of the development lifecycle has a corresponding test plan. i.e. as each phase
is being worked on, a test plan is developed to prepare for the testing of the products of
that phase. Be developing the test plans, we can also define the expected results for
testing of the products for that level as well as defining the entry and exit criteria for each
level.
In the V-Model the test activities are spelled out to the same level of detail as the design
activities. Software is designed on the left-hand (downhill) part of the model, and built
and tested on the right-hand (uphill) part of the model. Note that different organizations
may have different names for the development and testing phases.
The correspondences between the left and right hand activities are shown by the lines
across the middle of the V, showing the test levels from component testing at the bottom,
integration and system testing, and acceptance testing at the top level.
Advantages
Disadvantages
Develop Serena
ChangeMan Test Case
Infrastructure within
PVCS Dimensions
21. How do you test dead code or deactivated code as per DO-178B.
Ans: We do not test. Testing as per DO-178B is requirement driven. We just tests the
requirements. If the structural coverage shows less than 100% coverage, one of the
following 3 could apply:
(a). The test is inadequate/incorrect.
(b). There is a dead code.
(c). There is a deactivated code.
In the case of (a), one just digs deeper and ensures that the requirement is completely and
correctly tested. In the other two cases, I would just raise a PR and my job is done.
Unless there is a requirement that tells me how to handle deactivated code, I wouldn‘t
bother.
Prepared by: Rana Mehul
E-mail: [email protected]
14. Where does Do-178B specify the lify cycle that a project must follow?
Ans: DO-178B does not specify any life cycle. Honeywell traditionally chooses to use an
iterative ―Waterfall‖ life cycle.
16. Which members of the project team should become familiar with the
development process defined in SDP?
Ans: The software development process must be understood by the development team
and the test team. Refer DO-178B sec.4. For example, it is important that the project
team understands how all work is controlled if ―change documents‖(i.e. SCRs, PCRs etc.)
are embedded in a configuration management tool such as PVCS.
17. What main event occurs during the integration phase of development?
Ans: The executable object code is integrated into the target hardware(DO-178B sec 5.4)
19. Can the code be formally reviewd for credit before the design review has been
conducted?
Ans: No. The design review must be completed before the code can be reviewd if formal
credit is sought.
(We can always review the code informally at any time for no credit. This is
useful for ―wringing out‖ the system).
The verification process must oocur ―in order‖. DO-178B uses the term
―transition criteria‖ to refer them.
20. How does someone finds the design, code and the test procedure(s) associated
with a specific requirement?
Ans: All software requirements must be traced to the design, code and test procedure.
Typically, honeywell chooses to identify all requirements by the kye word ―shall‖. All
―shall‖ may then be traced to the design, code and the test procedures.
24. What are the two main analysis required to determine when the testing effort is
complete?
25. Explain requirement coverage analysis.
26. Why do we need to perform structural coverage analysis?
27. How to perform structural coverage analysis on assembly source code for level A
software?
28. Do-178B gives the guidelines for three traceability. Which 3?
29. What is the difference between integration process and integration testing?
30. What is the role of DERs?
31. What do you know about TSO?
32. What is the role of the QA engineer?
33. What is the significance of MCDC?
34. How many MCDC test cases are required for a combination of n variables?
35. Write test cases for c=a+b; (simple adder block) and identify which are
boundary, normal and robustness (assuming a and b can range from [0..5])
36. Write test cases for “A or (B and C)” and “A and (B or C)”
37. What is “Unique-cause” approach for MCDC?
38. What do you know about Masking approach for MCDC?
39. How many number of test cases are required for condition (A>10) ? A is an
integer.
40. Contents of a peer review checklists.
41. How many documents, as a minimum, are required to be submitted to the
certifying authority? Name them.
Ans: Three documents.
1. PSAC (Plan for Software Aspects of Certification).
2. SAS (Software Accomplishment Summary).
3. SCI (Software Configuration Index)
Avionics
1. Different forces acting on aircraft while flying and how aircraft is getting that.
2. Different motions of aircraft and what helps aircraft for moving in different
directions.
3. Different phases of a flight
4. Explain the project worked on. What is level of that software as per DO178B. What
all the impacts of that software failure.
5. Real Time example of avionics software‘s for different levels of DO178B.
6. AFDX message format
7. Any A429 Label format BCD, BNR etc