ats style guide

71
ATS Automated Test Software Style Guide Brian Jackson Test Technologies EDCS-303404 Version: 1.5 Approved February 3, 2004 Abstract This document describes the Cisco Test Technologies style convention standards for development of ATS automated test scripts and procedure libraries.

Upload: sku295

Post on 28-Nov-2014

201 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: ATS Style Guide

ATS Automated TestSoftware Style Guide

Brian JacksonTest Technologies

EDCS-303404

Version: 1.5 ApprovedFebruary 3, 2004

Abstract

This document describes the Cisco Test Technologies style convention standards for development ofATS automated test scripts and procedure libraries.

Page 2: ATS Style Guide

ATS Automated Test Software Style GuideCopyright © 2004 Cisco Systems, Inc. All rights reserved.Cisco Confidential — For Internal Use Only

Page 3: ATS Style Guide

Table of Contents

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

2 Quoting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.1 Quoting for Variable, Command, and Special-Character Substitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.2 Quoting for Variable, Command, and Special-Character Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.3 Default to the Use of Double Quotes to Quote Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32.4 Quote Single-Element Strings Using Double Quotes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.5 Quote Expressions Using Curly Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.5.1 Quote Expressions Using Curly Braces to Maintain Consistency . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.5.2 Quote Expressions Using Curly Braces to Improve Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.5.3 Quote Looping Expressions Using Curly Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.6 Quote Code Blocks Using Curly Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.7 Quote Procedure Bodies and Script Sections Using Curly Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.8 Quote Non-Space-Delimited Variable Names Using Curly Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.9 Quote Procedure Argument Lists Using Curly Braces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3 Commands and Code Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.1 Command Placement and Length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3.1.1 Code One Command per Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.1.2 Split Lengthy Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3.1.2.1 Split Command Lines That Exceed 80 Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.1.2.2 Use join to Split Strings That Exceed 80 Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.1.2.3 Split Commands at Logical Breaks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.2 Code Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133.2.1 Quote Code Blocks Using Curly Braces (Reminder) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133.2.2 Align Opening and Closing Code Block Curly Brace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133.2.3 Indent the Contents of Code Blocks Four Spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.2.4 Avoid Excessively Long or Deeply Nested Code Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.2.5 Treat Script Sections and Device Configurations As Code Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2.6 Treat Procedure Bodies As Code Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.3 Command Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.3.1 Use Spaces to Delimit Operators and Values in Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.3.2 Exclude the Equality Operator from Boolean Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.3.3 Explicitly Define Expression Operation Precedence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3.4 Special Command Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.4.1 Handling switch Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.4.2 Handling for Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.4.3 Do Not Include then in if Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.4.4 Using switch Versus elseif Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.4.5 Use "--" string to mark end of options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.4.6 Handling uplevel and upvar statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.4.7 Handling case statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

4 White Space and Indentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.1 Code Logic White-Space Separation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4.1.1 Use One Line of White Space to Visually Segment Software Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.1.2 Using Formfeeds for Print Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Table of Contents

ATS Automated Test Software Style Guide i

Page 4: ATS Style Guide

4.2 Indent Nested Code Blocks Four Spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

5 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235.1 Format Comments Like Bullet Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235.2 Comment All Logical Blocks of Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235.3 Indent Comments to Align Them with the Code That Follows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245.4 Add Comments at End of Nested Code Blocks (Optional) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245.5 Variable Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

5.5.1 Document Constants and Important Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255.5.2 Document Internal Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

5.6 Script Header and Footer Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265.6.1 Include the Standard Script Header Comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265.6.2 Include the Standard Script Footer Comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

5.7 Procedure Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305.7.1 Include Script Procedure Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305.7.2 Include the Standard Procedure Library Header Comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305.7.3 Include the Standard Procedure Library Footer Comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325.7.4 Include Standard Procedure Library Procedure Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325.7.5 Include Procedure Library Internal Procedure Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

5.8 ITcl Class Library Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355.8.1 Include the Standard Class Library Header Comment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355.8.2 Include Standard Class Library Method Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

5.9 Comment Nonintuitive Script Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375.10 Use Comments to Document Output Being Parsed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375.11 Comment Router Configurations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385.12 Generating Documentation from Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395.13 Include Cisco copyright notice in all files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395.14 Include RCS $Id$ tag in all files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

6 Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.1 Assign Meaningful Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.2 Use Standard Characters in Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.3 Abbreviate Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426.4 Techniques for Constructing Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

6.4.1 Underscore-Delimited Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426.4.2 Camelback Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

6.5 Name Prefixes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.5.1 Name Space Collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.5.2 Use Simple Name Prefixing in Test Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.5.3 Use Name Spaces in Procedure Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446.5.4 Begin Names with Underscores to Hide Them . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

6.6 Name Constant Variables Using Uppercase Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446.7 Name Files Using Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

7 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477.1 Define and Use Constant Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

8 Software Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498.1 Script Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498.2 Procedure Library Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

Table of Contents

ATS Automated Test Software Style Guide ii

Page 5: ATS Style Guide

9 Emacs TCL Mode and Fontification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

10 Where to Go from Here . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Appendix A: Style Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Table of Contents

ATS Automated Test Software Style Guide iii

Page 6: ATS Style Guide

1 Introduction

This document addresses automated software coding style. Style issues affect the look and feelof the code being developed. Although virtually any style can be used to implement Tool ControlLanguage (TCL) code, the style conventions presented in this document are intended to reducethe potential for error by fostering sound style practices. Additionally, the use of the followingstandard style will help to improve the maintainability and understandability of your code both byother users and by yourself when you return to work on a script after a lengthy absence. Finally,the use of this style will promote code sharing by ensuring that your code looks the same as thatdeveloped by other adopters of this style.

In applying a coding style, respecting the intent of each style rule is more important thanadhering to the letter of the law. Either follow the rule as given or develop your own rule toaddress the need as you see fit. Any script that follows a well-thought-out and consistent stylewill achieve the goal of being understandable and maintainable, by yourself and others, and willavoid common coding errors. So don't be rigid about using this style guide. Do become familiarwith its intent and how it can shape or supplement your own personal style. Also note that someof these style elements affect performance and enable the use of certain tools (for example,ATSDOC documentation generation).

Style guidelines presented in this document apply equally to the development of test scripts andscript development procedure libraries. This document is the Test Technologies approved styleguide for all TCL software developed for use with the Automated Test System (ATS).

The Style Summary provides a quick overview of the most important topics in this document.From there you can click the style item titles to see the details of any style rule.

This document is appropriate reading for any developer of ATS TCL language based automatedtest software, either scripts or procedure libraries. Send comments and questions about thisdocument to the test-consulting mailing list.

1 Introduction

ATS Automated Test Software Style Guide 1

Page 7: ATS Style Guide

1 Quoting

ATS Automated Test Software Style Guide 2

Page 8: ATS Style Guide

2 Quoting

Quoting is one of the most fundamental aspects of TCL. As such, it is also the most commonsource of TCL scripting errors. This section discusses standard style for the quoting of strings,expressions, and code blocks. For a detailed discussion of quoting, refer to the Tcl ScriptingLanguage Primer.

2.1 Quoting for Variable, Command, and Special-CharacterSubstitution

One common error in developing TCL software is incorrectly quoting strings in such a way thatvariable, command, and special-character substitution is suppressed when substitution isactually intended. In TCL, double quotes are used to quote strings in which substitution is tooccur. The following code fragments allow for proper substitution:

set data 1puts "Data: $data"; # Outputs: Data: 1puts "TCL Version: [info tcl]"; # Outputs: TCL Version: 8.0puts "Tab\tcharacter"; # Outputs: Tab character

If you find unwanted dollar signs, square brackets, or backslashes in your output, odds are thatyou've quoted a string in curly braces instead of double quotes.

2.2 Quoting for Variable, Command, and Special-CharacterSuppression

To suppress the substitution of variables, commands, and special characters, place your stringin curly braces, as seen in the following example:

puts {Referencing $variable}; # Outputs: Referencing $variableputs {Calling [info tcl]}; # Outputs: Calling [info tcl]puts {Tab is \t} # Outputs: Tab is \t

To suppress the substitution of only some elements of a string, place the string within doublequotes and use backslash (\) characters to escape the special meaning from specific characters.The following code fragment suppresses substitution of the first dollar sign:

set var 1puts "\$var == $var"; # Outputs: $var == 1

2.3 Default to the Use of Double Quotes to Quote StringsIt might seem that a standard rule for quoting should be to quote data in curly braces when itcontains nothing to be expanded or when you wish to suppress substitution and to use doublequoting in all other cases. However, this practice is not recommended. Instead you shoulddefault to the use of double quoting wherever possible. The reason for this rule is that curlybraces are used extensively throughout a script to quote code blocks. Quoting data in doublequotes makes it stand out as uniquely "data" amongst all the other quoting.

So use double quotes by default to quote all data. Use curly braces to quote data only when youneed to suppress substitution.

1 Quoting

ATS Automated Test Software Style Guide 3

Page 9: ATS Style Guide

Instead of quoting a string as in the following example:

set variable {This is the contents of the variable}

you should quote the string using double quotes, as in this example:

set variable "This is the contents of the variable"

2.4 Quote Single-Element Strings Using Double QuotesIn order to visually highlight string data, always quote a string using double quotes—even if thestring is composed of only a single word. The following code fragment shows proper quoting of asingle-element string:

pak_process parse $pak "output"

The exception to this rule is that you need not quote single-variable strings or strings that arebeing passed to a procedure as a subcommand. In the example above, the argument variable$pak is not quoted, because it is a single-variable string, and the string 'parse' is not quotedbecause it is a pak_process subcommand argument. The argument string 'output' is quotedbecause it is a string data argument.

2.5 Quote Expressions Using Curly BracesAlways quote expressions using curly braces. The consistent use of curly brace quoting helpsestablish visual consistency within your code, improves performance, and can prevent errors inlooping logic.

This section presents explanations for a policy of quoting all expressions using curly braces.

2.5.1 Quote Expressions Using Curly Braces to Maintain Consistency

Always quote expressions using curly braces to establish visual consistency within your code.

TCL requires you to quote expressions only if they contain spaces. Therefore, many expressions(for example, Boolean expressions) need not be quoted. The following code fragment shows anif statement containing an unquoted Boolean expression:

set var 1if $var {

puts "var is true"}

Although this code fragment will evaluate, it breaks the visual consistency of code in which allother expressions are quoted in curly braces. In the following example, notice that the firstexpression is not quoted while all others are:

if $debug_flag {if {$debug_option == "verbose"} {

puts "Verbose debugging is requested"} else {

puts "Non-verbose debugging is requested"}

}

To improve the visual consistency of the example above, the first expression should be quoted

1 Quoting

ATS Automated Test Software Style Guide 4

Page 10: ATS Style Guide

using curly braces:

if {$debug_flag} {if {$debug_option == "verbose"} {

puts "Verbose debugging is requested"} else {

puts "Non-verbose debugging is requested"}

}

Notice that in this reimplementation of the previous example, the if expression '$debug_flag'has been quoted.

2.5.2 Quote Expressions Using Curly Braces to Improve Performance

An even greater reason for quoting all expressions using curly braces concerns performance. Ifyou fail to quote an expression, the TCL interpreter will perform variable, special-character, andcommand substitution on the expression twice—first before the command is evaluated, andagain when the command evaluates the expression. By quoting expressions in curly braces, yousuppress the first substitution pass and as a result improve the performance of the command.

Consider the following example in which the expression is quoted using square brackets to forcecommand substitution:

if [string match "-verbose" $args] {puts "The verbose argument was received"

}

Because the above expression is not quoted using curly braces, it will incur the overhead ofhaving multiple substitutions performed on the expression. The following code fragment showsthe above example rewriten to properly quote the if expression:

if {[string match "-verbose" $args]} {puts "The verbose argument was received"

}

Although quoting with both curly braces and square brackets in the example above may seemredundant, it should be used anyway because it improves the performance of the code bysuppressing the first substitution pass.

Note: Because of the performance impact, failing to quote expressions in curly braces willproduce a warning message when you scan your code using the Tcl validator, Tclchecker(formerly named Procheck). This utility is located in '/auto/ttsw/bin/tclchecker'. You must run'/auto/ttsw/bin/as-install-license' to install a product license before you can run tclchecker.

In another application of this standard, you should always quote arithmetic expressions usingcurly braces. As is the case with other expressions, the reason for quoting arithmetic expressionin curly braces is both a cosmetic and performance consideration. For example:

set var [expr {$a * $b}]

In this example, the expr command will perform substitution on the expression before it isevaluated. Because the expression is quoted, the interpreter will not perform substitution beforethe expression is passed to expr. This treatment will dramatically improve the performance ofthis command.

2.5.3 Quote Looping Expressions Using Curly Braces

You should use curly braces to quote expressions passed to looping commands such as the

1 Quoting

ATS Automated Test Software Style Guide 5

Page 11: ATS Style Guide

TCL while and for commands not only to maintain visual consistency and suppress multiplesubstitutions but also to prevent infinite loops. Consider the following example:

set flag 1set count 1

while $flag {incr countif {$count > 100} {

set flag 0}

}

At first glance, it would appear that the above code fragment is a clumsy attempt to stay in a spinloop for 100 iterations. However, since the variable reference $flag is replaced with the value ofthe variable before being passed to the while command, this in fact becomes an infinite loop, asin 'while 1' . Such errors can be avoided by enclosing the expression in curly braces and thusdeferring the variable substitution of $flag to a point within the while loop. This can be seen inthe following example:

set flag 1set count 1

while {$flag} {incr countif {$count > 100} {

set flag 0}

}

The same potential for error and associated style convention applies to use of the TCL forcommand and any other looping command expression.

Warning: Never quote expressions in double quotes. This treatment is meaningless because allexpressions can be evaluated and substituted just as easily by the command to which they'repassed, and it ruins the visual consistency of your code. It also leads to substitution errors suchas those just discussed.

In summary, quote all expressions in curly braces to achieve visual consistency, improvecommand performance, and avoid infinite loops. The following example demonstrates curlybrace quoting used to accomplish all these goals:

if {[info exists flag]} {if {$flag} {

for {set i 1} {$i < 10} {incr i} {puts "${i}: Flag is set"

}} else {

puts "Flag is not set"}

}

2.6 Quote Code Blocks Using Curly BracesCode blocks should always be quoted within curly braces, with the first command and closingbrace starting on their own lines. Although double quotes can be used to quote a code block,this practice should be avoided because the TCL interpreter will immediately evaluate andexpand the variable and command substitutions in the block before they are passed to theconditional or looping logic used to execute them. In all cases, opt for deferred evaluation of thecode. This is achieved by quoting the code block within curly braces. The use of curly braces toquote code blocks also contributes to consistency within your software and makes the code

1 Quoting

ATS Automated Test Software Style Guide 6

Page 12: ATS Style Guide

block stand out as a code block.

For example, rather than coding this:

if {[string match "8*" [info tclversion]]} "puts "This is TCL version 8"

"

you should code the following:

if {[string match "8*" [info tclversion]]} {puts "This is TCL version 8"

}

In this case, both quoting styles would produce the same result; however, notice that the secondstyle makes the code block stand out as something different from the quoted string in the stringmatch expression.

The following example shows a case in which double-quoting of a code block will not producethe desired result:

set counter 0while {$counter < 10} "

set counter [expr {$counter + 1}]"

Here, because the code block is double-quoted, it will be evaluated by the TCL interpreter beforeit is passed to the while command, with the result that the body of the while statement becomesthe static expression 'set counter 1' . This will produce an infinite loop.

Note that you should always quote the body of a conditional or looping command, even if it is notrequired. This practice will help to establish a consistent visual look for all command bodies, asseen in the following example:

if {$option == "debug"} {debug

}

2.7 Quote Procedure Bodies and Script Sections Using CurlyBraces

Treat procedure bodies and script sections as you would code blocks by always quoting them incurly braces. For example, you should never code these elements as follows:

proc display {msg} "puts $msg

"test_config "

$router config "interface Ethernet1no shutdown

""

Not only does the use of double quotes confuse the visual presentation of your code but, in thecase of the procedure definition example above, it causes errors. The above procedure definitionwill perform a variable substitution on $msg when the procedure is defined instead of when it iscalled. Quote all procedure bodies using curly braces so that evaluation and substitution will bedeferred until invocation.

1 Quoting

ATS Automated Test Software Style Guide 7

Page 13: ATS Style Guide

The above example should be coded as follows:

proc display {msg} {puts $msg

}test_config {

$router config "interface Ethernet1no shutdown

"}

2.8 Quote Non-Space-Delimited Variable Names Using CurlyBraces

Place curly braces around variable names to delimit them in relation to surrounding text whenwhite space or punctuation cannot be used for this purpose. You may encounter the need todisplay the contents of a variable with no space between those contents and surrounding fixedtext. In the following code fragment, we're attempting to display the contents of the variable varconcatenated with the string 'd':

set var "value"puts "$vard"; # Produces an error

This code fragment will produce an error because the TCL interpreter will search for a variablenamed vard. Instead, we should encapsulate the variable name in curly braces to delimit it, as inthe following example:

set var "value"puts "${var}d"; # Outputs "valued"

This code fragment will be correctly interpreted to produce the output valued.

In cases in which a variable name is not delimited by a space but is delimited by characters thatare not valid within a variable name, the TCL interpreter will correctly interpret the code, as in thefollowing examples:

set var1 "my"set var2 "data"puts "$var1$var2"; # Outputs "mydata"puts "$var1.$var2"; # Outputs "my.data"

The coder may excercise discretion as to whether to quote the variable names:

set var1 "my"set var2 "data"puts "${var1}data"; # Outputs "mydata"puts "${var1}${var2}"; # Outputs "mydata"puts "${var1}.${var2}"; # Outputs "my.data"

2.9 Quote Procedure Argument Lists Using Curly BracesTCL requires you to quote the list of arguments accepted by a procedure if that procedureaccepts more than one argument. This practice is required so that the argument list can bepassed as a single element to the TCL proc command. When a procedure accepts only oneargument, TCL does not require that argument name to be quoted; for example:

1 Quoting

ATS Automated Test Software Style Guide 8

Page 14: ATS Style Guide

proc msg string {puts $string

}

Although TCL does not require you to quote single-argument lists, you should always quote allprocedure arguments lists in curly braces to establish consistency in the look of all proceduredefinitions. Therefore, the above example should be coded as follows:

proc msg {string} {puts $string

}

Note: When a procedure accepts no arguments, you should supply an empty list ({}) as theargument list in the procedure definition.

1 Quoting

ATS Automated Test Software Style Guide 9

Page 15: ATS Style Guide

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 10

Page 16: ATS Style Guide

3 Commands and Code Blocks

This section discusses style issues related to coding of TCL commands and code blocks in yoursoftware. Code blocks contain multiple commands that are to be evaluated by a command orprocedure, typically either conditionally or in a loop.

3.1 Command Placement and LengthAn important aspect of script readability, and therefore its maintainability, is the placement andlength of commands. Typically, commands should be written on separate lines in such a waythat no individual command exceeds 80 characters in length. This section discusses these twoaspects of command coding, providing examples and outlining the exceptions to these generalrules.

3.1.1 Code One Command per Line

Although TCL supports the ability to code multiple commands on a single line by ending eachcommand with a semicolon (;), you should not take advantage of this feature. Code TCLcommands on separate lines. By encoding each command on its own line, you'll make yourscripts easier to read, understand, and debug.

The only appropriate times to use semicolons in an ATS script are when placing a comment atthe end of a line and when separating variable set commands in for loop expressions. You canuse this method to comment on variables and constant definitions, to document the ends ofdeeply nested code blocks, and to highlight commands of interest.

The following example shows the use of the semicolon in these instances:

set FAIL 0; # Use this constant to return failure from a scriptset PASS 1; # Use this constant to return success from a script

for {set s 1; set p 0} {$s < $MAX_STRING} {incr s; incr p} {if {$s == 1} {

...}; # End of if {$s == 1}

}; # End of for loop

Most TCL examples will show the semicolon indented to immediately precede the pound sign (#)(for example, 'set FAIL 0 ;# Use ...' ). An alternative is to terminate the command withthe semicolon and place spaces after the semicolon up to the comment character. You shouldfeel free to use either convention, but stay consistently with one style or the other.

Note: The need to use end-of-block comments can point to the fact that your nested blocks aretoo long. You may want to reduce the length of some blocks by turning them intowell-documented procedures rather than leaving them as one long listing of code.

3.1.2 Split Lengthy Lines

To enhance readability, no single line of TCL code should exceed 80 characters in length.Because many developers set their editor window width to 80 characters, lines that exceed thislimit can produce ugly line wrapping that will adversely effect the readability of your code. Thissection discusses methods for implementing this safe and sane coding practice.

The use of 80-character line lengths is a convention inherited from the Cisco IOS style standard.This is a widely used standard within the computing industry.

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 11

Page 17: ATS Style Guide

3.1.2.1 Split Command Lines That Exceed 80 Characters

No single line of your script should exceed 80 characters in length. Split comment linesappropriately to ensure that no single line of comment exceeds this limit. In the case ofcommand lines that exceed 80 characters in length, you should split the command onto multiplelines by ending each line with backslash character (\) followed by a newline. The backslashcharacter escapes the meaning of the newline (newline is interpreted by TCL as end ofcommand) so that the command can be continued on subsequent lines. For example:

if {[string index [lindex $arg 0] 0] == "-" && \[lindex $arg 1] != "false"} {...

}

Some command lines become very long because of nesting of command substitutions in theline. You should split such commands by using temporary variables to store intermediate resultsand then using the variables in the final command. For example, the following command:

if {![regexp {input: +([0-9]+),.+output: +([0-9]+),} \[$router exec "show interface ethernet 0"] - input output]} {log_diagnostic_msg "Unable to parse shoud interface output"update_test_status $FAILreturn

}

could be recoded as:

set pattern {input: +([0-9]+),.+output: +([0-9]+),}set output [$router exec "show interface ethernet 0"]if {![regexp $pattern $output - input output]} {

log_diagnostic_msg "Unable to parse shoud interface output"update_test_status $FAILreturn

}

Note: Upon release, this document suggested a maximum line length of 72 characters. Reviewcomments indicated that this was too short. All agreed that lines should not exceed 80characters. However, most agreed that lines of no more than 76 characters produce morereadable code by not crowding the right hand window border and producing a right hand marginroughly the size of the 4 character left hand indent used on many lines. Additionally, code linesof fewer than 80 characters leave room for display of carriage returns by some editors and allowdevelopers to position the cursor at the end of the line without having it wrap to the next line (e.g.78 characters) It is therefore suggested that you try to leave some space to the right of eachcode line. To this end, 76 characters is a good target to shoot for.

3.1.2.2 Use join to Split Strings That Exceed 80 Characters

No string within your script should exceed 80 characters in length. In the case of very long stringconstants, you should split the string into multiple string values and merge them using the TCLjoin and list commands. For example:

log_message [join [list "Interface $interface packet counters," \"Input counter: $input, Output counter: $output"]]

In the above example, a lengthy string is split into two smaller strings. These strings are passedto the list command to be turned into a single two-element list, which is in turn passed to thejoin command to be merged into a single string. By default, the join command places a spacebetween joined list items. You can pass an optional second argument to join to specify the join

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 12

Page 18: ATS Style Guide

character; for example, {} would place no characters between the joined list elements.

When this method is used to split long strings across multiple lines, tabs and spaces used toalign code lines will not be included as part of the new string. Additionally, newline characterswill be excluded. When a very long string of text is defined , it is sometimes preferable to allowthe newlines to be included in the string so that you can control where long strings break onoutput. For example:

set message {When this method is used to split long strings acrossmultiple lines, newline characters will be escaped so theydo not appear in the string. When a very long string oftext is defined, it is sometimes preferable to allow thenewlines to be included in the string so that you can controlwhere long string break when output.}

3.1.2.3 Split Commands at Logical Breaks

When splitting a long command onto multiple lines, you should not arbitrarily split the command.Instead, split the command at the natural separation points in the meaning of the command. Forexample, rather than coding this:

for {set iptr 0; set optr 0} {iptr < $END_OF STRING} {incr \iptr} {...

}

you should code this:

for {set iptr 0; set optr 0} {iptr < $END_OF STRING} \{incr iptr} {...

}

Notice the improved readability of the above command caused by breaking the lengthycommand line between expressions rather than in the middle of an expression.

3.2 Code BlocksCode blocks represent groups of commands that should all be executed in sequence, usually asa result of a conditional expression or within a loop. This section discusses style issues relatedto coding of TCL code blocks.

3.2.1 Quote Code Blocks Using Curly Braces (Reminder)

Code blocks should always be quoted within curly braces. For a detailed discussion of codeblock quoting, refer to .

3.2.2 Align Opening and Closing Code Block Curly Brace

Code blocks should always be opened by placing the opening curly brace at the end of thecommand to which the code block is associated and ended by placing the ending curly brace ona line of its own. The indentation of the opening command line and the closing curly braceshould be the same. For example:

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 13

Page 19: ATS Style Guide

if {[string match "8*" [info tclversion]]} {if {[string match "*2" [info tclversion]]} {

puts "This is TCL version 8.2"}

}

Notice that in the above example, each code block's opening curly brace appears at the end ofthe line containing the if statement, and the closing curly brace is aligned at the sameindentation as the associated if statement.

When including an else or elseif extension in an if statement, you should place them on thesame line as the closing curly brace, as seen in the following example:

if {[string match "8*" [info tclversion]]} {if {[string match "*2" [info tclversion]]} {

puts "This is TCL version 8.2"} elseif {[string match "*3" [info tclversion]]} {

puts "This is TCL version 8.3"} else {

puts "This is TCL version 8"}

}

3.2.3 Indent the Contents of Code Blocks Four Spaces

Blocks of code can be nested, and quite often are. For example, TCL if command bodies cancontain additional if statements. In the case of nested code blocks, each code block should beindented four spaces. See for a detailed discussion of this topic.

3.2.4 Avoid Excessively Long or Deeply Nested Code Blocks

As much as possible, avoid excessively long or deeply nested code blocks. When code blocksare extremely long, it is difficult for anyone browsing the code to fully understand the actionsperformed by the code block and then return to the original command flow of the script. Deeplynested code blocks make it difficult for a reviewer of your code to keep track of the manyconditions that must be satisfied to enter a block of code. As a general rule, try to write codeblocks that are no longer than 24 lines (one screen) and are nested no more than three codeblocks deep.

When logic requires long code blocks or deep nesting, the logic should be broken up intomultiple procedures called from the script or procedure containing the nesting. For example:

if {$access_list_flag} {access_list_apply $interface_listforeach interface $interface_list {

set result [access_list_evaluate $interface]if {$result} {

puts "Access list looks good"} else {

puts "Access list looks bad"}

}}

The example provides an overview of the operations being performed by the script while hidingthe particulars of how the operations are performed in procedure definitions. This provides anappropriate level of detail for someone wishing to review a script's functionality; for example,someone trying to determine whether to incorporate a script into their test plan. Logic details canbe obtained by reviewing each called procedure. The use of procedures to shorten long code

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 14

Page 20: ATS Style Guide

blocks and reduce deep nesting also promotes code reusability.

3.2.5 Treat Script Sections and Device Configurations As Code Blocks

In many cases, blocks of code or device configuration commands are passed to a procedure forevaluation. For example, the test_config procedure is used in Autotest scripts to bracket codethat initializes a testbed before a test is executed and analyzed. Additionally, the CSCCONrouter control library config subcommand is used to specify a block of router configurationcommands to be applied to a router. In both these cases, the instructions being passed to theseprocedures should be treated like code blocks, following all the style rules that apply to suchblocks. For example:

package require Cscconpackage require Test

set router "my_router"

test_config {$router config {

interface ethernet1no shutdown

}}

test_analyze {set result [$router exec "show interface ethernet1"]if {[regexp "line protocol up" $result]} {

puts "Everything looks good on ethernet1"}

}

Notice that standard indentation rules are followed for the if command body being passed to thetest_analyze procedure for evaluation.

Note: Device configuration blocks are often double quoted to allow for variable expansion.However, you should still indent them as you would any other code block.

3.2.6 Treat Procedure Bodies As Code Blocks

Indent procedure bodies four spaces (just like any other code block). The closing curly brace forthe procedure body should align with the beginning of the proc command that initiated thedefinition (nearly always column 1). For example:

proc display {msg} {puts $msg

}

3.3 Command ExpressionsArithmetic and Boolean expressions are often passed to TCL commands to perform calculationsor to influence conditional command evaluation. This section discusses the style standards forcoding such expressions.

3.3.1 Use Spaces to Delimit Operators and Values in Expressions

TCL doesn't require you to use white space separation between numbers, variables, and

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 15

Page 21: ATS Style Guide

operators in expressions because the operator characters are interpreted as number andvariable name terminators. When coding lengthy expressions, you may be tempted to removewhite space from the expression in order to fit the entire expression on a single line. Forexample:

if {($pak_siz>=64&&$pak_siz<=1500)||!$pak_err_flg} {puts "Packet contains an error"

}

However, the simple lack of white space in the above example makes the expression difficult toread. When coding expressions, you should always include white space around operators,numbers, and variable names. If the inclusion of white space forces the expression to exceed asingle line, split the expression onto multiple lines using command continuation (\). Using thisconvention, the previous example would be coded as follows:

if {($pak_siz >= 64 && $pak_siz <= 1500) || !$pak_err_flg} {puts "Packet contains an error"

}

Notice the improvement in readability produced simply by adding white space. Some users findthat adding a single space after and before the opening an closing curly braces enhances thereadability of an expression.

3.3.2 Exclude the Equality Operator from Boolean Expressions

When using an if statement to test a variable's contents for either true or false (1 or 0), you donot have to code the comparison with true or false. Just code the variable to be evaluated as thesole contents of the expression. For example, rather than coding:

set flag 1if {$flag == 1} {

puts "Flag is true"}

you should code:

set flag 1if {$flag} {

puts "Flag is true"}

Both expressions produce the same result; however, the second is terser and easier to read. Inthe first example, '$flag == 1' is replaced by TCL with the result of the comparison, which istrue (1), so the statement is evaluated as 'if {1}' . The same is true of the second example, inwhich the variable $flag is replaced with its contents ('1').

In addition to performing Boolean comparisons on variable contents, such comparisons can beperformed on the result of command substitution, as in the following example:

If {[info exists myflag]} {puts "myflag: $myflag"

}

Note: To negate a Boolean expression (for example, to test the expression for "falseness"),precede the expression with a not sign (!), as in the following examples:

if {!$flag} {puts "Flag is false"

}if {![regexp {foobar} $output]} {

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 16

Page 22: ATS Style Guide

puts "Unable to parse output: $output"}

3.3.3 Explicitly Define Expression Operation Precedence

Both arithmetic and Boolean operations in an expression are performed in the standard order ofprecedence as dictated by the rules of math and logic. The order of evaluation, from top tobottom and left to right, is as follows:

Unaryoperators

- + ~ !

Binaryarithmeticoperators

* / % + -

Bitwise shiftoperators

<< >>

Comparisonoperators

< > <= >= == !=

Inequalityoperators

< > <= >=

Bitwise unionoperators

& ^

Logicaloperators

&& ||

If-then-elseoperator

x?y:z

Even though the number of commonly used operators is small, it can be difficult to rememberthe order in which operations are performed. Even if you do know the order, there's noguarantee that the next person who works on your code will. Therefore, you should alwaysexplicitly define the order of the operations to be performed in a multi-operation expression bygrouping the operations using parentheses, as in the following example:

if {($var > 10) && ($var < 100)} {puts "Value is within range"

}set var [expr "(($foo * 100) - ($bar / 7)) + 3"]

3.4 Special Command ConsiderationsThis section discusses style rules as they apply to specific TCL commands. In some cases,coding of TCL commands stretches or breaks the general style rules to enhance the readabilityof a specific command. In other cases, the coding of a command allows options that should bestandardized to develop a consistent style.

3.4.1 Handling switch Statements

Switch statements may break the rule for writing code blocks on separate lines. When the actionto be performed by a switch case is a single statement, that statement can be coded on thesame line as the switch command expression being evaluated. For example:

set option [lindex $args 0]

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 17

Page 23: ATS Style Guide

set value [lindex $args 1]switch -- $option {

"-logging" {set logging 1]"-nologging" {set logging 0}"-timeout" {set timeout $value}

}

Note: The -- option is passed in the switch statement above not only to utilize the defaultmatching mechanism ( '-exact' ) but to ensure that the contents of the option variable are notmisinterpreted as an option should its contents begin with a hyphen.

Since a single TCL switch statement can encapsulate a great deal of logic, lengthy code blockscan be associated with each expression. It is sometimes desirable to have each expressionevaluate a single procedure invocation instead of a block of code to keep the switch statementshort. Coding lengthy logic within a switch statement can be extremely confusing because it isdifficult to implement an indentation rule that will make sense of the result.

A default case is recommended for each switch statement in order to ensure that appropriateactions are taken for all possible values. In some cases, this could be just to indicate that anunexpected value was found and needs a case to be added for it.

3.4.2 Handling for Statements

The TCL for statement accepts four blocks of code for evaluation. The first block of code isexecuted when the statement is entered and is used to initialize the environment. The secondblock of code is an expression used to determine whether the statement should continue to beevaluated. The third block is evaluated between iterations of the for loop. The fourth block, thebody, contains the statements to be evaluated during each iteration.

The first three code blocks that are passed to a for statement are usually very small. Therefore,when coding a for statement, you can code the first three code blocks on a single line, but thefourth block should be coded on multiple lines as in the case of an if statement body. Forexample:

puts "Countdown: "for {set i 1} {i <= 100} {incr i} {

puts "\t$i..."}puts ""

When one or more of the first three code blocks of a for statement are so long as to exceed 80characters when taken together, the blocks should be separated onto multiple lines, as in thefollowing example:

for {set i 0; set j [length $string]} \{$i < $j} {incr $i; incr $j -1} {...

}

Notice in this example that semicolons have been used to separate statements within two codeblocks. Since for command code blocks are typically very short, it is acceptable, and oftendesirable, to use semicolons in these code blocks to allow placing the entire code block on asingle line.

3.4.3 Do Not Include then in if Statements

Although TCL supports the optional inclusion of the then clause, you should not include it in yourif statements. For example:

if {1} then {

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 18

Page 24: ATS Style Guide

puts "True"}

should be coded as:

if {1} {puts "False"

}

The two if statements shown above produce identical results. The first statement includes theoptional then clause, which adds nothing to the understanding of the statement and makes ifdiffer from other standard languages such as C and Perl that don't support the then clause. Youshould always use the second form when encoding an if statement.

3.4.4 Using switch Versus elseif Statements

In most cases, you should be perfectly content to code conditional branching logic using ifstatements containing elseif and else clauses. For example:

if {[string match "8*" [info tclversion]]} {if {[string match "*2" [info tclversion]]} {

puts "This is TCL version 8.2"} elseif {[string match "*3" [info tclversion]]} {

puts "This is TCL version 8.3"} else {

puts "This is TCL version 8"}

}

However, should the number of conditions to be evaluated become exceedingly long, you shouldinstead use a switch statement to reduce the amount of code needed to perform the evaluation.For example:

switch -glob [info tclversion] {"8*2" {puts "This is TCL version 8.2"}"8*3" {puts "This is TCL version 8.3"}"8*" {puts "This is TCL version 8"}

}

A single switch statement is often easier to read and understand than a lengthy chain of elseifexpressions. Consider using switch instead of if when the number of expressions to evaluateexceeds three.

3.4.5 Use "--" string to mark end of options

Some Tcl commands support an arbitrary number of dashed options followed by an arbitrarynumber of arguments: in particular, regexp, regsub, and switch. Where an argument has thepossibility of starting with a dash, Tcl can be confused into thinking an argument is an optionwhere it isn't. Even if the argument is constant and doesn't start with a dash, there is thepossibility of code being modified in the future and making it non-constant with dash as apossible first character. To avoid bugs, you should always use the "--" string to mark the divisionbetween options and arguments, even if it does not currently seem necessary.

regexp -all -nocase -- $pattern -> result

3.4.6 Handling uplevel and upvar statements

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 19

Page 25: ATS Style Guide

The uplevel and upvar statements both take an optional first argument that indicates where inthe call stack the command should apply. For uplevel, the given command is executed in theappropriate scope. For upvar the named variable in the appropriate scope is linked to a localvariable. By default, the scope is that of the immediate parent in the call stack.

There can, however, be a performance impact and Tcl may do the wrong thing if the firstargument looks like it could be a level because these commands take a variable number ofarguments. To prevent this, always specify a level as the first argument. Use level 1 to get thesame scope as you would if the level were not specified:

uplevel 1 $cmd $args

3.4.7 Handling case statements

The case command is an obsolete form of switch. It should not be used in new code, andpreferrably should be replaced by switch. The command uses and style rules are very similar.

1 Commands and Code Blocks

ATS Automated Test Software Style Guide 20

Page 26: ATS Style Guide

4 White Space and Indentation

It may only be empty space, but it's still important to the readability and maintainability of yoursoftware. This section discusses standards for the use of white space to separate your softwarevisually into sections and to highlight the nesting of code blocks.

4.1 Code Logic White-Space SeparationBlank lines of separation can be used to separate your software visually into blocks of logic. Thissection discusses two methods for visually delimiting the logical blocks of your software usingwhite space.

4.1.1 Use One Line of White Space to Visually Segment Software Logic

Use of blank lines in your software is an effective way to separate and group your program logic.Your choice of the groupings that you highlight is somewhat subjective, but in general youshould attempt to group your code into blocks of from 2 to 20 lines by placing blank linesbetween related blocks of code. For example:

set output [$router exec "show interface $int1"]foreach s [split $output "\n"] {

regexp {([0-9]+) packets input} $output - $ipaks}if {![info exists ipaks]} {

log_diagnostic_msg "Unable to parse router show interfaceoutput:\n$output"

update_test_status $FAILreturn

}

if {$output > $threshold} {log_diagnostic_msg "Input packet threshold ($theshold) exceed"update_test_status $PASS

} else {log_diagnostic_msg "Input packet threshold ($theshold) not

exceed"update_test_status $FAIL

}

Note: The use of white-space separation is particularly effective in combination with code blockcomments, as seen in the following enhanced version of the example above:

# Extract the input counter value from the router# "show interface" output for the target interfaceset output [$router exec "show interface $int1"]foreach s {[split $output "\n"]} {

regexp {([0-9]+) packets input} $output - $ipaks}if {![info exists ipaks]} {

log_diagnostic_msg "Unable to parse router interfaceoutput:\n$output"

update_test_status $FAILreturn

}

# Register the result of this test based on the number# of incoming packets receivedif {$output > $threshold} {

log_diagnostic_msg "Input packet threshold ($theshold) exceed"

1 White Space and Indentation

ATS Automated Test Software Style Guide 21

Page 27: ATS Style Guide

update_test_status $PASS} else {

log_diagnostic_msg "Input packet threshold ($theshold) notexceed"

update_test_status $FAIL}

Just a word of caution: don't overuse white space when separating code logic. A single line ofwhite space will suffice for separation; never use more.

If you're adding white space to enhance the printed output of your code, use the techniqueoutlined in the next section instead.

4.1.2 Using Formfeeds for Print Formatting

You may optionally choose to insert formfeed characters (^L) into your software to enhance itsreadability when printed. These characters will be ignored by the TCL interpreter but will force aprinter to eject the current page before printing continues. You can use formfeeds to force blocksof code to remain together on a single page. For example, you may wish to place formfeedsbetween all procedure definitions in a library.

The method used to insert formfeeds into your software is dependent upon your editor. InEmacs, enter the key sequence C-qC-l

4.2 Indent Nested Code Blocks Four SpacesBlocks of code can be nested, and quite often are. For example, TCL if command bodies cancontain additional if statements. If code blocks are nested, each code block should be indentedfour spaces. By indenting each nested code block four spaces, you'll clearly identify separationsin the logic of your software.

For example:

foreach s {"one" "two" "three"} {set len [string length $s]if {$s == "one"} {

puts "The first string is length of $len"} else {

puts "This isn't the first string"puts "Its length is $len"

}}

This indentation standard is adopted from the Cisco IOS router software style guide.

Note: Any combination of tab and space characters can be used to produce the requiredindentation. The standard is to insert the required number tabs, bound to 8 character tab stops,followed by 4 spaces if required.

1 White Space and Indentation

ATS Automated Test Software Style Guide 22

Page 28: ATS Style Guide

5 Comments

Anything that aids in the readability of software, such as white space, also enhances itsmaintainability. Comments are another such element. It is important to comment your code sothat you and others can better understand it later.

This section contains a description of the various styles of commenting that should beincorporated into a well-formed script.

5.1 Format Comments Like Bullet ItemsAll comments should begin with a pound sign (#) followed by a single space and a sentencewhose first letter is capitalized. You may indent portions of a comment to highlight sample textand other items that are not part of the comment being made.

Comment sentences are typically not terminated by periods. If several sentences are required tocreate a comment, you can either end each sentence with a period or simply begin eachsentence on a new comment line. Always use an initial capital letter.

Comments must appear on a line by themselves unless they follow a semicolon. Separation ofcommands and comments by means of a semicolon should be used only to document variablesand the end of nested blocks.

Each comment line must not exceed 80 characters in length. For example:

# Update the program counter...

# Extract the input packet counter from the router show# interface output...

# Recalibrate the traffic rate# Traffic rate recalibration must be performed periodically# to ensure valid test results...

This standard applies to embedded code comments. Header comments should be written as youwould a document, using periods to terminate sentences and blank lines to represent paragraphbreaks.

5.2 Comment All Logical Blocks of CodeNatural breaks in software logic should be delineated with a single line of white space. Inaddition, each block of software logic should be preceded by a brief comment explaining theoperation being performed. For example:

# Display a sorted list of the TCL commands# Insert blank lines between commands beginning with# different characters

# Iterate across a sorted list of all TCL commandsset command_list [lsort [info commands]]

1 Comments

ATS Automated Test Software Style Guide 23

Page 29: ATS Style Guide

foreach command {$command_list} {

# Print a blank line between commands starting with# different charactersset first_letter [string index $command 0]if {[info exists prev_letter]} {

if {![string match $first_letter $prev_letter]} {puts ""set prev_letter $first_letter

}}

# Display the current commandputs $command

}

In the above example, we've preceded the entire code fragment with a comment explaining itsfunction, and then we've inserted brief comments to explain each logical portion of the code.Notice that there is no blank line placed between the comment and the code in the individuallogic blocks. This practice binds the comment to the code being described.

5.3 Indent Comments to Align Them with the Code ThatFollows

Comments that describe a following block of code should be indented to align with the code. Thealignment make it obvious that the comment belongs with the following code. For example:

# Iterate across a sorted list of all TCL commandsset command_list [lsort [info commands]]foreach command {$command_list} {

# Print a blank line between commands starting with# different charactersset first_letter [string index $command 0]if {[info exists prev_letter]} {

if {![string match $first_letter $prev_letter]} {puts ""set prev_letter $first_letter

}}

# Display the current commandputs $command

}

5.4 Add Comments at End of Nested Code Blocks (Optional)When code blocks are long or excessively nested, it is sometimes difficult to determine whichcode block is being closed by a curly brace. In these cases, follow the curly brace with a briefcomment identifying the code block being closed. For example:

if {$route_flag} {...foreach route {$route_list} {

...if {$security_flag} {

...}; # End of if {$security_flag}

}; # End of foreach route loop}; # End of if {$route_flag}

1 Comments

ATS Automated Test Software Style Guide 24

Page 30: ATS Style Guide

When a comment is placed on the same line as a closing curly brace, or any other TCL syntaxelement, the comment must be separated from the brace by a semicolon (;). The semicolonindicates that the current command is completed and a new command follows—that newcommand being a comment in this case.

Warning: You shouldn't need to make frequent use of this style element because no code blockshould be so long or so deeply nested as to cause the reader to lose track of the closing curlybrace. It is preferable to break such code blocks into multiple procedure calls. However, if youabsolutely must keep the logic all in one place, use this method to document your code blocks.

5.5 Variable CommentsVariables and data structures may warrant special documentation. Some software maintains agreat deal of data stored in several variables. Both TCL arrays and keyed lists can be used tocreate complex data structures containing multiple fields, each for a specific purpose. In suchcases, add comments to your code explaining the use of important variables and datastructures.

5.5.1 Document Constants and Important Variables

Variable constants (explained later in this document) should be defined at the beginning of yourscript. In addition to initializing each constant, you should include a comment explaining thepurpose and use of the constant. For example:

set MAX_RETRY_COUNT 10; # Maximum number of times to try anoperationset MIN_PAK_SIZE 64; # Minimum size of a valid IP packetset MAX_PAK_SIZE 1500; # Maximum size of a valid IP packet

The convention of using a semicolon followed by a comment describing the constant conservesspace so that all constant definitions can be viewed on a single screen.

Use simple comments to document important variables, as shown in the following example:

# Important Variables:## command_max Maximum number of commands to be processed# command_current Current command being processed# command_prev Last command processed

5.5.2 Document Internal Data Structures

Complex data structures do not need to be initialized. So there is no initialization statement toprovide an obvious place for descriptive comments. However, you should still include commentsat the top of your script explaining the use of such variables and the purpose for each field. Forexample:

# Important Data Structures:## Global Array: tcl_command_list# Used to store information about TCL commands# Indexes:# command,[1-n] Contains the command name# type,[1-n] Contains 'p' for proc, 'c' for command# used,[1-n] Exists if the command has been executed

The above example shows the documentation for a complex data structure that could be used to

1 Comments

ATS Automated Test Software Style Guide 25

Page 31: ATS Style Guide

store information about TCL commands. The data structure is stored as an array and containselements for the command name itself, whether the command is a proc or a TCL built-incommand, and a flag to indicate whether the command has been executed. The array isinitialized later in the script, so a block comment is used to document it.

5.6 Script Header and Footer CommentsAll ATS test scripts should contain standard script header and footer comments to assist users inthe execution and maintenance of the script. This section discusses the format of thesecomments.

5.6.1 Include the Standard Script Header Comment

All scripts should begin with a standard header comment containing a common set of descriptiveelements in a specified order. This comment, known as the standard script header comment,specifies the minimum information that the header should contain and can be extended toinclude additional information as needed.

The script header should be placed immediately after the interpreter invocation line at the top ofyour script. The following fields constitute the script header comment:

##ScriptHeader

A visual flag that indicates to automated documentation generatorsthat the following comment is a script header comment.

$Id: $ The first line of the header comment should be includedunmodified. This line will be replaced by Concurrent VersioningSystem (CVS) upon script checkout to indicate the version of thescript being used.

Copyright (c)2003 CiscoSystems, Inc.

The second line of the header comment should be includedunmodified. The standard Cisco copyright should be included in allsoftware developed at Cisco.

Name: The name of the script. This must match the filename containingthe script.

Purpose: A single sentence explaining the testing performed by the script.

Author: The person, identified by name and group, who developed thescript and is responsible for its maintenance.

References: (Optional) Include pointers to any external documents related tothis test script, such as a test plan or a functional specification.Supply EDCS numbers where available.

Description: A detailed description of the testing performed by the script.

Topology: A character mode diagram of the testbed topology required to runthe script. If topology is unimportant, or the script runs on a singledevice, it is sufficient to simply state the topology requirementsusing a few words.

Synopsis: An overview of the usage syntax for the script. Identify variablearguments by enclosing a symbolic name for the argument in anglebrackets. Identify optional arguments by enclosing them withinsquare brackets and separating the values by the or sign (|)surrounded by spaces. Identify required arguments by enclosingthem in curly braces and using the or sign to delimit possiblevalues. Use an ellipsis (...) to indicate that the preceding argumentcan be repeated any number of times.

1 Comments

ATS Automated Test Software Style Guide 26

Page 32: ATS Style Guide

Arguments: List the arguments accepted by the script, one argument per line,and explain the purpose and use of the argument. Include validvalues and numeric ranges in the description.

SampleUsage:

Provide samples of one or more suite or job file entries used toinvoke the script, along with comments explaining theirsignificance. Include a pointer to a committed suite file in thissection if one exists.

Pass/FailCriteria:

Interpretation of test results should be outlined. This includes thepass/fail criteria of the script. Note that if a script implementsmultiple test cases, it may be more appropriate to specify thepass/fail criteria for each test case in the "Test Steps" section ofthis header.

SampleOutput:

(Optional) Include a sample of the diagnostic output generated bythe script. Include explanations of any values that are notself-explanatory in the sample.

Test Steps: (Optional) It is often useful to enumerate the steps performed by ascript in the header comment. It may be sufficient to simply explaina script's functionality in the "Description" section, but if a scriptperforms many actions or is very complex, it may be best to outlinethese actions as numbered steps in this section.

Support Alias: (Optional) The username or mailing list used to contact theindividual or group providing support for this script.

Notes: (Optional) Any usage notes of interest that you wish to highlight forthis script.

Known Bugs: (Optional) List any known bugs in this script along with anyworkarounds.

Todo: (Optional) List any enhancements that you have planned for thescript but haven't yet implemented. You or someone else may dofurther work on the script.

See Also: (Optional) List any other related scripts that anyone running thisscript should also consider running.

# End ofHeader

Since script header comments can be lengthy, this commentprovides a visual flag that can be searched for in order to skip overthe header comment while in the editor.

The following example shows a script header comment for a typical script:

##Script Header# $Id: $# Copyright (c) 2003 Cisco Systems, Inc.## Name:# ip_static## Purpose:# Execute a three router IP Static routed ping packet# switching test using a variety media, encapsulations,# and switching modes.## Author:# Brian Jackson, Test Technologies## References:# IP Static Switching Test Plan (EDCS-12345)## Description:# This script implements a suite of tests exercising the

1 Comments

ATS Automated Test Software Style Guide 27

Page 33: ATS Style Guide

# IP protocol running on a Cisco router to determine the# success or failure of sending ping packets between two# routers through the router under test. Static routes are# applied on the source and destination routers to direct# the packet stream. The router issuing the ping packets# is refered to as the Generator (Gen). The router# responding to the ping packets is the Reflector (Ref).# The router switching packets between the Generator and# Reflector is the Unit Under Test (UUT).## This test is described as a "connectivity" or "switching"# test because its purpose is to test the UUT's ability to# switch packets between various media interfaces and# encapsulations using a variety of switching modes on a# variety of hardware platforms that are running a variety# of IOS software releases.## This script is configured for Autotest execution.## Topology:# +-----------+ +-----------------+ +-------------+# | Generator |---| Unit Under Test |---| Reflector |# +-----------+ +-----------------+ +-------------+## A three-router topology connected via multiple media.## Synopsis:# switching/ip_static Id GenDescr GenUnit GenEncap GenMode \# RefDescr RefUnit RefEncap RefMode GenInt UutGenInt \# UutRefInt RefInt Gen Uut Ref## Arguments:# Id Standard Autotest suite file line ID# GenDescr Brief description of the Generator side# media (e.g., mci_e)# GenUnit Generator side UUT card number (1 or 2)# GenEncap Generator side media encapsulation:# default, arpa, frame-relay, fr-ietf,# hdh, hdlc, iso1, noencap, ppp, ppp-stac,# smds, snap, x25# GenMode Unit Under Test Generator side switching# mode (slow or fast)# RefDescr Brief description of the Reflector side# media (e.g. mci_e)# RefUnit Reflector side UUT card number (1 or 2)# RefEncap Reflector side media encapsulation:# default, arpa, frame-relay, fr-ietf,# hdh, hdlc, iso1, noencap, ppp, ppp-stac,# smds, snap, x25# RefMode Unit Under Test Reflector side switching# mode (slow or fast)# GenInt Generator interface used in the test# UutGenInt Generator side Unit Under Test interface# used in the test# UutRefInt Reflector side Unit Under Test interface# used in the test# RefInt Refelctor interface used in the test# Gen Name of the Generator router# Uut Name of the Unit Under Test router# Ref Name of the Reflector Router## Sample Usage:# switching/ipstatic ipstatic.1 mci_e 1 noencap slow \# mci_s 1 x25 slow $router1 $router2 $router3## Pass/Fail Criteria:# Pass - If interfaces come up, configs apply, routes# appear, and ping packet switches# Fail - Otherwise

1 Comments

ATS Automated Test Software Style Guide 28

Page 34: ATS Style Guide

## Sample Output:# IP STATIC route switching from mci_e # 1 \# (slow, noencap) to mci_s # 1 (slow, x25)# No fr_ietf encaps. in $Version; skipped## Test Steps:# 1) Bring up the interfaces involved in the test and# apply the encapsulations and switching modes.# 2) Verify that all test interfaces are up.# 3) Configure the static routes on the Gen and Ref routers.# 4) Verify that the routes appear in the IP routing table.# 5) Send 5 ping packets from the Gen to Ref router.# 6) Verify that at least 80% of the ping packets are# received.# 7) Remove all configuration.# 8) Verify that the configuration is gone, the interfaces# are down, and the static routes are gone.## Notes:# 1) This script depends upon external encapsulation and# switching mode configuration information and valid# combinations as defined in the following switching# matrix files:# /autons/matrix/interns/ip/switching_matrix.91# /autons/matrix/interns/ip/switching_matrix.90# /autons/matrix/interns/ip/switching_matrix.83# 2) The $router[1-n] arguments specified in the suite# file entry will be replaced with the names of the# [1-n] routers as defined in the testbed configuration# section of the CONFIG file.# 3) To some degree, this script has become superseded# by the Core switching script located in the# tests/functionality/core directory.## Known Bugs:# None## Todo:# 1) Ensure 100% packet switching instead of 80% by# priming the ARP cache with an initial ping.## See Also:# tests/switching/* - Switching scripts for other protocols.## End of Header

Note that the standard script header comment is included in the ATS scripting templates. Whenyou copy a template, you'll have access to the comment fields that you should fill in.

5.6.2 Include the Standard Script Footer Comment

The standard script footer comment is a fixed comment as follows:

# $Log: $## ;;; Local Variables: ***# ;;; mode: tcl ***# ;;; End: ***

The footer comment is composed of two elements. The first line ( '$Log: $' ) instructs CVS toappend a copy of the commit comments to the end of the script. These commit comments canbe used by an individual browsing a script to understand the modification history of the script.There is therefore no reason to include a manually maintained modification history in the scriptheader comment (a common practice). Note that the log is maintained at the end of the script so

1 Comments

ATS Automated Test Software Style Guide 29

Page 35: ATS Style Guide

that scripters need not scroll through lengthy logs to reach the body of the script.

The second element of the footer comment, the lines beginning with three semicolons, isinstructions to the Emacs editor that tell the editor to enter tcl-mode when the script is opened.

Include the footer comment in your script as is. The standard footer comment is also included inthe ATS scripting templates.

5.7 Procedure CommentsThe comments used to document a procedure depend upon the location and purpose of theprocedure. If the procedure is defined in a script, the documentation requirements are fairlyminimal. If, however, the procedure is placed in a library, the documentation requirements aremore strict. If the library is intended for wide use—that is, by those outside your group—then thedocumentation requirements become very stringent.

Although the commenting of a locally used procedure library can be quite minimal, you may stillwant to fully comment the library as outlined in this section in anticipation of its wider use.

The following sections outline the commenting standards for procedures.

5.7.1 Include Script Procedure Comments

Procedures to be used within a single script should be defined at the top of the script. Aprocedure should be preceded by short comments describing the function performed by theprocedure. Typically, procedures located within a script are fairly short and do not call otherprocedures, so the description of these procedures can be very brief. For example:

# Repeatedly poll the router route table until the desired route# appears, returning True if the route appears and False otherwiseproc route_up {router prot addr} {

for {set i 0} {$i < $MAX_ROUTE_RETRIES} {incr $i} {if {[string match $route [$router exec "show $prot route"]]}

{return $TRUE

}sleep $ROUTE_SLEEP

}return $FALSE

}

The above example is prefaced by a very brief comment explaining what the route_upprocedure does and the value returned.

5.7.2 Include the Standard Procedure Library Header Comment

If one or more procedures are to be used by more than one script, they should be stored in aprocedure library that can be shared by those scripts. All procedure library files should beginwith a standard procedure library header comment that includes the following fields ofinformation:

##LibraryHeader

A visual flag that indicates to automated documentation generatorsthat the following comment is a library header comment.

$Id: $ The first line of the header comment should be includedunmodified. This line will be replaced by CVS upon file checkout toindicate the version of the library being used.

1 Comments

ATS Automated Test Software Style Guide 30

Page 36: ATS Style Guide

# Copyright (c)2003 CiscoSystems, Inc.

The second line of the header comment should be includedunmodified. The standard Cisco copyright should be included in allsoftware developed at Cisco.

Name: The name of the library. This must match the filename containingthe library.

Purpose: A single sentence explaining the functionality provided by thelibrary.

Author: The person, identified by name and group, who developed thelibrary and is responsible for its maintenance.

Usage: Include the command (either source or package require) used toload the library (e.g., 'source $expect_library/sparse.exp').

Description: A detailed description of the functionality provided by the library.

Requirements: Identify any additional libraries required by this library and indicatewhether they need to be sourced prior to sourcing this one. Even ifautosourcing is handled through the package require command, itis still a good idea to list the required libraries in the headercomment. State "None" if there are no external libraryrequirements.

Variables: (Optional) Provide a list of the variables within the library's namespace that are used to maintain state, along with a briefdescription. Also document the fields defined within complex datastructures. See the previous section on commenting importantvariables and complex data structures in a script for additionaldetails and examples.

Notes: (Optional) Any usage notes of interest that you wish to highlight forthis script.

Known Bugs: (Optional) List any known bugs in this library along with anyworkarounds.

Todo: (Optional) List any enhancements that you have planned for thelibrary but haven't yet implemented. You or someone else may dofurther work on the library.

See Also: (Optional) List any other related libraries that anyone running thislibrary should also consider running.

Support Alias: (Optional) The username or mailing list used to contact theindividual or group providing support for this library. This isrequired for libraries submitted for inclusion in the cisco-sharemodule.

Keywords: Provide a list of keywords associated with this library that can beused to search for it in the future. The keywords associated with alibrary should be a list of single words that summarizes itsfunctionality.

Category: Provide a storage hierarchy for the library used in the automaticgeneration of the script development library command referencemanual.

# End ofHeader

Since library header comments can be lengthy, this commentprovides a visual flag that can be searched for in order to skip overthe header comment while in the editor.

The following example shows a procedure library header comment for a typical procedurelibrary:

1 Comments

ATS Automated Test Software Style Guide 31

Page 37: ATS Style Guide

##Library Header# $Id: $# Copyright (c) 2003 Cisco Systems, Inc.## Name:# dbg_util.exp## Purpose:# A script development library containing general purpose# script debugging utilities.## Author:# Brian Jackson, Test Technologies## Usage:# source $expect/library/dgb_util.exp## Description:# This library contains general purpose procedures that can# be used during the TCL software development process to# debug common scripting problems. The procedures contained# within this library include utilities to conditionally# display debugging messages, to test procedure and script# assertions, to simulate remote device interactions, to# inject faults into a script, and to implement a procedure# library self-test.## Use this library during the development of a script or# procedure library to verify the software in a simulation# environment and to perform an internal unit test on the# software components.## Requirements:# msg_lib.exp - A general purpose message display library.## Variables:# dbg_enable - A Boolean flag used to enable debug message# display.## Support Alias:# test-consulting## Keywords:# script, software, development, debug, test, simulate## Category:# internal/development/test

The standard procedure library header comment is included in the standard ATS procedurelibrary template.

5.7.3 Include the Standard Procedure Library Footer Comment

The procedure library footer comment is the same as that used in a script and should beincluded without modification. The following is the fixed format of this comment:

# $Log: $## ;;; Local Variables: ***# ;;; mode: tcl ***# ;;; End: ***

5.7.4 Include Standard Procedure Library Procedure Comments

1 Comments

ATS Automated Test Software Style Guide 32

Page 38: ATS Style Guide

Each procedure in a procedure library should be preceded by a standard procedure libraryprocedure comment. This comment explains the use of the procedure, lists its return values, andprovides examples that can be used to incorporate the procedure into a script. The fields ofinformation that should be included in a procedure library procedure comment are as follows:

##ProcedureHeader

A visual flag that indicates to automated documentation generatorsthat the following comment is a procedure comment. Note that youshould only place this visual flag in front of user-callableprocedures for which you want to produce documentation. Excludethis line from procedures that are used internally within the library.

Name: The name of the procedure (including a name space prefix if used).

Purpose: A single sentence summarizing the functionality provided by theprocedure.

Synopsis: An overview of the usage syntax for the procedure. Identifyvariable arguments by enclosing a symbolic name for the argumentin angle brackets. Identify optional arguments by enclosing themwithin question marks. List alternate argument syntaxes onseparate lines, repeating the procedure name followed by theargument list alternative. Use an ellipsis (...) to indicate that thepreceding argument can be repeated any number of times.

Arguments: List the arguments to the procedure, one per line, followed by anexplanation of each argument's purpose. If applicable, list validargument values or number ranges (e.g., [64 - 1500]) in thecomment. If arguments are valid only in conjunction with apreceding argument, indent the subordinate arguments.

Return Values: List the values returned by the procedure and indicate the purposeof each possible value.

Description: Provide a detailed description of the procedure, explaining fully thefunction that it performs and discussing potential applications.

Examples: Provide example uses of the procedure. Include comments in theexamples if they are not self-explanatory.

Sample Input: (Optional) Provide a sample of the input to the procedure providedby its argument values. This is particularly important in the case ofparsing procedures, where an understanding of the procedure isaided by a sample of the input being parsed.

SampleOutput:

(Optional) For procedures that log output to files, provide a sampleof the format of the output produced.

Notes: (Optional) Add any special notes related to the use of theprocedure, numbered for ease of reference.

See Also: (Optional) List any procedures or commands that are closelyassociated with the use of this procedure. For example, a 'read'procedure should reference corresponding 'open', 'write', and'close' procedures.

The following example shows a procedure library procedure comment for a typical libraryprocedure:

##Procedure Header# Name:# ats::debug## Purpose:# Conditionally output debug messages## Synopsis:# ats::debug enable

1 Comments

ATS Automated Test Software Style Guide 33

Page 39: ATS Style Guide

# ats::debug disable# ats::debug msg <format> ?<string> ...?## Arguments:# enable Enable display of debug messages# disable Disable display of debug messages# msg Conditionally display the following message# <format> Message to be displayed or a 'printf' style# message format# <string> Optional elements to be formatted into a# message format## Return Values:# "enable" | "disable" Returns the current debug status# when called## Description:# The "debug" command can be used to conditionally display# debug messages embedded in script or procedure libraries.# When debugging is enabled, messages are displayed to# standard output if running in an interactive interpreter# or the log file if running under Autotest or EASY control.# When debugging is disabled, debug messages are suppressed.## Use the "debug enable" command to enable display of debug# messages. Use the "debug disable" command to disable# message display. To display a message, use the "debug msg"# command followed by the message to be displayed. Note that# the message can be a 'printf' style format string followed# by one or more string elements to be formatted into the# message. Use this form of the command to include the# current value of variables in the message being displayed.## Use of this library typically involves loading the library# into an interactive interpreter, issuing the 'debug enable'# command, then sourcing the script or library to be debugged.# Optionally, you may place the 'debug enable' command in the# head of a script and execute that script in the Autotest# or EASY environment.## Examples:# ats::debug enable# ats::debug msg "This is a sample message"# set myvar 9# ats::debug msg "The value of my is %s" $myvar# ats::debug disable# ats::debug msg "You'll never see this message"## Sample Output:# DEBUG: This is a sample message# DEBUG: The value of myvar is 9## Notes:# 1) Debug message will not be displayed until the# "debug enable" command has been issued.# 2) Calls to "debug" cause a minor performance impact# to the code in which they're used. In the case of# performance critical software or software that is# executed repeatedly, you should limit your use of# this procedure or possibly remove calls to "debug"# from such software before productional release.

The standard procedure library procedure comment is included in the ATS procedure librarytemplate.

5.7.5 Include Procedure Library Internal Procedure Comments

1 Comments

ATS Automated Test Software Style Guide 34

Page 40: ATS Style Guide

Documentation for procedures used internally within a procedure library (procedures forprocedures) can sometimes be useful to people who are trying to understand the use of alibrary. Include the following simple internal procedure header comment for all such procedures,not only to document these procedures for individuals browsing the code but also to provide forinclusion in generated documentation:

##Internal Procedure Header# Return the first element of a list while setting the# list to contain the remaining elementsproc shift {listName} {

upvar $listName listset rc [lindex $list 0]set list [lrange $list 1 end]return $rc

}

In the example, internal procedure header comments contain a brief description of the operationperformed by the procedure preceded by the '##Internal Procedure Header' visual flag.

5.8 ITcl Class Library CommentsITcl classes and methods are defined in a file known as a class library. Although this documentprovides no information specific to ITcl coding style, this section outlines the standard headercomments that should be included in an ITcl class library.

Note: This standard was developed after the development of the ITcl based Metal product.Those extending and documenting the Metal libraries should feel free to continue to conform tothe Metal header commenting standard while adopting the remainder of the standards presentedin this document.

5.8.1 Include the Standard Class Library Header Comment

All class libraries should begin with a standard class library header comment that includes thefollowing fields of information:

##ClassHeader

A visual flag that indicates to automated documentation generatorsthat the following comment is a class library header comment.

$Id: $ The first line of the header comment should be includedunmodified. This line will be replaced by CVS upon script checkoutto indicate the version of the library being used.

# Copyright (c)2003 CiscoSystems, Inc.

The second line of the header comment should be includedunmodified. The standard Cisco copyright should be included in allsoftware developed at Cisco.

Name: The name of the class library. This must match the filenamecontaining the library.

Purpose: A single sentence explaining the functionality provided by the classlibrary.

Author: The person, identified by name and group, who developed theclass library and is responsible for its maintenance.

Inherits: The base classes from which the class inherits.

Usage: Include the command (either source or package require) used toload the class library (e.g., 'source$expect_library/sparse.itcl' ).

1 Comments

ATS Automated Test Software Style Guide 35

Page 41: ATS Style Guide

InstantiationExample:

Examples of how to instantiate an object of this class. Includeexamples of available configuration options.

Description: A detailed description of the functionality provided by the classlibrary.

Requirements: Identify any additional class libraries required by this library andindicate whether they need to be sourced prior to sourcing thisone. Even if autosourcing is handled through the package requirecommand, it is still a good idea to list the required libraries in theheader comment. State "None" if there are no external libraryrequirements.

PublicVariables:

(Optional) Provide a list of the public variables within the classlibrary's name space that are used to maintain state, along with abrief description. Also document the fields defined within complexdata structures. See the previous section on commenting importantvariables and complex data structures in a script for additionaldetails and examples.

Notes: (Optional) Any usage notes of interest that you wish to highlight forthis class library.

Known Bugs: (Optional) List any known bugs in this class library along with anyworkarounds.

Todo: (Optional) List any enhancements that you have planned for theclass library but haven't yet implemented. You or someone elsemay do further work on the library.

See Also: (Optional) List any other related libraries to which anyone usingthis library may want to refer.

Support Alias: (Optional) The username or mailing list used to contact theindividual or group providing support for this class library. This isrequired for libraries submitted for inclusion in the cisco-sharemodule.

Keywords: Provide a list of keywords associated with this class library that canbe used to search for it in the future. The keywords associated witha library should be a list of single words that summarizes itsfunctionality.

Category: Provide a storage hierarchy for the class library used in theautomatic generation of the script development library commandreference manual.

# End ofHeader

Since class library header comments can be lengthy, this commentprovides a visual flag that can be searched for in order to skip overthe header comment while in the editor.

5.8.2 Include Standard Class Library Method Comments

All methods defined in a class library should be preceded with a detailed comment defining thepurpose and use of the method. The following fields of information should be included:

##MethodHeader

A visual flag that indicates to automated documentation generatorsthat the following comment is a class library header comment.

Name: The name of class followed by two colons (::) and the name of themethod.

Class Name: The name of the class to which this method belongs.

1 Comments

ATS Automated Test Software Style Guide 36

Page 42: ATS Style Guide

Purpose: A single sentence explaining the functionality provided by themethod.

Synopsis: An overview of the usage syntax for the method.

Arguments: List the arguments to the method, one per line, followed by anexplanation of each argument's purpose. If applicable, list validargument values or number ranges (e.g., [64 - 1500]) in thecomment. If arguments are valid only in conjunction with apreceding argument, indent the subordinate arguments.

Return Values: List the values returned by the method and indicate the purpose ofeach possible value.

Description: Provide a detailed description of the method, explaining fully thefunction that it performs and discussing potential applications.

Examples: Provide example uses of the method. Include comments in theexamples if they are not self-explanatory.

Sample Input: (Optional) Provide a sample of the input to the method provided byits argument values.

SampleOutput:

(Optional) For methods that log output to files, provide a sample ofthe format of the output produced.

Notes: (Optional) Add any special notes related to the use of the method,numbered for ease of reference.

See Also: (Optional) List any procedures, methods, or commands that areclosely associated with the use of this method. For example, a'read' procedure should reference corresponding 'open', 'write', and'close' procedures.

5.9 Comment Nonintuitive Script LogicParticular emphasis should be placed on commenting nonintuitive script logic. Thisdocumentation includes a detailed explanation of the meaning of input being evaluated oractions being taken, and an account of the implementation of complex algorithms. In thesecases, you should provide more than a single line of comment to explain the operationsperformed by the software.

For example:

# Set the number of days in the current year# Leap year adds 1 day to February (the 29th) in years that are# divisible by 4 and either divisible by 400 or not by 100 (i.e.# throw out the years divisible by 100 except those that are also# divisible by 400) in order to synchronize the calendar with the# seasonsif {!($year % 4) && (($year % 400) || !($year % 100))} {

set days 366; # Leap year} else {

set days 365}

5.10 Use Comments to Document Output Being ParsedMost scripts include invocations of the TCL regexp command, or a utility procedure thatultimately calls regexp, in order to parse output from a device. When the output being parsed iscomplex or lengthy, include a sample of the output being parsed in a comment preceding theparsing logic. By doing so, you'll make it easier for individuals reading the code to understand

1 Comments

ATS Automated Test Software Style Guide 37

Page 43: ATS Style Guide

the goal of potentially complex regular expression patterns.

For example:

# Parse the packet counters from the IOS "show interface" command# output to extract input and output packet, byte, and error# counters# Sample "show interface" output:## Ethernet 0 is up, line protocol is up# Hardware is MCI Ethernet, address is 0000.0c00.750c (bia 0000# Internet address is 131.108.28.8, subnet mask is 255.255.255.0# MTU 1500 bytes, BW 10000 Kbit, DLY 100000 usec, rely 255/255,# Encapsulation ARPA, loopback not set, keepalive set (10 sec)# ARP type: ARPA, ARP Timeout 4:00:00# Last input 0:00:00, output 0:00:00, output hang never# Last clearing of "show interface" counters 0:00:00# Output queue 0/40, 0 drops; input queue 0/75, 0 drops# Five minute input rate 0 bits/sec, 0 packets/sec# Five minute output rate 2000 bits/sec, 4 packets/sec# 1127576 packets input, 447251251 bytes, 0 no buffer# Received 354125 broadcasts, 0 runts, 0 giants, 57186* thr# 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 ab# 5332142 packets output, 496316039 bytes, 0 underruns# 0 output errors, 432 collisions, 0 interface resets, 0 re#set output [$router exec "show interface $int1"]foreach s [split $output "\n"] {

regexp {([0-9]+) packets input, ([0-9]+) bytes,} $s - ipaksibytes

regexp {([0-9]+) input errors,} $s - ierrorsregexp {([0-9]+) packets output, ([0-9]+) bytes,} $s - opaks

obytesregexp {([0-9]+) output errors,} $s - ierrors

}if {![info exists ipaks] || ![info exists ierrors] ||

![info exists opaks] || ![info exists oerrors]} {log_diagnostic_msg \

"Unable to parse $router 'show interface $int1'output\n$output"

update_test_status $FAIL}

5.11 Comment Router ConfigurationsCisco router test scripts usually include a great deal of router configuration data that needs to beapplied to the routers in a testbed to set up the test environment. These configurationstatements are typically standard router commands (e.g., "no shutdown") that are simply part ofthe administrative task of configuring a router. But some configurations being applied arecomplex or are integral to the test being performed. In these cases, you should use the routerconfiguration comment character (!) to include comments and white space in your routerconfiguration to improve its readability and understandability. For example:

$uut_router config "! Apply the requested encapsulation and switching mode to the! generator side interfaceinterface $uut_gen_int[get_modes off ip_static $Version $gen_mode][get_encaps off ip_static $Version $gen_encap "UutGen"]no ip addressshutdown!! Apply the requested encapsulation and switching mode to the! reflector side interfaceinterface $uut_ref_int

1 Comments

ATS Automated Test Software Style Guide 38

Page 44: ATS Style Guide

[get_encaps off ip_static $Version $RefEncap "UutRef"]no ip addressshutdown!no ip routing

"

5.12 Generating Documentation from CommentsThe Test Technologies organization is currently working on a set of tools that can be used togenerate procedure library and script documentation in HTML, Unix man page, and text formatfrom comments contained in source code. The details of these tools are not available as of thewriting of this document, but if you follow the header-commenting conventions outlined in thisdocument, you can be assured that documentation for your software can and will be included inthe generated output.

5.13 Include Cisco copyright notice in all filesAll Cisco code should carry the Cisco copyright notice. This notice is normally included in thestandard header comments for the file, although currently there is no standard header commentformat for command-line tools. These should, however, still carry the copyright notice:

# Copyright (c) 2006 Cisco Systems, Inc.

5.14 Include RCS $Id$ tag in all filesAs with the Cisco copyright notice, the RCS $Id$ tag is normally present in the standard headercomment for the file. This tag is substituted by CVS (through RCS) with information about the filethat is useful for distinguishing it from other versions of the same file: including numeric version,date and user name associated with the commit. In lieu of other versioning information, this isimportant for keeping track of updates and patches to deployed files.

1 Comments

ATS Automated Test Software Style Guide 39

Page 45: ATS Style Guide

1 Naming

ATS Automated Test Software Style Guide 40

Page 46: ATS Style Guide

6 Naming

Every element incorporates one piece of documentation that will follow it everywhere—that is, itsname. Just as comments can aid in understanding software, applying meaningful names tovariables and procedures can enhance software by quickly identifying the purpose and use of anelement. This section discusses standards for naming variables and procedures used in ATStest scripts and procedure libraries.

6.1 Assign Meaningful NamesThe first and most important rule regarding the naming of variables and procedures is to apply ameaningful name to each of these elements. For example, instead of giving a counter variable aname such as i, name the variable something like input_count. The following are examples ofvariables and procedures that have meaningful names:

pak_count_out A variable used to count outgoing packets.

pak_count_in A similar variable used to count incoming packets. Notice that the"in" versus "out" distinction is placed at the end of the name so thatboth variables can be clearly identified as packet counters and theslight difference is subordinated to the end of the name.

pak_count_get() A procedure used to obtain the packet counter values.

Variables should always have meaningful names except in cases where short-lived variables arebeing used within a very limited scope of your software. The most frequent example of thisexception is the naming of loop variables. For example:

set string "This is a string"foreach s $string {

puts $s}

In this example, the variable s need not be given a significant name because its purpose andscope of use are limited and obvious. Here the use of a very brief name is preferable because itsaves typing time and space.

6.2 Use Standard Characters in NamesTCL allows you to use a wide range of characters in variable and procedure names. Thesecharacters include uppercase and lowercase alphabetic characters, numerals, and virtually anypunctuation character that won't be misinterpreted as a language element. Noentheless, youshould restrict the characters used in naming elements to lowercase alphabetics andunderscores (_). Use of punctuation characters other than underscore in a name, can createvisual confusion in your program by making names look like regular expression patterns or othersoftware elements.

A name should always begin with a lowercase alphabetic character unless you are trying to hidethe name, in which case it should begin with an underscore (see ). Uppercase alphabeticcharacters should be used only in naming constants (see ) and camelback naming (see below).Underscore or upper case characters should be used to delimit multiple words used to composea variable name. Variable names should always end with a lowercase alphabetic character.

The following are some naming examples:

router A variable used to store a router name.

router_type A variable used to store the router type.

1 Naming

ATS Automated Test Software Style Guide 41

Page 47: ATS Style Guide

trim_flag A Boolean variable used to enable trimming. Embeddedunderscore naming.

trimFlag The same definition using camelback naming.

_csccon_connect_timeout A hidden global variable used by the CSCCON router controllibrary to store a timeout value for router connections.

TRUE A constant variable storing the value of true (1).

var9__a__mEss? A total mess.

6.3 Abbreviate NamesIn order to avoid lengthy command lines, reduce overall program size, and save your fingersfrom cramping up, you should abbreviate the words used to compose variable and procedurenames. Words are commonly abbreviated by removing vowels (e.g., 'count' becomes 'cnt' and'flag' becomes 'flg'), unless the vowels are useful in distinguishing the abbreviated word fromother words. Abbreviations can also be produced by using the significant portion of the word(e.g., 'number' becomes 'num') or the phonetic value (e.g., 'packet' becomes 'pak'). Combinethese abbreviations with underscore separation and you've created a terse, but meaningful,name.

The following are examples of well-formed abbreviated names:

pak_cnt_in Input packet counter.

trim_flg A Boolean variable used to enable trimming.

usr_num A user's relative number.

Note: The first two examples above should be used in preference to the unabbreviatedexamples shown in previous sections.

6.4 Techniques for Constructing NamesThis document stresses the value of following a single standard naming convention. Thatstandard should be one of two accepted conventions. This section discusses the relative meritsof those conventions, leaving it to you to select the one the better suits your style. Whichevermethod you adopt, use it consistently across all the software that you develop.

6.4.1 Underscore-Delimited Naming

Underscore-delimited naming uses underscores to separate the individual words orabbreviations that make up a name. The convention is visually pleasing and helps to highlightname components, but the inclusion of underscores does add to the name length. The primarybenefit of this convention is that it is already extensively used throughout the ATS, so if youadopt it you're more likely to achieve visual consistency between your software and the softwaresurrounding it.

6.4.2 Camelback Naming

An alternate naming convention, used extensively in object oriented programming, is camelbacknaming. This method involves using uppercase letters to separate the individual words andabbreviations that compose a name. Instead of using an underscore to separate two nameelements, simply change the case of the first letter of the second element to uppercase and jointhem. For example:

1 Naming

ATS Automated Test Software Style Guide 42

Page 48: ATS Style Guide

pakCntIn Input packet counter.

trimFlg A Boolean variable used to enable trimming.

usrNum A user's relative number.

router The name of a router.

pakCountGet() A procedure used to obtain the packet counter values.

An obvious benefit to this naming convention is that it can significantly reduce the length of aname while retaining the visual separation of its components. Additionally, those who areexperienced object oriented programmers will find this naming convention more familiar andvisually more appealing.

The downside to this naming convention is that it is not consistent with the naming convention inprimary use throughout the ATS; namely, underscore-delimited naming.

Note: Despite a personal preference for camelback naming, I use underscore-delimited namingwhen writing ATS software for the sake of visual consistency with the entire system of software.This naming convention may be more useful in software development performed outside theATS.

6.5 Name PrefixesIn order to differentiate a variable or procedure name from names used by software other thanyour own, you may have to apply a word prefix to the name to associate it with your software.This section discusses when name prefixing should be used and how to do it.

6.5.1 Name Space Collision

When naming variables for local use within your software, you can be confident that the namesyou assign are unique. However, a common practice in defining procedures is to store persistentdata in global variables. All global variables are stored in a single name space. Variable namecollision can occur with other software using the global name space. Furthermore, all proceduresare defined in the global name space, even if they're to be used only locally within your script.Let's say you're using the CSCCON router control library. If you define a procedure within yourscript named 'console', you will have just destroyed the CSCCON console procedure.

The general problem of inadvertently replacing variables and procedures in the global namespace is known as name space collision. This section addresses methods for avoiding thisphenomenon.

6.5.2 Use Simple Name Prefixing in Test Scripts

The simplest way to avoid name space collision is to apply a name prefix to all global variablesand procedures that are defined within your software. A name prefix is simply a short stringprepended to a name using an underscore. The prefix, though short, should also attempt touniquely identify the owner of the element.

The following are examples of some simple name prefixes.

ipmtst_ Used by the IP Multicast test script.

atutl_ Used for AppleTalk utility procedures.

Using of simple name prefixing is acceptable, but a preferred method for making procedurenames unique is presented in the next section.

1 Naming

ATS Automated Test Software Style Guide 43

Page 49: ATS Style Guide

6.5.3 Use Name Spaces in Procedure Libraries

Name spaces provide a simple mechanism for avoiding name space collision and thecumbersome and needlessly long names that can be produced by simple name prefixing. Whendeveloping a procedure library for reuse, you should always use name spaces to define yourprocedures and global data in a name space other than the global name space. To define aname space, use the namespace eval command as seen in the following simple example:

namespace eval dbg {variable debug_enable; # Flag used to enable/disable debug

output}

proc dbg::debug {cmd {msg {}}} {...

}

In this example, the 'dbg' name space is created. Within that name space, the variablecommand is used to define a variable that is global to that name space. A procedure calleddebug is then defined within that name space by prefacing the name of the procedure with thename of the name space, bracketed in double colons. This procedure can be called by otherprocedures within the name space using the command debug or by users outside the namespace by specifying its fully qualified name dbg::debug.

For more information on name spaces, refer to ATS Procedure Library Development Guide.

6.5.4 Begin Names with Underscores to Hide Them

One danger of defining persistent variables in the global name space is the potential for users toredefine the contents of those variables. One way of hiding your global variables from tamperingis to place a visual flag in the the variable name.

A common standard in global variable naming is to begin the name of global variables with anunderscore (_). This provides a visual flag to the user to indicate that the contents of the variableshould neither be read nor modified.

6.6 Name Constant Variables Using Uppercase CharactersAn exception to the rule regarding the use of uppercase characters in variable names involvesconstant variables. Constant variables are variables that store a constant value; in other words,they are variables that should not be modified by the user. Constant variables should be used tostore looping values and addresses rather than hard-coding such constant data in your script.

Constant variable names should be composed entirely of uppercase characters and, optionally,underscores. The use of uppercase characters signals to the user that the contents of thevariable are constant and the variable therefore should not be modified.

The following are examples of constant variable names:

FALSE Stores the value 0 (false).

MAX_RETRIES Stores the value 10 (a maximum loop counter).

IP_ADDR Stores the value 10.227.20.1.

6.7 Name Files Using Extensions

1 Naming

ATS Automated Test Software Style Guide 44

Page 50: ATS Style Guide

All of the naming conventions outlined in this section for variables and procedures also apply tothe naming of files that are added to the ATS system, including procedure libraries, suites, andjob and queue files.

An additional convention that applies to the naming of files involves the use of filename suffixes.When naming a file, you should append a suffix that identifies the use and contents of the file.This convention does not apply to the naming of scripts, which by precedence do not possessfilename suffixes. The following are some of the standard filename suffixes used in the ATSsystem:

.exp Use this filename suffix on procedure libraries.

.suite Use this filename suffix on Autotest suite files.

.queue Use this filename suffix on Autotest queue files.

.job Use this filename suffix on EASY job files.

.dat Use this filename suffix on data files.

.config | .conf Use this filename suffix on software configuration files.

.txt | .doc Use this filename suffix on documentation files.

Note: It is better to distinguish similarly named files by significant differences in name ratherthan by simply appending a number to identical names. Whatever is the cause for separating thefile contents can be used to differentiate the filenames.

1 Naming

ATS Automated Test Software Style Guide 45

Page 51: ATS Style Guide

1 Constants

ATS Automated Test Software Style Guide 46

Page 52: ATS Style Guide

7 Constants

7.1 Define and Use Constant VariablesScripts typically include a large amount of constant data. Constant data includes maximum loopcounters, comparison values, device configuration strings, and procedure call data. When youare using a constant data value that is likely to be changed, you should define a constantvariable to store and refer to the constant data value rather than hard-coding the value in yourscript.

The reason for using constant variables is twofold: economy and meaningfulness. First, achange to a single constant variable definition affects all of its use cases throughout your script.Second, a well-named constant variable can provide more information about the meaning of thevalue than does the value itself.

For a list of potential constant variable names, refer to the section . The following exampleshows the definition and use of a constant variable:

# Define constantsset MAX_RETRIES 10

...

# Attempt to create a test device connectionfor {set i 0} {$i < $MAX_RETRIES} {incr i} {

...}

Note: There's a fine line between proper use of constants and overuse of constants. Everyconstant value in your script need not be defined in a constant variable. Typically the signs thatpoint to the need for a constant variable definition are reuse of the value, the need to documentthe purpose of the value, and the need to change the value in order to fix bugs in the script.

1 Constants

ATS Automated Test Software Style Guide 47

Page 53: ATS Style Guide

1 Software Structure

ATS Automated Test Software Style Guide 48

Page 54: ATS Style Guide

8 Software Structure

Each line of a piece of software should be formatted to achieve visual consistency. In addition,the overall structure of the software and the order in which sections appear should be madeconsistent to enhance its readability and maintainability. This section discusses the standardstructure that should be used to implement test scripts and reusable procedure libraries.

8.1 Script StructureTo ensure visual consistency with other test scripts and to make portions of a script easy to find,each test script should be developed in sections that adhere to a prescribed order, as follows:

InterpreterInvocation

The first line of a test script should invoke the Expect interpreter.Although test scripts aren't run from the command line andtherefore don't need to invoke the interpreter, the inclusion of thisline will cause the Unix file type to identify the script as an Expectexecutable shell script.

HeaderComment

Include the standard ATS script header comment as explained inthe section .

LibrarySourcing

Source any procedure libraries (e.g., csccon.exp) required by thetest script to perform the test.

ConstantDefinition

Define and set constant variables used in the script.

ArgumentParsing

Parse the script argument string, storing its contents in individualvariables.

ArgumentValidation

Verify any argument dependencies of the script.

PasswordSetting

Set any passwords required to connect to equipment in thetestbed.

LocalProcedureDefinition

Define any procedures that will be used locally within the testscript.

TestConfiguration

Configure the testbed equipment and the environment to preparefor test execution and analysis.

TestExecution andAnalysis

Actually perform the test by injecting the stimulus into the testbedand verifying the response. Report the test result in this section.

TestUnconfiguration

Remove all configuration that was applied to the testbed in order toperform the test. Scripts should leave the testbed in the same statethat it was in before the script began execution.

FooterComment

Include the ATS standard test script footer comment, as explainedin the section .

For additional information on the development of test scripts, refer to ATS Test ScriptDevelopment Guide.

8.2 Procedure Library StructureTo ensure visual consistency with other procedure libraries and to make portions of a library

1 Software Structure

ATS Automated Test Software Style Guide 49

Page 55: ATS Style Guide

easy to find, each library should be developed in sections that adhere to a prescribed order, asfollows:

InterpreterInvocation

A procedure library should begin with a line that identifies the fileas an Expect executable shell script.

HeaderComment

Include the standard ATS procedure library header comment asexplained in .

PackageDefinition

Use the package provide command to define the library as apackage. Not all libraries are used as packages, but the inclusionof this line will ensure that the library is ready to be used as one ifthe need arises.

RequireLibraries

Include package require statements for any other procedurelibraries upon which this library depends.

Define andInitialize theNamespace

As section explains, you should use the namespace command todefine a name space to contain your library procedures. Within thename space definition, use variable to define global variables tobe used locally within the procedure library. The initialization logiccan also make calls to the namespace export command to exportprocedure and variables for namespace import into the globalname space.

Define UserCallableProcedures

Define the procedures that are accessible to the user of the library.

DefineInternal,SupportProcedures

Define the procedures that are accessible only to the procedureswithin the library.

FooterComment

Include the ATS standard procedure library footer comment, asexplained in .

For additional information on the development of procedure library, refer to ATS ProcedureLibrary Development Guide.

1 Software Structure

ATS Automated Test Software Style Guide 50

Page 56: ATS Style Guide

9 Emacs TCL Mode and Fontification

If you're using the Emacs editor to develop TCL software (a practice that I highly recommend),you can use the context sensitive features of the editor to help implement this coding standard.For example, when you enable tcl-mode during the edit session, the tab character willautomatically indent nested code blocks. The cursor will jump back and forth between openingand closing braces for strings and blocks.

You can enable font-lock to highlight various sections of your program using different colors:comments will be displayed in red, commands in turquoise, and strings in orange. This editingmode can help you to quickly identify unterminated strings and other program elements.

To enable these features, add the following command blocks to your "~/.emacs" configurationfile:

;;; Automatically enter an editing mode based on the file suffix(setq auto-mode-alist (cons '("\\.tcl$" . tcl-mode)auto-mode-alist))(setq auto-mode-alist (cons '("\\.exp$" . tcl-mode)auto-mode-alist))

...

;;; Enable font locking for various modes(cond (window-system(add-hook 'tcl-mode-hook 'turn-on-font-lock)(setq font-lock-maximum-decoration t)(global-font-lock-mode t)

))

1 Emacs TCL Mode and Fontification

ATS Automated Test Software Style Guide 51

Page 57: ATS Style Guide

1 Where to Go from Here

ATS Automated Test Software Style Guide 52

Page 58: ATS Style Guide

10 Where to Go from Here

If you've just finished reading through the Test Technologies style standards for development ofATS software, you should plan to review this document after completion of your next ATSsoftware development project in order to verify that the software complies with this standard.

But then what?

Before reading this guide, you probably browsed the TCL Scripting Language Primer. If youhaven't already done so, take a look at that document to obtain a solid understanding of TCL sothat you can fully comprehend and appreciate the conventions and examples presented in thisdocument.

If you will be developing automated test scripts for use with the ATS, you should now review theATS Test Script Development Guide for detailed instructions on use of the ATS scriptdevelopment libraries.

If you will be developing reusable procedure libraries for use with the ATS, you should reviewthe ATS Procedure Library Development Guide for information on how to make softwarefindable and reusable.

As you continue to develop ATS scripts, refer back to this guide to increase your familiarity withthe style conventions.

1 Where to Go from Here

ATS Automated Test Software Style Guide 53

Page 59: ATS Style Guide

Appendix A: Style Summary

ATS Automated Test Software Style Guide 54

Page 60: ATS Style Guide

Appendix A: Style Summary

2 Quoting

2.3 Default to the Use ofDouble Quotes to QuoteStrings

Unless you're suppressingsubstitution, use doublequotes in preference to curlybraces when quoting stringsto differentiate string datafrom other quoted data (e.g.,code blocks andexpressions).

set variable "This is the contents of the variable"

2.4 Quote Single-ElementStrings Using DoubleQuotes

Quote single-element stringsusing double quotes, exceptstrings composed of a singlevariable or subcommandstrings passed to aprocedure.

pak_process parse $pak "output"

2.5.1 Quote ExpressionsUsing Curly Braces toMaintain Consistency

Always quote expressionsusing curly braces, even ifnot required by TCL, topromote coding styleconsistency.

if {$debug_flag} {if {$debug_option == "verbose"} {

puts "Verbose debugging is requested"} else {

puts "Non-verbose debugging is requested"}

}

2.5.2 Quote ExpressionsUsing Curly Braces toImprove Performance

Quote expressions usingcurly braces to improveperformance by preventingmultiple substitution.

if {[string match "-verbose" $args]} {puts "The verbose argument was received"

}

2.5.3 Quote LoopingExpressions Using CurlyBraces

Quote looping expressions

set flag 1set count 1

while {$flag} {incr countif {$count > 100} {

set flag 0}

Appendix A: Style Summary

ATS Automated Test Software Style Guide 55

Page 61: ATS Style Guide

using curly braces toprevent infinite loops.

}

2.6 Quote Code BlocksUsing Curly Braces

Always quote code blocksusing curly braces instead ofdouble quotes to deferevaluation and visuallydelineate your code blocks,even if the code block bodyof a conditional or loopingcommand doesn't requirequoting.

if {[string match "8*" [info tclversion]]} {puts "This is TCL version 8"

}

2.7 Quote ProcedureBodies and ScriptSections Using CurlyBraces

Always quote procedurebodies and script sectionsusing curly braces instead ofdouble quotes to deferevaluation and visuallydelineate these elements.

proc display {msg} {puts $msg

}test_config {

$router config "interface Ethernet1no shutdown

"}

2.8 QuoteNon-Space-DelimitedVariable Names UsingCurly Braces

Always place curly bracesaround variable names thatare not delimited by spaceor punctuation fromsurrounding characters in astring.

set var1 "my"set var2 "data"puts "${var1}data"; # Outputs "mydata"puts "${var1}${var2}"; # Outputs "mydata"puts "${var1}.${var2}"; # Outputs "my.data"

2.9 Quote ProcedureArgument Lists UsingCurly Braces

Always place curly bracesaround procedure argumentlists even if the procedureaccepts only one argument.

proc msg {string} {puts $string

}

3 Commands and Code Blocks

3.1.1 Code One Commandper Line

set FAIL 0; # Use this constant to return failure from a scriptset PASS 1; # Use this constant to return success from a script

for {set s 1; set p 0} {$s < $MAX_STRING} {incr s; incr p} {

Appendix A: Style Summary

ATS Automated Test Software Style Guide 56

Page 62: ATS Style Guide

Always write a singlecommand per line, reservingsemicolons for placingcomments after variabledefinitions and lines ofinterest and for separatingcommands in forexpressions.

if {$s == 1} {...

}; # End of if {$s == 1}}; # End of for loop

3.1.2.1 Split CommandLines That Exceed 80Characters

Use the backslash characterto escape newlines in orderto continue a lengthycommand (a line thatexceeds 80 characters) onone or more new lines.

if {[string index [lindex $arg 0] 0] == "-" && \[lindex $arg 1] != "false"} {...

}

3.1.2.2 Use join to SplitStrings That Exceed 80Characters

Use the TCL join and listcommands to rejoin lengthystrings that have been splitonto multiple lines.

log_message [join [list "Interface $interface packet counters,"\

"Input counter: $input, Output counter: $output"]]

3.1.2.3 Split Commands atLogical Breaks

Instead of splitting lengthycommands onto multiplelines arbitrarily, split thecommands at naturalseparation points in thecommand syntax.

for {set iptr 0; set optr 0} {iptr < $END_OF STRING} \{incr iptr} {...

}

3.2.2 Align Opening andClosing Code Block CurlyBrace

Open code blocks using acurly brace at the end of theline containing the commandto which they are passed,and close them with a curlybrace aligned with the startof the command line onwhich they're opened.

if {[string match "8*" [info tclversion]]} {if {[string match "*2" [info tclversion]]} {

puts "This is TCL version 8.2"}

}

3.2.4 Avoid ExcessivelyLong or Deeply NestedCode Blocks

if {$access_list_flag} {access_list_apply $interface_listforeach interface $interface_list {

set result [access_list_evaluate $interface]if {$result} {

puts "Access list looks good"

Appendix A: Style Summary

ATS Automated Test Software Style Guide 57

Page 63: ATS Style Guide

Avoid the use of excessivelylong or deeply nested codeblocks by breaking yourcode up into multipleprocedures.

} else {puts "Access list looks bad"

}}

}

3.2.5 Treat Script Sectionsand Device ConfigurationsAs Code Blocks

Indent the contents of scriptsections 4 spaces just asyou would a code block.

package require Cscconpackage require Test

set router "my_router"

test_config {$router config {

interface ethernet1no shutdown

}}

test_analyze {set result [$router exec "show interface ethernet1"]if {[regexp "line protocol up" $result]} {

puts "Everything looks good on ethernet1"}

}

3.2.6 Treat ProcedureBodies As Code Blocks

Indent the body ofprocedure definitions fourspaces just as you would acode block.

proc display {msg} {puts $msg

}

3.3.1 Use Spaces toDelimit Operators andValues in Expressions

Use spaces to delimitoperators, variables, andnumbers to enhance thereadability of an expression.

if {($pak_siz >= 64 && $pak_siz <= 1500) || !$pak_err_flg} {puts "Packet contains an error"

}

3.3.2 Exclude the EqualityOperator from BooleanExpressions

Do not include the equalityoperator (==) in Booleanexpressions.

set flag 1if {$flag} {

puts "Flag is true"}

3.3.3 Explicitly DefineExpression OperationPrecedence

Use parentheses () toexplicitly define the order inwhich arithmetic andBoolean operations will beperformed in a complexexpressions.

if {($var > 10) && ($var < 100)} {puts "Value is within range"

}set var [expr "(($foo * 100) - ($bar / 7)) + 3"]

3.4.3 Do Not Include then if {1} {

Appendix A: Style Summary

ATS Automated Test Software Style Guide 58

Page 64: ATS Style Guide

in if Statements

Exclude the then from ifstatements.

puts "False"}

3.4.5 Use "--" string tomark end of options

Include the "--" argumentafter options to preventbugs.

regexp -all -nocase -- $pattern -> result

3.4.6 Handling uplevel andupvar statements

Include levels in uplevel andupvar calls to prevent bugs.

uplevel 1 $cmd $args

4 White Space and Indentation

4.1.1 Use One Line ofWhite Space to VisuallySegment Software Logic

Visually separate yoursoftware into groups ofprogram logic using singleblank lines to enhancesoftware readability andmaintainability.

set output [$router exec "show interface $int1"]foreach s [split $output "\n"] {

regexp {([0-9]+) packets input} $output - $ipaks}if {![info exists ipaks]} {

log_diagnostic_msg "Unable to parse router show interfaceoutput:\n$output"

update_test_status $FAILreturn

}

if {$output > $threshold} {log_diagnostic_msg "Input packet threshold ($theshold)

exceed"update_test_status $PASS

} else {log_diagnostic_msg "Input packet threshold ($theshold) not

exceed"update_test_status $FAIL

}

4.2 Indent Nested CodeBlocks Four Spaces

Indent nested code blocksfour spaces per code blockto visually identify thenesting level of each line ofcode in the block.

foreach s {"one" "two" "three"} {set len [string length $s]if {$s == "one"} {

puts "The first string is length of $len"} else {

puts "This isn't the first string"puts "Its length is $len"

}}

5 Comments

5.1 Format CommentsLike Bullet Items

Begin comments with apound sign, followed by onespace, then the commentwith the first letter

# Update the program counter...

# Extract the input packet counter from the router show# interface output...

Appendix A: Style Summary

ATS Automated Test Software Style Guide 59

Page 65: ATS Style Guide

capitalized, and omit theterminating period.

# Recalibrate the traffic rate# Traffic rate recalibration must be performed periodically# to ensure valid test results...

5.2 Comment All LogicalBlocks of Code

Comment all blocks of codethat have been separatedusing white space.

# Display a sorted list of the TCL commands# Insert blank lines between commands beginning with# different characters

# Iterate across a sorted list of all TCL commandsset command_list [lsort [info commands]]foreach command {$command_list} {

# Print a blank line between commands starting with# different charactersset first_letter [string index $command 0]if {[info exists prev_letter]} {

if {![string match $first_letter $prev_letter]} {puts ""set prev_letter $first_letter

}}

# Display the current commandputs $command

}

5.3 Indent Comments toAlign Them with the CodeThat Follows

Align comments to the samenest level as the code theydescribe.

# Iterate across a sorted list of all TCL commandsset command_list [lsort [info commands]]foreach command {$command_list} {

# Print a blank line between commands starting with# different charactersset first_letter [string index $command 0]if {[info exists prev_letter]} {

if {![string match $first_letter $prev_letter]} {puts ""set prev_letter $first_letter

}}

# Display the current commandputs $command

}

5.4 Add Comments at Endof Nested Code Blocks(Optional)

Place comments after theending curly braces ofdeeply nested or lengthycode blocks to identify theblock they terminate; orbetter yet, don't write deeplynested or lengthy codeblocks.

if {$route_flag} {...foreach route {$route_list} {

...if {$security_flag} {

...}; # End of if {$security_flag}

}; # End of foreach route loop}; # End of if {$route_flag}

5.5.1 Document Constantsand Important Variables

Add comments to documentthe purpose and use of allconstants and importantvariables used in yoursoftware.

set MAX_RETRY_COUNT 10; # Maximum number of times to try anoperationset MIN_PAK_SIZE 64; # Minimum size of a valid IP packetset MAX_PAK_SIZE 1500; # Maximum size of a valid IP packet

5.5.2 Document InternalData Structures

# Important Data Structures:## Global Array: tcl_command_list# Used to store information about TCL commands

Appendix A: Style Summary

ATS Automated Test Software Style Guide 60

Page 66: ATS Style Guide

Add comments to documentthe contents of complexinternal data structures.

# Indexes:# command,[1-n] Contains the command name# type,[1-n] Contains 'p' for proc, 'c' for command# used,[1-n] Exists if the command has been executed

5.6.1 Include the StandardScript Header Comment

Begin test scripts with thestandard ATS script headercomment.

##Script Header$Id: $# Copyright (C) 2003 by Cisco Systems, Inc.Name:Purpose:Author:References:Description:Topology:Synopsis:Arguments:Sample Usage:Pass/Fail Criteria:Sample Output:Test Steps:Support Alias:Notes:Known Bugs:Todo:See Also:# End of Header

5.6.2 Include the StandardScript Footer Comment

End test scripts with theATS standard script footercomment.

# $Log: $## ;;; Local Variables: ***# ;;; mode: tcl ***# ;;; End: ***

5.7.1 Include ScriptProcedure Comments

All procedures definedwithin a script should bepreceded by a simplecomment explaining thepurpose and use of theprocedure.

# Repeatedly poll the router route table until the desiredroute# appears, returning True if the route appears and Falseotherwiseproc route_up {router prot addr} {

for {set i 0} {$i < $MAX_ROUTE_RETRIES} {incr $i} {if {[string match $route [$router exec "show $prot

route"]]} {return $TRUE

}sleep $ROUTE_SLEEP

}return $FALSE

}

5.7.2 Include the StandardProcedure Library HeaderComment

All procedure librariesshould begin with the ATSstandard procedure libraryheader comment.

##Library Header$Id: $# Copyright (C) 2003 by Cisco Systems, Inc.Name:Purpose:Author:Usage:Description:Requirements:Variables:Notes:Known Bugs:

Appendix A: Style Summary

ATS Automated Test Software Style Guide 61

Page 67: ATS Style Guide

Todo:See Also:Support Alias:Keywords:Category:# End of Header

5.7.3 Include the StandardProcedure Library FooterComment

All procedure librariesshould end with the ATSstandard procedure libraryfooter comment.

# $Log: $## ;;; Local Variables: ***# ;;; mode: tcl ***# ;;; End: ***

5.7.4 Include StandardProcedure LibraryProcedure Comments

All procedures defined in aprocedure library should bepreceded with a detailedprocedure comment definingthe purpose and use of theprocedure.

##Procedure HeaderName:Purpose:Synopsis:Arguments:Return Values:Description:Examples:Sample Input:Sample Output:Notes:See Also:

5.7.5 Include ProcedureLibrary Internal ProcedureComments

Provide documentation forinternal procedures as anaid to someone trying tounderstand the use of alibrary.

##Internal Procedure Header# Return the first element of a list while setting the# list to contain the remaining elementsproc shift {listName} {

upvar $listName listset rc [lindex $list 0]set list [lrange $list 1 end]return $rc

}

5.8.1 Include the StandardClass Library HeaderComment

All class libraries shouldbegin with the ATS standardclass library headercomment.

##Class Header$Id: $# Copyright (C) 2003 by Cisco Systems, Inc.Name:Purpose:Author:Inherits:Usage:Instantiation Example:Description:Requirements:Public Variables:Notes:Known Bugs:Todo:See Also:Support Alias:

Appendix A: Style Summary

ATS Automated Test Software Style Guide 62

Page 68: ATS Style Guide

Keywords:Category:# End of Header

5.8.2 Include StandardClass Library MethodComments

All methods defined in aclass library should bepreceded with a detailedcomment defining thepurpose and use of themethod.

##Method HeaderName:Class Name:Purpose:Synopsis:Arguments:Return Values:Description:Examples:Sample Input:Sample Output:Notes:See Also:

5.9 Comment NonintuitiveScript Logic

Use detailed comments todocument nonintuitive logicin your software.

# Set the number of days in the current year# Leap year adds 1 day to February (the 29th) in years that are# divisible by 4 and either divisible by 400 or not by 100(i.e.# throw out the years divisible by 100 except those that arealso# divisible by 400) in order to synchronize the calendar withthe# seasonsif {!($year % 4) && (($year % 400) || !($year % 100))} {

set days 366; # Leap year} else {

set days 365}

5.10 Use Comments toDocument Output BeingParsed

Before a regexp command,include a comment thatcontains output beingparsed so that readers canunderstand the data that thepattern must match.

# Parse the packet counters from the IOS "show interface"command# output to extract input and output packet, byte, and error# counters# Sample "show interface" output:## Ethernet 0 is up, line protocol is up# Hardware is MCI Ethernet, address is 0000.0c00.750c (bia0000# Internet address is 131.108.28.8, subnet mask is255.255.255.0# MTU 1500 bytes, BW 10000 Kbit, DLY 100000 usec, rely255/255,# Encapsulation ARPA, loopback not set, keepalive set (10sec)# ARP type: ARPA, ARP Timeout 4:00:00# Last input 0:00:00, output 0:00:00, output hang never# Last clearing of "show interface" counters 0:00:00# Output queue 0/40, 0 drops; input queue 0/75, 0 drops# Five minute input rate 0 bits/sec, 0 packets/sec# Five minute output rate 2000 bits/sec, 4 packets/sec# 1127576 packets input, 447251251 bytes, 0 no buffer# Received 354125 broadcasts, 0 runts, 0 giants, 57186*thr# 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0ab# 5332142 packets output, 496316039 bytes, 0 underruns# 0 output errors, 432 collisions, 0 interface resets, 0re#set output [$router exec "show interface $int1"]foreach s [split $output "\n"] {

regexp {([0-9]+) packets input, ([0-9]+) bytes,} $s -ipaks ibytes

regexp {([0-9]+) input errors,} $s -ierrors

regexp {([0-9]+) packets output, ([0-9]+) bytes,} $s -opaks obytes

regexp {([0-9]+) output errors,} $s -ierrors}if {![info exists ipaks] || ![info exists ierrors] ||

![info exists opaks] || ![info exists oerrors]} {

Appendix A: Style Summary

ATS Automated Test Software Style Guide 63

Page 69: ATS Style Guide

log_diagnostic_msg \"Unable to parse $router 'show interface $int1'

output\n$output"update_test_status $FAIL

}

5.11 Comment RouterConfigurations

Use the router configurationcomment character (!) tocomment complex andimportant routerconfiguration strings.

$uut_router config "! Apply the requested encapsulation and switching mode to

the! generator side interfaceinterface $uut_gen_int[get_modes off ip_static $Version $gen_mode][get_encaps off ip_static $Version $gen_encap "UutGen"]no ip addressshutdown!! Apply the requested encapsulation and switching mode to

the! reflector side interfaceinterface $uut_ref_int[get_encaps off ip_static $Version $RefEncap "UutRef"]no ip addressshutdown!no ip routing

"

5.13 Include Ciscocopyright notice in all files

Include Cisco copyrightnotice in all files

# Copyright (c) 2006 Cisco Systems, Inc.

6 Naming

6.1 Assign MeaningfulNames

Use meaningful names forvariables and procedures.Instead of 'i' use'input_count'.

pak_count_outpak_count_inpak_count_get()

6.2 Use StandardCharacters in Names

Use only lowercasealphabetic characters andunderscores in variablenames. Use uppercasecharacters only for namingconstants and in camelbacknaming.

routerrouter_typetrim_flag_csccon_connect_timeoutTRUEtrimFlagvar9__a__mess?

6.3 Abbreviate Names

Abbreviate the words usedto compose a name byremoving vowels or using aportion of the word whereappropriate.

pak_cnt_intrim_flgusr_num

6.5.2 Use Simple Nameipmtst_atutl_

Appendix A: Style Summary

ATS Automated Test Software Style Guide 64

Page 70: ATS Style Guide

Prefixing in Test Scripts

Use simple name prefixingto ensure that scriptprocedure and global datavariable names are uniquewithin the global namespace.

6.5.3 Use Name Spaces inProcedure Libraries

Use name spaces inprocedure libraries to avoidname space collision.

namespace eval dbg {variable debug_enable; # Flag used to enable/disable

debug output}

proc dbg::debug {cmd {msg {}}} {...

}

6.6 Name ConstantVariables UsingUppercase Characters

Use uppercase alphabeticcharacters and underscoresto make constant variablesstand out visually.

FALSEMAX_RETRIESIP_ADDR

6.7 Name Files UsingExtensions

Use filename extensions assuffixes to filenames tosignify the type of filecontents.

.exp - Procedure Library

.suite - Autotest Suite File

.queue - Autotest Queue File

.job - Autotest Job File

.dat - Data File

.config | .conf - Test Configuration File

.txt | .doc - Documentation

7 Constants

7.1 Define and UseConstant Variables

Define constant variables forconstant values that will bereused, need to bedocumented, or are likely toneed quick changing toimplement a script bug fix.

# Define constantsset MAX_RETRIES 10

...

# Attempt to create a test device connectionfor {set i 0} {$i < $MAX_RETRIES} {incr i} {

...}

8 Software Structure

8.1 Script Structure

Ensure that your scriptfollows the standardstructure and includes all

Interpreter InvocationHeader CommentLibrary SourcingPassword SettingArgument ParsingArgument Validation and Parsing

Appendix A: Style Summary

ATS Automated Test Software Style Guide 65

Page 71: ATS Style Guide

necessary sections.Constant DefinitionLocal Procedure DefinitionTest ConfigurationTest Execution and AnalysisTest UnconfigurationFooter Comment

8.2 Procedure LibraryStructure

Ensure that your procedurelibrary follows the standardstructure and includes allnecessary sections.

Interpreter InvocationHeader CommentPackage DefinitionRequire LibrariesDefine and Initialize the NamespaceDefine User Callable ProceduresDefine Internal, Support ProceduresFooter Comment

Appendix A: Style Summary

ATS Automated Test Software Style Guide 66