Skip to content

handlers_test.go: MOCK --> POSIX #231

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

Merged
merged 13 commits into from
Apr 4, 2025
Merged

Conversation

phbnf
Copy link
Collaborator

@phbnf phbnf commented Apr 3, 2025

Towards #217, #5.

This PR reimplements handlers_test.go using a POSIX based log, rather than using a mock package.

Precisely, this PR:

  1. introduces a POSIX issuer storage testonly implementation
  2. refactors helper functions in handlers_test.go to initialise a log with a POSIX issuer storage, a POSIX Tessera backend, and a BBolt deduplication database
  3. migrates all tests to this new test log implementation
  4. Removes the mocking package and instructions
  5. adds a GetRoots test
  6. Removes a test where writes to Tessera fail. We'll need to implement this again in a followup PR. I couldn't do it in this PR because I could not find a straight forward way to generate a Tessera error from a test with a POSIX backend without making this PR too complex.

Followup PRs will add additional tests according to TODOs.

phbnf added 7 commits April 3, 2025 09:25
# Conflicts:
#	internal/scti/handlers_test.go
# Conflicts:
#	internal/scti/handlers_test.go

# Conflicts:
#	internal/scti/handlers_test.go
# Conflicts:
#	internal/scti/handlers_test.go

# Conflicts:
#	internal/scti/handlers_test.go

# Conflicts:
#	internal/scti/handlers_test.go
# Conflicts:
#	internal/scti/handlers_test.go
# Conflicts:
#	internal/scti/handlers_test.go
@phbnf phbnf marked this pull request as ready for review April 3, 2025 09:50
@phbnf phbnf marked this pull request as draft April 3, 2025 09:53
@phbnf phbnf marked this pull request as ready for review April 3, 2025 10:00
server := setupTestServer(t, log, path.Join(prefix, "ct/v1/get-roots"))
defer server.Close()

t.Run("get-roots", func(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the t.Run?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woops, thanks


func TestGetRoots(t *testing.T) {
log := setupTestLog(t)
server := setupTestServer(t, log, path.Join(prefix, "ct/v1/get-roots"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use types.GetRootsPath? (bunch of other places in the PR too for this and the other paths)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can yeah - I did not do this intentionally because I see little benefits:

  • I find the end result less readable
  • this value is never going to change

recorder := makeAddPrechainRequest(t, info.handlers, chain)
if recorder.Code != test.want {
t.Fatalf("addPrechain()=%d (body:%v); want %d", recorder.Code, recorder.Body, test.want)
resp, err := http.Post(server.URL+"/ct/v1/add-pre-chain", "application/json", chain)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path.Join(server.URL, types.AddPreChainPath)?

Copy link
Collaborator Author

@phbnf phbnf Apr 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Been there: I can't do this because server.URL contains http://, which path.Join does not understand, it will remove a forward slash.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about url.JoinPath?

https://pkg.go.dev/net/url#JoinPath

func NewIssuerStorage(path string) (IssuersStorage, error) {
// Does nothing if the dictory already exists.
if err := os.MkdirAll(path, 0755); err != nil {
return "", fmt.Errorf("failed to create path %q: %w", path, err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need to wrap the err so the caller can determine something and react accordingly, or is %v ok?

Comment on lines 52 to 56
if strings.Contains(string(key), "/") {
return "", fmt.Errorf("key %q cannot contain '/'", string(key))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just flagging that this is potentially brittle for future uses if e.g. you decide to use this storage with base64 encoding for keys down the line.

Some filesystems might get upset with other unusual characters like \0, \\, or : too

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a package docstring, and expended this function docstring to highlight that this might not work on all filesystems, and that it's certainly not for production use.

Comment on lines 73 to 76
} else {
return fmt.Errorf("failed to read object %q: %w", objName, err)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need the indented else {} here since you'll either return or continue if errors.Is(os.ErrNotExist).

return fmt.Errorf("failed to read object %q: %w", objName, err)
}
} else if bytes.Equal(f, kv.V) {
klog.V(2).Infof("AddIssuersIfNotExist: object %q already exists, continuing", objName)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
klog.V(2).Infof("AddIssuersIfNotExist: object %q already exists, continuing", objName)
klog.V(2).Infof("AddIssuersIfNotExist: object %q already exists with identical contents, continuing", objName)

// - a POSIX Tessera storage driver
// - a POSIX issuer storage system
// - a BBolt deduplication database
func newPosixStorageFunc(t *testing.T) storage.CreateStorage {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -83,82 +79,129 @@ func (f *fixedTimeSource) Now() time.Time {
return f.fakeTime
}

// setupTest creates mock objects and contexts. Caller should invoke info.mockCtrl.Finish().
func setupTest(t *testing.T, pemRoots []string, signer crypto.Signer) handlerTestInfo {
// setupTestLog creates test TesseraCT log using a POSIX backend.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// setupTestLog creates test TesseraCT log using a POSIX backend.
// setupTestLog creates a test TesseraCT log using the POSIX backend.

rejectExpired: false,
roots := x509util.NewPEMCertPool()
if err := roots.AppendCertsFromPEMFile(testRootPath); err != nil {
t.Fatalf("failed to read trusted roots: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t.Fatalf("failed to read trusted roots: %v", err)
t.Fatalf("Failed to read trusted roots: %v", err)

Comment on lines 55 to 56
if strings.Contains(string(key), "/") {
return "", fmt.Errorf("key %q cannot contain '/'", string(key))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if strings.Contains(string(key), "/") {
return "", fmt.Errorf("key %q cannot contain '/'", string(key))
if strings.Contains(string(key), os.PathSeparator) {
return "", fmt.Errorf("key %q cannot contain '%s'", string(key), os.PathSeparator)

The / in test needs to be updated if this is updated.

https://pkg.go.dev/os#PathSeparator

@phbnf phbnf merged commit 0176f79 into transparency-dev:main Apr 4, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants