-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/lab 5 #463
Feature/lab 5 #463
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
var out io.Writer = os.Stdout | ||
|
||
func main() { | ||
fmt.Fprint(out, IPAddr{127, 0, 0, 1}) | ||
} | ||
|
||
type IPAddr struct { | ||
add1, add2, add3, add4 uint8 | ||
} | ||
|
||
func (ipAddr IPAddr) String() string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one is an odd one too. I guess I came from java and usually I am all in on readability and I hate to have comments in my code. Therefore generally I tend to stay away from shortform in naming variables, method, etc. (I would have request changes on the pr if it's Java or even js). But if it's the proper coding pattern of golang then I will have to change my mindset and follow the convention. It would be good if there's a pattern doc that we can follow especially when building enterprise app. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was an odd one for me too, I always believe that variable names should be clear and concise. Guess this is something we need to get use to. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming convention in go is to use really short names for receivers. The reason is that a method can only have one receiver, and that name should be reused for all methods on a particular type. I don't think having a long receiver name aides readability, I actually think the ridiculously long variable names in java hinders readability. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. alright will change it thanks, need to get use to it =) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about you do it then? :) |
||
return strings.Join([]string{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use a string format instead of joining on a slice There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dpes fmt.Sprintf return a string not print out the string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://godoc.org/fmt#Sprintf (it returns a string) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://godoc.org/fmt#Sprintf (it does) |
||
strconv.Itoa(int(ipAddr.add1)), | ||
strconv.Itoa(int(ipAddr.add2)), | ||
strconv.Itoa(int(ipAddr.add3)), | ||
strconv.Itoa(int(ipAddr.add4))}, ".") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"strconv" | ||
"testing" | ||
) | ||
|
||
func TestMainFunction(t *testing.T) { | ||
t.Run("Test main to return string values of IPAddr({127, 0, 0, 1}) with proper formatting", func(t *testing.T) { | ||
var buf bytes.Buffer | ||
out = &buf | ||
|
||
main() | ||
|
||
expected := strconv.Quote("127.0.0.1") | ||
actual := strconv.Quote(buf.String()) | ||
|
||
if expected != actual { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use the testify library, it would be as simple as assert.Equal(expected, actual, msg) - one line instead of 3 lines of code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I tried testify but I noticed that lab6 is the only one that explicitly say to use testify so I figured best to kept it plain vanilla for all labs until lab 6 so at least I get the hang of doing it without external dependencies till then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not exactly, lab06 ask you to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would recommend using testify, however don't feel the need to change it since your tests are all passing. If you do the later labs, you'll probably want to use it more since it significantly shortens the test code. |
||
t.Errorf("Unexpected output, expected: %s, actual: %s", expected, actual) | ||
} | ||
}) | ||
} | ||
|
||
func TestIpAddrDefaultToString(t *testing.T) { | ||
testCases := []struct { | ||
description string | ||
input IPAddr | ||
expected string | ||
}{ | ||
{"Test IPAddr with all zeros in addresses", IPAddr{0, 0, 0, 0}, "0.0.0.0"}, | ||
{"Test IPAddr with some values assigned", IPAddr{add1: 5, add4: 4}, "5.0.0.4"}, | ||
{"Test IPAddr with no value", IPAddr{}, "0.0.0.0"}, | ||
{"Test IPAddr with max values allowed on uint8", IPAddr{255, 255, 255, 255}, "255.255.255.255"}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One of the code-owners asked me to have a test case of 'IPAddr{0}" or IPAddr{172, 0}, so perhaps you can try that too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok will add them There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on your type declaration for You can partially initialize an array, so You could write tests with partial struct initialization using the variable identifiers
Playspace example: https://goplay.space/#uhJY-1G0t3h There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks @anzboi, ive got a test for IPAddr{add1: 1, add2:1} already above. So i guess I will just add another one for {addr1: 0} and {addr1: 172, addr2: 0} thanks! |
||
} | ||
|
||
for _, testCase := range testCases { | ||
input := testCase.input | ||
expected := testCase.expected | ||
|
||
t.Run(testCase.description, func(t *testing.T) { | ||
actual := input.String() | ||
if expected != actual { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to use testify library here as well. |
||
t.Errorf("Unexpected output, expected: %s, actual: %s", expected, actual) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint8 is correct that it gives the correct IP Address range of 0-255, and the clue given by the lecture notes is using array of 4 bytes (type IPAddr [4]byte). From a technical perspective, it is more accurate, as IPv4 address is represented as bytes( 8 bits). My guess is that the program would run faster using byte as it more native at the hardware level. I actually googled around, and seems mos t implementations in go is implemented as Byte and not uint8.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm not wrong byte is an alias of uint8 and uint8 is a more explicit way of declaring it. But at the end of the day it really depends on people's preferences interms of readability. I am more than happy to change it to byte but I do want to hear from any of the course reviewer about it though. Maybe you are right since in this case it's an ip address, maybe byte alias is more relevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I don't have problems with uint32, this is more of a comment to spark some conversations. I believe that the data type should reflect the type of data that you'll be getting, and in this case. it will be bytes. I do think that having array instead of 4 different variables will help, your String() will just be a one line using string methods. So this is something you can explore. I'd say just leave it, and wait to see what the final approver has to say about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually don't have a problem with it either way. Golang inlines structs instances, so this will be just as efficient space and time-wise as
[4]byte
. The difference is how you use theIPAddr
type.[4]byte
gives you array access and the ability to range over the elements of the address.your
struct
allows you to only initialize say the third element (useIPAddr{add3: 1}
).My preference is towards
[4]byte
, but its not a strong preference.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, @starfallz is correct in saying
byte
is an alias ofuint8
. There really is no difference between the two, only in that bytes are more often used for text based data handling simply because people prefer saying byte instead of int (int is a number, whereas byte is data).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change as per reviewer requests (it will test cases nicer too).