Lab 2 - Simple Search Engine and Testing
Table of Contents
1. Simple Search Engine
In Week 2, we implemented an ultra-basic search engine to practice our use of ssh and scp. Using the structure of the given Server.java file, I was able to implement the search engine using the following code:
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
class Handler implements URLHandler {
List<String> list = new ArrayList<>();
public String handleRequest(URI url) {
if (url.getPath().equals("/")) {
return String.format("Basic Search Engine");
}
else {
System.out.println("Path: " + url.getPath());
if (url.getPath().contains("/add")) {
String[] parameters = url.getQuery().split("=");
if (parameters[0].equals("s")) {
list.add(parameters[1]);
return String.format("%s added to the list", parameters[1]);
}
}
if (url.getPath().contains("/search")) {
String[] parameters = url.getQuery().split("=");
List<String> ans = new ArrayList<>();
if (parameters[0].equals("s")) {
for (String i: list) {
if (i.contains(parameters[1])) {
ans.add(i);
}
}
}
return String.join(" ", ans);
}
return "404 Not Found!";
}
}
}
class SearchEngine {
public static void main(String[] args) throws IOException {
if(args.length == 0){
System.out.println("Missing port number! Try any number between 1024 to 49151");
return;
}
int port = Integer.parseInt(args[0]);
Server.start(port, new Handler());
}
}
You can run the above class using javac SearchEngine.java and java SearchEngine <port-number>. (Note that you must pass in the desired port number as an argument into the command line - this value can be anything between 1024 and 49151). Once you run the program, the main function is called - establishing the web server at the selected port and allowing you to view the live version of your project at <host>:<port-number>. Your screen should look somewhat like the one below:

After getting the live version of the program running, you can append various paths to the end of the URL to achieve different results. There are two basic functions that you can use: /add?s=<element> and /search?s=<query>. They’re both detailed below:
- /add
-
After appending
/addto the end of your URL, you can append?s=followed by any String value. Doing this will call thehandleRequestfunction and will go into the the firstifcondition. This appendage will add your chosen value to the ArrayList,list. The function will then print to the screen, confirming that your chosen value has been added to the list. An example for the String value “34” is shown below: -

-
- /search
-
After adding
/searchto the end of your URL, you can append?s=followed by any String value. This will invoke the secondifcondition inhandleRequestand will search the ArrayList,list, for any occurrences of the String value passed in through the query. The function then iterates throughlistand returns a list of the elements fromlistthat contain the String value. In the example below, I have added the following values tolist:{"34", "25", "24", "234", "as34d"}. Searching for the value “34” returns the following: -

-
2. Testing
- ArrayExamples Bugs
- Test - The test used to identify this bug is detailed below:
@Test public void testReverse() { int[] a = {3, 1, 5}; assertArrayEquals(new int[]{5, 1, 3}, ArrayExamples.reversed(a)); }- Code - The code for the
ArrayExmples.reversed()function is detailed below:
static int[] reversed(int[] arr) { int[] newArray = new int[arr.length]; for(int i = 0; i < arr.length; i += 1) { arr[i] = newArray[arr.length - i - 1]; } return arr; }- Symptoms - When the above test is run, the
reversedfunction runs on arraya, but returns the array{0, 0, 0}, which is the incorrect reversal. The correct reversed array should be{5, 1, 3}. - Bugs - When the above test is run, the function above is invoked on the array
a. Thereversedfunction then iterates througharr(reference toa), reassigning each value inarr(a) to the diametrically opposite index value fromnewArray, an initialized array from within thereversedfunction. This causes each value inato be reassigned to the default values put intonewArraywhennewArraywas initialized, which in our case, is 0. - Fixes - This issue could be easily corrected by correcting line 4 of the
reversedfunction to be the following:newArray[i] = arr[arr.length - i - 1];. Additionally, you would need to change the return statement to bereturn newArray;instead ofreturn arr; - Sample Run - The JUNIT report for this test is shown below:

- ListExamples Bugs
- Test - The test used to identify this bug is detailed below:
@Test public void testMerge() { ArrayList<String> first = new ArrayList<String>(); ArrayList<String> second = new ArrayList<String>(); first.add("A"); second.add("B"); first.add("C"); second.add("D"); ArrayList<String> test = new ArrayList<String>(); test.add("A"); test.add("B"); test.add("C"); test.add("D"); assertEquals(test, ListExamples.merge(first, second)); }- Code - The code for the
ListExamples.merge()function is detailed below:
static List<String> merge(List<String> list1, List<String> list2) { List<String> result = new ArrayList<>(); int index1 = 0, index2 = 0; while(index1 < list1.size() && index2 < list2.size()) { if(list1.get(index1).compareTo(list2.get(index2)) < 0) { result.add(list1.get(index1)); index1 += 1; } else { result.add(list2.get(index2)); index2 += 1; } } while(index1 < list1.size()) { result.add(list1.get(index1)); index1 += 1; } while(index2 < list2.size()) { result.add(list2.get(index2)); index1 += 1; } return result; }- Symptoms - The test
testMergeinvokes themergefunction from above on thefirstandsecondArrayLists. When run on these two ArrayLists, themergefunction runs infinitely, and is stuck in an infinite loop. This causes the heap (the memory allocated by Java for your program) gets too full, causing the program to be terminated early. - Bugs - The function
merge, when run on two ArrayLists, does not check if the element that it is considering adding has already been added. Thus, in line 28, the program continuously adds the last element fromlist1(first) when all elements inlist1are lexicographically lesser in value, as compared with the elements fromlist2(second). - Fixes - The function
mergeshould keep a track of which list the last element was added from, whether that be through a boolean value or keeping a current List and redefining that to the current active list. Once a list has been exhausted and all the elements of the list have been added to theresultArrayList, the function should only add elements from the other List. - Sample Run - The JUNIT report for this test is shown below:
