View
226
Download
3
Tags:
Embed Size (px)
Citation preview
COMS W3156:Software Engineering, Fall 2001
Lecture #14: Implementation II, LDAP
Janak J Parekh
Administrativia• LDAP configured• HW2 due now• Design due in one week• Requirements update pending (v1.2)
– LDAP renaming– Missing some boolean operators– Something else?
• Webboard…– You are supposed to do the homework
Next class
• I’m debating
Today’s class
• Implementation, continued (testing)
• LDAP
From last class
• Conclusion: we need a compromise – highlight faults, while accepting that not all faults will be detected
• Black-box test cases first (specifications)
• Then, develop additional glass-box techniques (code)
Black-box module testing
• Goal: devise small number of test cases that cover most of the possibilities
• Every test case must be chosen to detect a previously undetected fault: don’t repeat
• Equivalence testing and boundary value analysis
Equivalence class testing
• Break down cases into equivalence classes
• Example: database with max 16,000 records– If it works for 251, it’ll probably work for
12,000
• Define classes that need to be tested– Less than 1 record– From 1 to 16,000 records– More than 16,000 records
Boundary testing
• Take the equivalence classes to the next level– 0 records– 1 record– 2 records– 723 records– 16,382 records– 16,383 records– 16,384 records
Boundary testing (II)
• Test both sides of the classes• While the example referred to input
specifications, can also boundary-test output cases
• Example: payroll– Test deductions between, and including, min
and max deduction values, as well as beyond them
– Devise test cases to get these results
Boundary testing (III)
• In general, for a range {R1, R2}, 5 test cases:– Less than R1
– Equal to R1
– Greater than R1, less than R2
– Equal to R2
– Greater than R2
• Need to start thinking this way
Functional testing
• Test on functionalities of module
• Step 1: determine functions of module
• Step 2: Devise test data for each low-level function
• Step 3: Determine higher-level functions
• (picture)
• This is hybrid black-box and glass-box
Functional testing (II)
• In practice, need to do functional analysis, since it’s not always so simple
• Often, cross-module functionality
• Object-oriented doesn’t help
• Difficult to resolve at times, but general principle remains sound
Glass-box testing
• Look at the source code, and design test cases from there
• Statement coverage
• Path coverage
• Branch coverage
Statement coverage
• Run a series of test cases in which every statement is executed at least once.
• Use a CASE tool to keep track of how many times each statement has been executed– Rational PureCoverage, which we do have, but
we’re probably not going to use it
• Problem: no guarantee all outcomes of branches are tested (i.e. if clauses)
Branch coverage
• Run a series of tests to ensure all branches are tested at least once
• Tools such as Generic Coverage Tool (gct)
• Statement/branch coverage are structural tests
Path coverage
• Test all paths
• Challenge: reduce number of paths to be examined while still uncovering as many faults as possible– Restrict test cases to linear code sequences:
identify set of points from which control may jump, and devise code sequences that begin at control flow and end at another control flow
All-definition-use-path
• Define each occurrence of a variable as a definition of the variable (int i=1) or use of the variable (y=i+5)
• Identify all paths between definition and use• Set up a test case for each path• Still theoretically 2d paths (d = #branches)• Can be shown that in real programs this is
not reached
Dead code
• Sometimes programmers will have an “infeasible path” that cannot be reached given any input
• Statement coverage detects this
Complexity metrics
• Intuition suggests more complex code implies more bug-prone code
• Various metrics to determine complexity– LOC– McCabe’s measure of cyclomatic complexity
• # branches in the module• Found to be reasonably accurate
– Halstead utilizes a linear combination of several metrics (operators and operands)
• Problem: both Halstead and McCabe practically are linear with LOC
Code walkthroughs/inspections
• Works very, very well*
• Explaining your own code finds many faults
• Suggest you try it in a group environment
• Much cheaper than execution-based testing– Takes less time– Faults are detected earlier
Comparing testing mechanisms
• Brief conclusion: all are valid, but some work a bit better than others
• In some studies, it’s been shown that code reading was most effective at detecting “interface faults”, while black-box testing was most effective at finding “control faults”
• Conclusion: code walkthroughts/inspections work
Cleanroom
• Combine a number of different techniques, including incremental lifecycle
• Critical aspect: cannot compile a module until it passes inspection
• Has been successful for both small and large programs
• Metric: testing faults from time of compilation
Challenges of testing objects
• Can’t execution-test a class, only objects
• Information hiding and simple methods complicate things: need to call both setter and getter methods to test variable changes
• Need to test inherited methods!– Context may have changed: methods it may call
may have been overridden
Miscellany
• Management: how much time and money to test?– Cost-benefit analysis
– Reliability analysis: statistical determination of faults remaining
• When to rewrite?– Predetermine “maximum number of faults”
• Challenges– When, how to reuse code
LDAP
• Lightweight Directory Access Protocol• Essentially a hierarchical (treelike) database
– Attributes: Attribute-value pair– Objects: collection of Attributes (record)– Records are uniquely identified using the DN,
or distinguished name
• Not XML, but you don’t need to talk the language: JNDI does the work
Distinguished name
• Unique name assigned to everything in the database
• Implicit hierarchy: “root” is the right part• Comma (,) is delineator• Utterly flexible• “cn=Janak,ou=PSL,ou=CS,o=Columbia”• “cn=Janak,dc=psl,dc=cs,dc=columbia,dc=e
du”
Our LDAP database
• Designated as “o=softe” – it’s the root of the tree
• Three nodes (each have the root affixed):– ou=services– ou=actors– ou=states
• Each item under this must have its own DN
Entries in LDAP
• Every entry will have its own unique DN: the “identifier” will usually be a CN (Common Name) component of the DN
• “cn=A1,ou=services,dc=softe,dc=cs,dc=columbia,dc=edu”
• “cn=johndoe,ou=actors,dc=softe,dc=cs,dc=columbia,dc=edu”
Schema
• Each entry can be one of any (millions) of types
• We’ve explicitly created three for you– Service– Actor– ActorState
• Names changed from requirements; will fix
Service
• Service reference ID: CN tag in DN: use your group ID
• Required:– ServerIP (string)– ServerPort (int)– ServerType (string): A or S
• Optional– WorldName– ServerExtensions
Actor
• Actor “name”/login id: CN tag in DN• Required:
– HP: int– XP: int– Gold: int– Password: String
• We’ll give you crypting code
• Optional:– ImageURL
ActorState
• CN in DN: unique identifier– Concatenate Actor, World, and Service
– ac=actorname+wn=worldname+sv=servicename
• Required– LocationX: int
– LocationY: int
– Status: int
– WorldInstance: int
JNDI
• Straightforward API, built into JDK 1.3 and higher
• Can do more than LDAP: DNS, etc.
• For LDAP, uses concept of directory context in which the operation will be done– ldap://softe.cs.columbia.edu:389/o=softe
• Once set, go ahead and do operation(s)
• Recitation!
JNDI Lookups
• getAttributes() method searches by (unique) DN– similar to lookup() but more powerful
• Returns Attributes object: collection of attribute-value pairs; you can “get” and “put”; like a Hashtable
JNDI Searches
• search() searches within a DN for all entries that match the Attributes set you provide
• Returns NamingEnumeration (subinterface of Enumeration)– Each entry in the Enumeration is a
SearchResult, which you can convert toString() and then do a lookup
JNDI Lists
• list() finds all in the DN context
• Returns NamingEnumeration, consisting of NameClass pairs
• getName() method in this class
JNDI Writes
• Just like we can getAttributes(), we can…
• (re)bind()– Ok, so the parallel isn’t ideal– Name: DN– Object: null (Java can serialize to LDAP!)– Attributes: our good friend
JNDI Deletes
• unbind();
• Must supply whole DN to it– Use search() if you don’t know what the full
DN of the relevant object is
• Almost never throws exception, even if the record isn’t there– idempotent
JNDI Miscellany
• Name class– You don’t have to use this: it’s a bit more
“civilized” way of dealing with DN’s, though– For the scope of this class, it’s acceptable just
to use Strings for DN’s
Our permissions setup
• Services: readable by all, writeable only by those who have password
• Actors: read/write by password only• ActorStates: read/write by password only• Net effect
– Client has no password, and no need of one– All servers will share the same DN and
password (yes, logins are via DN too!)
What does this mean for you?
• Implementation/Testing– You now know what your testing plan will look like
• LDAP– You finally know all the details to use LDAP not
only for your design, but also your implementation
– Shouldn’t need a whole lot for the design
– We give you code samples: adjust it to suit your needs