troubleshooting and debugging techniques week 1
Practice Quiz: Introduction to Debugging
1. What is part of the final step when problem solving?
- Documentation
- Long-term remediation
- Finding the root cause
- Gathering information
2. Which tool can you use when debugging to look at library calls made by the software?
- top
- strace
- tcpdump
- ltrace
3. What is the first step of problem solving?
- Prevention
- Gathering information
- Long-term remediation
- Finding the root cause
4. What software tools are used to analyze network traffic to isolate problems? (Check all that apply)
- tcpdump
- wireshark
- strace
- top
5. The strace (in Linux) tool allows us to see all of the _____ our program has made.
- Network traffic
- Disk writes
- System calls
- Connection requests
6. When a user reports that an "application doesn't work," what is an appropriate follow-up question to gather more information about the problem?
- Is the server plugged in?
- Why do you need the application?
- Do you have a support ticket number?
- What should happen when you open the app?
7. What is a heisenbug?
- The observer effect.
- A test environment.
- The root cause.
- An event viewer.
8. The compare_strings function is supposed to compare just the alphanumeric content of two strings, ignoring upper vs lower case and punctuation. But something is not working. Fill in the code to try to find the problems, then fix the problems.
import redef compare_strings(string1, string2): #Convert both strings to lowercase #and remove leading and trailing blanks string1 = string1.lower().strip() string2 = string2.lower().strip()
#Ignore punctuation punctuation = r"[.?!,;:-']" string1 = re.sub(punctuation, r"", string1) string2 = re.sub(punctuation, r"", string2)
#DEBUG CODE GOES HERE print(___)
return string1 == string2
print(compare_strings("Have a Great Day!", "Have a great day?")) # Trueprint(compare_strings("It's raining again.", "its raining, again")) # Trueprint(compare_strings("Learn to count: 1, 2, 3.", "Learn to count: one, two, three.")) # Falseprint(compare_strings("They found some body.", "They found somebody.")) # False
import re
def compare_strings(string1, string2):
#Convert both strings to lowercase
#and remove leading and trailing blanks
string1 = string1.lower().strip()
string2 = string2.lower().strip()
#Ignore punctuation
punctuation = r"[.?!,;:-']"
string1 = re.sub(punctuation, r"", string1)
string2 = re.sub(punctuation, r"", string2)
#DEBUG CODE GOES HERE
print(___)
return string1 == string2
print(compare_strings("Have a Great Day!", "Have a great day?")) # True
print(compare_strings("It's raining again.", "its raining, again")) # True
print(compare_strings("Learn to count: 1, 2, 3.", "Learn to count: one, two, three.")) # False
- import re #to use regular expressionsdef compare_strings(string1, string2): #function compare_strings that takes two strings as argument and compares themstring1 = string1.lower().strip() # converts the string1 characters to lowercase using lower() method and removes trailing blanksstring2 = string2.lower().strip() # converts the string1 characters to lowercase using lower() method and removes trailing blankspunctuation = r”[-.?!,;:’]” #regular expression for punctuation charactersstring1 = re.sub(punctuation, r””, string1) # specifies RE pattern i.e. punctuation in the 1st argument, new string r in 2nd argument, and a string to be handle i.e. string1 in the 3rd argumentstring2 = re.sub(punctuation, r””, string2) # same as above statement but works on string2 as 3rd argumentprint(‘string1:’,string1,’\nstring2:’,string2) #prints both the strings separated with a new linereturn string1 == string2 # compares strings and returns true if they matched else false#function calls to test the working of the above function compare_stringsprint(compare_strings(“Have a Great Day!”,”Have a great day?”)) # Trueprint(compare_strings(“It’s raining again.”,”its raining, again”)) # Trueprint(compare_strings(“Learn to count: 1, 2, 3.”,”Learn to count: one, two, three.”)) # Falseprint(compare_strings(“They found some body.”,”They found somebody.”)) # False
9. How do we verify if a problem is still persisting or not?
- Restart the device or server hardware
- Attempt to trigger the problem again by following the steps of our reproduction case
- Repeatedly ask the user
- Check again later
10. The datetime module supplies classes for manipulating dates and times, and contains many types, objects, and methods. You've seen some of them used in the dow function, which returns the day of the week for a specific date. We'll use them again in the next_date function, which takes the date_string parameter in the format of "year-month-day", and uses the add_year function to calculate the next year that this date will occur (it's 4 years later for the 29th of February during Leap Year, and 1 year later for all other dates). Then it returns the value in the same format as it receives the date: "year-month-day".
Can you find the error in the code? Is it in the next_date function or the add_year function? How can you determine if the add_year function returns what it's supposed to? Add debug lines as necessary to find the problems, then fix the code to work as indicated above.
import datetimefrom datetime import date
def add_year(date_obj): try: new_date_obj = date_obj.replace(year = date_obj.year + 1) except ValueError: # This gets executed when the above method fails, # which means that we're making a Leap Year calculation new_date_obj = date_obj.replace(year = date_obj.year + 4) return new_date_obj
def next_date(date_string): # Convert the argument from string to date object date_obj = datetime.datetime.strptime(date_string, r"%Y-%m-%d") next_date_obj = add_year(date_obj)
# Convert the datetime object to string, # in the format of "yyyy-mm-dd" next_date_string = next_date_obj.strftime("yyyy-mm-dd") return next_date_string
today = date.today() # Get today's dateprint(next_date(str(today))) # Should return a year from today, unless today is Leap Day
print(next_date("2021-01-01")) # Should return 2022-01-01print(next_date("2020-02-29")) # Should return 2024-02-29
import datetime
from datetime import date
def add_year(date_obj):
try:
new_date_obj = date_obj.replace(year = date_obj.year + 1)
except ValueError:
# This gets executed when the above method fails,
# which means that we're making a Leap Year calculation
new_date_obj = date_obj.replace(year = date_obj.year + 4)
return new_date_obj
def next_date(date_string):
# Convert the argument from string to date object
date_obj = datetime.datetime.strptime(date_string, r"%Y-%m-%d")
next_date_obj = add_year(date_obj)
# Convert the datetime object to string,
# in the format of "yyyy-mm-dd"
next_date_string = next_date_obj.strftime("yyyy-mm-dd")
return next_date_string
today = date.today() # Get today's date
print(next_date(str(today)))
# Should return a year from today, unless today is Leap Day
print(next_date("2021-01-01")) # Should return 2022-01-01
- import datetimefrom datetime import datedef add_year(date_obj):print(f”Original date: {date_obj}”)try:new_date_obj = date_obj.replace(year = date_obj.year + 1)print(f”New date: {new_date_obj}”)except ValueError:# This gets executed when the above method fails,# which means that we’re making a Leap Year calculationnew_date_obj = date_obj.replace(year = date_obj.year + 4)print(f”New date: {new_date_obj} (leap year)”)return new_date_objdef next_date(date_string):# Convert the argument from string to date objectdate_obj = datetime.datetime.strptime(date_string, r”%Y-%m-%d”)next_date_obj = add_year(date_obj)# Convert the datetime object to string,# in the format of “yyyy-mm-dd”next_date_string = next_date_obj.strftime(“%Y-%m-%d”)return next_date_stringtoday = date.today() # Get today’s dateprint(next_date(str(today)))# Should return a year from today, unless today is Leap Dayprint(next_date(“2021-01-01”)) # Should return 2022-01-01print(next_date(“2020-02-29”)) # Should return 2024-02-29
11. You have a list of computers that a script connects to in order to gather SNMP traffic and calculate an average for a set of metrics. The script is now failing, and you do not know which remote computer is the problem. How would you troubleshoot this issue using the bisecting methodology?
- Run the script with the first half of the computers.
- Run the script with last computer on the list.
- Run the script with first computer on the list
- Run the script with two-thirds of the computers.
12. The find_item function uses binary search to recursively locate an item in the list, returning True if found, False otherwise. Something is missing from this function. Can you spot what it is and fix it? Add debug lines where appropriate, to help narrow down the problem.
def find_item(list, item): #Returns True if the item is in the list, False if not. if len(list) == 0: return False
#Is the item in the center of the list? middle = len(list)//2 if list[middle] == item: return True
#Is the item in the first half of the list? if item < list[middle]: #Call the function with the first half of the list return find_item(list[:middle], item) else: #Call the function with the second half of the list return find_item(list[middle+1:], item)
return False
#Do not edit below this line - This code helps check your work!list_of_names = ["Parker", "Drew", "Cameron", "Logan", "Alex", "Chris", "Terry", "Jamie", "Jordan", "Taylor"]
print(find_item(list_of_names, "Alex")) # Trueprint(find_item(list_of_names, "Andrew")) # Falseprint(find_item(list_of_names, "Drew")) # Trueprint(find_item(list_of_names, "Jared")) # False
def find_item(list, item):
#Returns True if the item is in the list, False if not.
if len(list) == 0:
return False
#Is the item in the center of the list?
middle = len(list)//2
if list[middle] == item:
return True
#Is the item in the first half of the list?
if item < list[middle]:
#Call the function with the first half of the list
return find_item(list[:middle], item)
else:
#Call the function with the second half of the list
return find_item(list[middle+1:], item)
return False
#Do not edit below this line - This code helps check your work!
list_of_names = ["Parker", "Drew", "Cameron", "Logan", "Alex", "Chris", "Terry", "Jamie", "Jordan", "Taylor"]
print(find_item(list_of_names, "Alex")) # True
print(find_item(list_of_names, "Andrew")) # False
print(find_item(list_of_names, "Drew")) # True
- def find_item(list, item):#Returns True if the item is in the list, False if not.iflen(list) == 0:returnFalse# In order to use binary search, list needs to be sortedlist.sort()#Is the item in the center of the list?middle = len(list)//2iflist[middle] == item:returnTrue#Is the item in the first half of the list?if item < list[middle]:#Call the function with the first half of the listreturn find_item(list[:middle], item)else:#Call the function with the second half of the listreturn find_item(list[middle+1:], item)returnFalse#Do not edit below this line – This code helps check your work!list_of_names = [“Parker”, “Drew”, “Cameron”, “Logan”, “Alex”, “Chris”, “Terry”, “Jamie”, “Jordan”, “Taylor”]print(find_item(list_of_names, “Alex”)) # Trueprint(find_item(list_of_names, “Andrew”)) # Falseprint(find_item(list_of_names, “Drew”)) # Trueprint(find_item(list_of_names, “Jared”)) # False
13. The binary_search function returns the position of key in the list if found, or -1 if not found. We want to make sure that it's working correctly, so we need to place debugging lines to let us know each time that the list is cut in half, whether we're on the left or the right. Nothing needs to be printed when the key has been located.
For example, binary_search([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3) first determines that the key, 3, is in the left half of the list, and prints "Checking the left side", then determines that it's in the right half of the new list and prints "Checking the right side", before returning the value of 2, which is the position of the key in the list.
Add commands to the code, to print out "Checking the left side" or "Checking the right side", in the appropriate places.
def binary_search(list, key): #Returns the position of key in the list if found, -1 otherwise.
#List must be sorted: list.sort() left = 0 right = len(list) - 1
while left <= right: middle = (left + right) // 2
if list[middle] == key: return middle if list[middle] > key: right = middle - 1 if list[middle] < key: left = middle + 1 return -1
print(binary_search([10, 2, 9, 6, 7, 1, 5, 3, 4, 8], 1))"""Should print 2 debug lines and the return value:Checking the left sideChecking the left side0"""
print(binary_search([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5))"""Should print no debug lines, as it's located immediately:4"""
print(binary_search([10, 9, 8, 7, 6, 5, 4, 3, 2, 1], 7))"""Should print 3 debug lines and the return value:Checking the right sideChecking the left sideChecking the right side6"""
print(binary_search([1, 3, 5, 7, 9, 10, 2, 4, 6, 8], 10))"""Should print 3 debug lines and the return value:Checking the right sideChecking the right sideChecking the right side9"""
print(binary_search([5, 1, 8, 2, 4, 10, 7, 6, 3, 9], 11))"""Should print 4 debug lines and the "not found" value of -1:Checking the right sideChecking the right sideChecking the right sideChecking the right side-1"""
def binary_search(list, key):
#Returns the position of key in the list if found, -1 otherwise.
#List must be sorted:
list.sort()
left = 0
right = len(list) - 1
while left <= right:
middle = (left + right) // 2
if list[middle] == key:
return middle
if list[middle] > key:
right = middle - 1
if list[middle] < key:
left = middle + 1
return -1
print(binary_search([10, 2, 9, 6, 7, 1, 5, 3, 4, 8], 1))
"""Should print 2 debug lines and the return value:
Checking the left side
Checking the left side
0
"""
print(binary_search([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5))
"""Should print no debug lines, as it's located immediately:
4
"""
print(binary_search([10, 9, 8, 7, 6, 5, 4, 3, 2, 1], 7))
"""Should print 3 debug lines and the return value:
Checking the right side
Checking the left side
Checking the right side
6
"""
print(binary_search([1, 3, 5, 7, 9, 10, 2, 4, 6, 8], 10))
"""Should print 3 debug lines and the return value:
Checking the right side
Checking the right side
Checking the right side
9
"""
print(binary_search([5, 1, 8, 2, 4, 10, 7, 6, 3, 9], 11))
"""Should print 4 debug lines and the "not found" value of -1:
Checking the right side
Checking the right side
Checking the right side
Checking the right side
-1
- def binary_search(list, key):#Returns the position of key in the list if found, -1 otherwise.#List must be sorted:list.sort()left = 0right = len(list) – 1while left <= right:middle = (left + right) // 2iflist[middle] == key:return middleiflist[middle] > key:print(“Checking the left side”)right = middle – 1iflist[middle] < key:print(“Checking the right side”)left = middle + 1return-1print(binary_search([10, 2, 9, 6, 7, 1, 5, 3, 4, 8], 1))“””Should print 2 debug lines and the return value:Checking the left sideChecking the left side0“””print(binary_search([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5))“””Should print no debug lines, as it’s located immediately:4“””print(binary_search([10, 9, 8, 7, 6, 5, 4, 3, 2, 1], 7))“””Should print 3 debug lines and the return value:Checking the right sideChecking the left sideChecking the right side6“””print(binary_search([1, 3, 5, 7, 9, 10, 2, 4, 6, 8], 10))“””Should print 3 debug lines and the return value:Checking the right sideChecking the right sideChecking the right side9“””print(binary_search([5, 1, 8, 2, 4, 10, 7, 6, 3, 9], 11))“””Should print 4 debug lines and the “not found” value of -1:Checking the right sideChecking the right sideChecking the right sideChecking the right side-1“””
14. When trying to find an error in a log file or output to the screen, what command can we use to review, say, the first 10 lines?
- wc
- tail
- head
- bisect
15. The best_search function compares linear_search and binary_search functions, to locate a key in the list, and returns how many steps each method took, and which one is the best for that situation. The list does not need to be sorted, as the binary_search function sorts it before proceeding (and uses one step to do so). Here, linear_search and binary_search functions both return the number of steps that it took to either locate the key, or determine that it's not in the list. If the number of steps is the same for both methods (including the extra step for sorting in binary_search), then the result is a tie. Fill in the blanks to make this work.
def linear_search(list, key): #Returns the number of steps to determine if key is in the list
#Initialize the counter of steps steps=0 for i, item in enumerate(list): steps += 1 if item == key: break return ___
def binary_search(list, key): #Returns the number of steps to determine if key is in the list
#List must be sorted: list.sort()
#The Sort was 1 step, so initialize the counter of steps to 1 steps=1
left = 0 right = len(list) - 1 while left <= right: steps += 1 middle = (left + right) // 2 if list[middle] == key: break if list[middle] > key: right = middle - 1 if list[middle] < key: left = middle + 1 return ___
def best_search(list, key): steps_linear = ___ steps_binary = ___ results = "Linear: " + str(steps_linear) + " steps, " results += "Binary: " + str(steps_binary) + " steps. " if (___): results += "Best Search is Linear." elif (___): results += "Best Search is Binary." else: results += "Result is a Tie."
return results
print(best_search([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1))#Should be: Linear: 1 steps, Binary: 4 steps. Best Search is Linear.
print(best_search([10, 2, 9, 1, 7, 5, 3, 4, 6, 8], 1))#Should be: Linear: 4 steps, Binary: 4 steps. Result is a Tie.
print(best_search([10, 9, 8, 7, 6, 5, 4, 3, 2, 1], 7))#Should be: Linear: 4 steps, Binary: 5 steps. Best Search is Linear.
print(best_search([1, 3, 5, 7, 9, 10, 2, 4, 6, 8], 10))#Should be: Linear: 6 steps, Binary: 5 steps. Best Search is Binary.
print(best_search([5, 1, 8, 2, 4, 10, 7, 6, 3, 9], 11))#Should be: Linear: 10 steps, Binary: 5 steps. Best Search is Binary.
def linear_search(list, key):
#Returns the number of steps to determine if key is in the list
#Initialize the counter of steps
steps=0
for i, item in enumerate(list):
steps += 1
if item == key:
break
return ___
def binary_search(list, key):
#Returns the number of steps to determine if key is in the list
#List must be sorted:
list.sort()
#The Sort was 1 step, so initialize the counter of steps to 1
steps=1
left = 0
right = len(list) - 1
while left <= right:
steps += 1
middle = (left + right) // 2
if list[middle] == key:
break
if list[middle] > key:
right = middle - 1
if list[middle] < key:
left = middle + 1
return ___
def best_search(list, key):
steps_linear = ___
steps_binary = ___
results = "Linear: " + str(steps_linear) + " steps, "
results += "Binary: " + str(steps_binary) + " steps. "
if (___):
results += "Best Search is Linear."
elif (___):
results += "Best Search is Binary."
else:
results += "Result is a Tie."
return results
print(best_search([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1))
#Should be: Linear: 1 steps, Binary: 4 steps. Best Search is Linear.
print(best_search([10, 2, 9, 1, 7, 5, 3, 4, 6, 8], 1))
#Should be: Linear: 4 steps, Binary: 4 steps. Result is a Tie.
print(best_search([10, 9, 8, 7, 6, 5, 4, 3, 2, 1], 7))
#Should be: Linear: 4 steps, Binary: 5 steps. Best Search is Linear.
print(best_search([1, 3, 5, 7, 9, 10, 2, 4, 6, 8], 10))
#Should be: Linear: 6 steps, Binary: 5 steps. Best Search is Binary.
print(best_search([5, 1, 8, 2, 4, 10, 7, 6, 3, 9], 11))