Accessing static Data and Functions in Legacy C
http://www.renaissancesoftware.net/blog/archives/450 It’s a new year; last year was a leap year; so the quadrennial reports of leap year bugs are coming in. Apologies are in the press from Apple, TomTom, and Microsoft. Trains we stopped f
http://www.renaissancesoftware.net/blog/archives/450
It’s a new year; last year was a leap year; so the quadrennial reports of leap year bugs are coming in. Apologies are in the press from Apple, TomTom, and Microsoft. Trains we stopped from running in China. Somehow calling them glitches seems to make it someone else’s fault, something out of their control. How long have leap years been around? Julius Caesar introduced Leap Years in the Roman empire over 2000 years ago. The Gregorian calendar has been around since 1682. This is not a new idea, or a new bug.
I’m going to try to take one excuse away from the programmers that create these bugs by answering a question that comes up all the time, “How do I test static functions in my C code?”
In code developed using TDD, static functions are tested indirectly through the public interface. As I mentioned in a this article TDD is a code rot radar. It helps you see design problems. Needing direct access to hidden functions and data in C is a sign of code rot. It is time to refactor.
But what about existing legacy code that has statics? It is probably way past the time for idealism and time for some pragmatism. In this article and the next, we’ll look at how to get your code
untouched into the test harness and access those pesky <span>static </span>
variables
and functions.
If you don’t mind touching your code, you could change all mentions of static
to STATIC
.
Then using the preprocessor, STATIC
can
he set to static
during
production and to nothing for test, making the names globally accessible. In gcc you would use these command line options
-
For production builds use
-dSTATIC=static
-
For unit test builds use
-dSTATIC
Let’s look at two options that, at least for access to statics, you will not have to touch your code to get it under test. First is <span>#include</span>
-ing
your .c in the test file. In the next article we’ll build a test adapter .c that give access to the hidden parts.
We are going to revisit code that is similar to the original code responsible for the Zune Bug. I rewrote the code to avoid attracting any lawyers but it is structured similarly to the original Zune driver, complete with static data and functions that must be correct for the function to work.
The header file provides a data structure and initialization function for figuring out the information about the date. Here is the header:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Date_Init
populates
the Date
instance
passed in. Ignoring the fact that I can probably fully test this by rigging the daysSince1980
,
and inspecting the contents of the resultingDate
structure,
we are going to see how we can directly test the hidden functions and data.
Date_Init
has
three hidden helper functions.
1 2 3 4 5 6 7 |
|
Date_Init
is
the tip of the iceberg. All the interesting stuff is happening in the hidden data and functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
|
Let’s say you want to check the days per month vectors. You might want to write a test to check the months against the handy poem we use here in the US: Thirty days, has September, April, June and November; all the rest have thirty-one, except for February. It has 28 except in leap year it has 29.
If you started by writing this test…
1 2 3 4 |
|
… you get this error:
1 |
|
Let’s get access to the hidden statics in the test case by including Date.c
instead
ofDate.h
in DateTest.cpp
.
The full test case file looks like this now:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
With a little refactoring days per month vectors can be checked like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
You have access to all the hidden stuff, so you can write the test for the static functions:
IsLeapYear()
, GetDaysInYear()
, FirstSetYearAndDayOfYear()
,ThenSetMonthAndDayOfMonth()
,
and FinallySetDayOfWeek()
.
If Date
been
an abstract data type, with its data structure hidden in the .c
file,
the tests would all have access to structure members hidden from the rest of the world.
There is a downside to this approach, which probably does not matter in this case, but could in others. You can only have one test file that can include a given .c
file.
In the next article we’ll solve that problem.
Have you heard of any interesting leap year bugs? Did you prevent your own?

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

The role and usage of static in C language: 1. Variable scope; 2. Life cycle; 3. Internal function; 4. Modify global variables; 5. Modify function; 6. Other uses; Detailed introduction: 1. Variable scope, when If there is the static keyword before a variable, then the scope of the variable is limited to the file in which it is declared. In other words, the variable is a "file-level scope", which is very useful for preventing the "duplicate definition" problem of variables; 2. Life cycle, static variables are initialized once when the program starts executing, and destroyed when the program ends, etc.

The data folder contains system and program data, such as software settings and installation packages. Each folder in the Data folder represents a different type of data storage folder, regardless of whether the Data file refers to the file name Data or the extension. Named data, they are all data files customized by the system or program. Data is a backup file for data storage. Generally, it can be opened with meidaplayer, notepad or word.

1. static Please look at the following program first: publicclassHello{publicstaticvoidmain(String[]args){//(1)System.out.println("Hello, world!");//(2)}} Have seen this Segment programs are familiar to most people who have studied Java. Even if you have not learned Java but have learned other high-level languages, such as C, you should be able to understand the meaning of this code. It simply outputs "Hello, world" and has no other use. However, it shows the main purpose of the static keyword.

Practical application scenarios and usage skills of the static keyword in C language 1. Overview static is a keyword in C language, used to modify variables and functions. Its function is to change its life cycle and visibility during program running, making variables and functions static. This article will introduce the actual application scenarios and usage techniques of the static keyword, and illustrate it through specific code examples. 2. Static variables extend the life cycle of variables. Using the static keyword to modify local variables can extend their life cycle.

The solution to the garbled mysql load data: 1. Find the SQL statement with garbled characters; 2. Modify the statement to "LOAD DATA LOCAL INFILE "employee.txt" INTO TABLE EMPLOYEE character set utf8;".

Modifier abstract (abstract) 1. Abstract can modify a class (1) The class modified by abstract is called an abstract class (2) Syntax: abstractclass class name {} (3) Features: Abstract classes cannot create objects separately, but they can be declared Reference the abstract class name reference name; (4) Abstract classes can define member variables and member methods (5) Abstract classes have constructors. When used to create subclass objects, jvm creates a parent class object by default; abstract constructor methods apply Applied when jvm creates parent class object. 2. Abstract can modify methods (1) The method modified by asbtract is called an abstract method (2) Syntax: access modifier abstract return value

The functions of static: 1. Variables; 2. Methods; 3. Classes; 4. Other uses; 5. Multi-threaded environment; 6. Performance optimization; 7. Singleton mode; 8. Constants; 9. Local variables; 10. Memory Layout optimization; 11. Avoid repeated initialization; 12. Use in functions. Detailed introduction: 1. Variables, static variables. When a variable is declared as static, it belongs to the class level, not the instance level, which means that no matter how many objects are created, only one static variable exists, and all objects share this Static variables and so on.

The differences are: 1. xdata usually refers to independent variables, while data refers to the entire data set; 2. xdata is mainly used to establish data analysis models, while data is used for data analysis and statistics; 3. xdata is usually used for regression Analysis, variance analysis, predictive modeling, data can be analyzed using various statistical methods; 4. xdata usually requires data preprocessing, and data can contain complete original data.
