JUnit's LinkedList method test fails, why?
I have this method which will search a LinkedList (named ListNode) and check for chars, and check if they contain uppercase chars, then store it in a new linked list, and return it. I wrote code for this and tested it with JUnit and it failed JUNit (one of those blue boxes). Does anyone know what's wrong?
Here is my LinkedList method:
public static ListNode copyUpperCase(ListNode head) {
ListNode newListNode = mkEmpty();
if(head == null){
throw new ListsException("");
}else{
while(head.next != null){
if(Character.isUpperCase(head.element)){
newListNode.element = head.element;
}
head = head.next;
}
}
return newListNode;
}
Here is the ListNode:
public class ListNode {
public char element;
public ListNode next;
}
Here is the test method:
@Test
public void testCopyUpperCase()
{
// Inject upper case letters randomly in the test strings.
// Assert equal results when extracting the upper case chars from
// the corresponding list, as wheen extracting them from the
// injected string itself.
for ( String s : cases ) {
String uppersAndLowers = randInjectUpper(s);
// Extract the upper case characters
StringBuilder uppers = new StringBuilder();
for ( int i = 0; i < uppersAndLowers.length(); i++ ) {
final char c = uppersAndLowers.charAt(i);
if ( Character.isUpperCase(c) )
uppers.append(c);
}
ListNode temp = Lists.toList(uppersAndLowers);
ListNode lhs = Lists.copyUpperCase(temp);
assertFalse(hasSharedNodes(temp,lhs));
ListNode rhs = Lists.toList(uppers.toString());
assertTrue(Lists.equals(lhs,rhs));
}
}
The failing line in the test method is the last line, which is:
assertTrue(Lists.equals(lhs,rhs));
If it fails on that line, what does that mean?
ps. This is also the equals method:
// Two lists are equal if both are empty, or if they have equal lengths
// and contain pairwise equal elements at the same positions.
public static boolean equals(ListNode l1,ListNode l2) {
if ( isEmpty(l1) && isEmpty(l2) )
return true;
else if ( isEmpty(l1) || isEmpty(l2) )
return false;
else { // both lists are non-empty
ListNode p1 = l1.next, p2 = l2.next;
while ( p1 != null && p2 != null ) {
char c1 = p1.element, c2 = p2.element;
if ( p1.element != p2.element )
return false;
p1 = p1.next;
p2 = p2.next;
}
return p1 == null && p2 == null;
}
}
EDIT: Here is the new method:
public static ListNode copyUpperCase(ListNode head) {
ListNode newListNode = mkEmpty();
if(head == null){
throw new ListsException("Lists: null passed to copyUpperCase");
}else{
String cpy = toString(head);
char[] chry = cpy.toCharArray();
for(int i = 0; i < chry.length ; i++ )
if(Character.isUpperCase(chry[i])){
newListNode.element = chry[i];
}
newListNode = newListNode.next;
}
return newListNode;
}
Your equals method seems to be ok. It correctly checks if both lists are empty, then correctly checks if one list is empty and the other is empty. After that, you iterate over both lists at the same time, checking each character, and at the end, expect both pointers to be null. Everything is fine.
So the problem must be in the toList
method or in the copyUppercase
method. Indeed, your copyUppercase
approach is buggy. Ask yourself, what happens to a list with only one element? Then ask yourself, what will happen to the last element of the provided list? Can you see the sights?
while loop condition is false: it must simply be
while (head != null) { ... }