-
Notifications
You must be signed in to change notification settings - Fork 0
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
[csr] add private_server
certificate type
#2
base: master
Are you sure you want to change the base?
Conversation
WalkthroughThe changes update the dependency version in the Changes
Sequence Diagram(s)sequenceDiagram
participant C as Client
participant H as CSR Handler (API)
participant D as CSR Domain
participant S as Service
participant R as Repository
C->>H: POST /csr (payload with "type", content, metadata)
H->>D: Call csr.NewCSR(csrType, content, metadata)
D-->>H: New CSR instance
H->>S: Call Service.Create(new CSR)
S->>S: Process CSR
S->>S: Retrieve prefix using csrTypeToPrefix mapping
S->>S: Call newSerialNumber(prefix) to generate serial number
S->>D: Call NewCSRStatus(id, csrType, content, metadata, status, certificate, reason)
D-->>S: Return CSR status
S-->>H: Return CSR status
H->>H: Convert status via csrStatusToResponse
H-->>C: Return JSON response
sequenceDiagram
participant C as Client
participant H as CSR Handler (API)
participant R as Repository
C->>H: GET /csr/{id}
H->>R: Call Repository.Get(id)
R->>R: Retrieve record and call NewCSRStatus (with csrType)
R-->>H: Return CSR status object
H->>H: Convert status via csrStatusToResponse
H-->>C: Return JSON response
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
@coderabbitai generate unit testing code for this file.
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.
@capcom6 Here's a comprehensive unit test file for internal/csr/domain.go
:
package csr
import (
"encoding/json"
"testing"
"github.com/android-sms-gateway/client-go/ca"
"github.com/stretchr/testify/assert"
)
func TestNewCSR(t *testing.T) {
tests := []struct {
name string
csrType ca.CSRType
content string
metadata map[string]string
want CSR
}{
{
name: "With type provided",
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: map[string]string{"key": "value"},
want: CSR{
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: map[string]string{"key": "value"},
},
},
{
name: "With empty type",
csrType: "",
content: "test-content",
metadata: map[string]string{"key": "value"},
want: CSR{
csrType: ca.CSRTypeWebhook,
content: "test-content",
metadata: map[string]string{"key": "value"},
},
},
{
name: "With empty metadata",
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: nil,
want: CSR{
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := NewCSR(tt.csrType, tt.content, tt.metadata)
assert.Equal(t, tt.want, got)
})
}
}
func TestCSR_Type(t *testing.T) {
csr := CSR{
csrType: ca.CSRType("private_server"),
}
assert.Equal(t, ca.CSRType("private_server"), csr.Type())
}
func TestCSR_Content(t *testing.T) {
csr := CSR{
content: "test-content",
}
assert.Equal(t, "test-content", csr.Content())
}
func TestCSR_Metadata(t *testing.T) {
metadata := map[string]string{"key": "value"}
csr := CSR{
metadata: metadata,
}
assert.Equal(t, metadata, csr.Metadata())
}
func TestCSR_toMap(t *testing.T) {
tests := []struct {
name string
csr CSR
expected map[string]string
}{
{
name: "With metadata",
csr: CSR{
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: map[string]string{"key": "value"},
},
expected: map[string]string{
"type": "private_server",
"content": "test-content",
"metadata": `{"key":"value"}`,
},
},
{
name: "Without metadata",
csr: CSR{
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: map[string]string{},
},
expected: map[string]string{
"type": "private_server",
"content": "test-content",
"metadata": "{}",
},
},
{
name: "With nil metadata",
csr: CSR{
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: nil,
},
expected: map[string]string{
"type": "private_server",
"content": "test-content",
"metadata": "{}",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.csr.toMap()
// Check that maps have the same keys and values
assert.Equal(t, tt.expected, result)
// For metadata, verify it's valid JSON
if metadataJSON, exists := result["metadata"]; exists {
var metadataMap map[string]string
err := json.Unmarshal([]byte(metadataJSON), &metadataMap)
assert.NoError(t, err, "Metadata should be valid JSON")
// If the original metadata was not nil or empty, verify the unmarshaled content
if tt.csr.metadata != nil && len(tt.csr.metadata) > 0 {
assert.Equal(t, tt.csr.metadata, metadataMap)
}
}
})
}
}
func TestNewCSRStatus(t *testing.T) {
id := "test-id"
csrType := ca.CSRType("private_server")
content := "test-content"
metadata := map[string]string{"key": "value"}
status := ca.CSRStatus("pending")
certificate := "test-certificate"
reason := "test-reason"
csrStatus := NewCSRStatus(id, csrType, content, metadata, status, certificate, reason)
assert.Equal(t, id, csrStatus.id)
assert.Equal(t, csrType, csrStatus.csrType)
assert.Equal(t, content, csrStatus.content)
assert.Equal(t, metadata, csrStatus.metadata)
assert.Equal(t, status, csrStatus.status)
assert.Equal(t, certificate, csrStatus.certificate)
assert.Equal(t, reason, csrStatus.reason)
}
func TestCSRStatus_ID(t *testing.T) {
csrStatus := CSRStatus{id: "test-id"}
assert.Equal(t, "test-id", csrStatus.ID())
}
func TestCSRStatus_Status(t *testing.T) {
csrStatus := CSRStatus{status: ca.CSRStatus("approved")}
assert.Equal(t, ca.CSRStatus("approved"), csrStatus.Status())
}
func TestCSRStatus_Certificate(t *testing.T) {
csrStatus := CSRStatus{certificate: "test-certificate"}
assert.Equal(t, "test-certificate", csrStatus.Certificate())
}
func TestCsrID_Bytes(t *testing.T) {
id := csrID("test-id")
expected := []byte("test-id")
assert.Equal(t, expected, id.Bytes())
}
This test file provides complete coverage for all the structs and functions in the domain.go file, including:
- Testing the CSR constructor with various inputs
- Testing all getter methods
- Testing the toMap method with different metadata scenarios
- Testing the CSRStatus constructor and its methods
- Testing the csrID type's Bytes method
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.
@coderabbitai, please use csr_test
package and test only public methods and fields
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.
@capcom6 Here's the updated unit test code using the csr_test
package and testing only public methods:
package csr_test
import (
"testing"
"github.com/android-sms-gateway/ca-backend/internal/csr"
"github.com/android-sms-gateway/client-go/ca"
"github.com/stretchr/testify/assert"
)
func TestNewCSR(t *testing.T) {
tests := []struct {
name string
csrType ca.CSRType
content string
metadata map[string]string
}{
{
name: "With type provided",
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: map[string]string{"key": "value"},
},
{
name: "With empty type",
csrType: "",
content: "test-content",
metadata: map[string]string{"key": "value"},
},
{
name: "With empty metadata",
csrType: ca.CSRType("private_server"),
content: "test-content",
metadata: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := csr.NewCSR(tt.csrType, tt.content, tt.metadata)
// Check type (should default to webhook if empty)
expectedType := tt.csrType
if expectedType == "" {
expectedType = ca.CSRTypeWebhook
}
assert.Equal(t, expectedType, got.Type())
// Check content and metadata
assert.Equal(t, tt.content, got.Content())
assert.Equal(t, tt.metadata, got.Metadata())
})
}
}
func TestCSR_Getters(t *testing.T) {
csrType := ca.CSRType("private_server")
content := "test-content"
metadata := map[string]string{"key": "value"}
testCSR := csr.NewCSR(csrType, content, metadata)
assert.Equal(t, csrType, testCSR.Type())
assert.Equal(t, content, testCSR.Content())
assert.Equal(t, metadata, testCSR.Metadata())
}
func TestNewCSRStatus(t *testing.T) {
id := "test-id"
csrType := ca.CSRType("private_server")
content := "test-content"
metadata := map[string]string{"key": "value"}
status := ca.CSRStatus("pending")
certificate := "test-certificate"
reason := "test-reason"
csrStatus := csr.NewCSRStatus(id, csrType, content, metadata, status, certificate, reason)
// Verify through public getters
assert.Equal(t, id, csrStatus.ID())
assert.Equal(t, csrType, csrStatus.Type())
assert.Equal(t, content, csrStatus.Content())
assert.Equal(t, metadata, csrStatus.Metadata())
assert.Equal(t, status, csrStatus.Status())
assert.Equal(t, certificate, csrStatus.Certificate())
}
func TestCSRStatus_Getters(t *testing.T) {
id := "test-id"
csrType := ca.CSRType("private_server")
content := "test-content"
metadata := map[string]string{"key": "value"}
status := ca.CSRStatus("approved")
certificate := "test-certificate"
reason := "test-reason"
csrStatus := csr.NewCSRStatus(id, csrType, content, metadata, status, certificate, reason)
assert.Equal(t, id, csrStatus.ID())
assert.Equal(t, status, csrStatus.Status())
assert.Equal(t, certificate, csrStatus.Certificate())
}
This test file adheres to black-box testing principles by using the csr_test
package and only testing public methods. We verify the functionality by calling public constructors and getter methods rather than accessing internal fields directly.
✏️ Learnings added
Learnt from: capcom6
PR: android-sms-gateway/ca-backend#2
File: internal/csr/domain.go:1-1
Timestamp: 2025-03-07T23:33:54.409Z
Learning: When writing unit tests for Go packages, use a `package_test` naming convention for black-box testing where only public (exported) methods and fields can be tested. This provides better validation of the public API's behavior.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
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.
Actionable comments posted: 0
🧹 Nitpick comments (4)
internal/csr/domain_test.go (4)
88-102
: TestCSRStatus_Getters is incompleteThis test only verifies a subset of the getters (ID, status, and certificate) but omits validation for Type(), Content(), Metadata(), and possibly Reason(). Consider extending this test to cover all getters or explain why only some are being tested.
func TestCSRStatus_Getters(t *testing.T) { id := "test-id" csrType := ca.CSRType("private_server") content := "test-content" metadata := map[string]string{"key": "value"} status := ca.CSRStatus("approved") certificate := "test-certificate" reason := "test-reason" csrStatus := csr.NewCSRStatus(id, csrType, content, metadata, status, certificate, reason) assert.Equal(t, id, csrStatus.ID()) + assert.Equal(t, csrType, csrStatus.Type()) + assert.Equal(t, content, csrStatus.Content()) + assert.Equal(t, metadata, csrStatus.Metadata()) assert.Equal(t, status, csrStatus.Status()) assert.Equal(t, certificate, csrStatus.Certificate()) + // If Reason getter exists + // assert.Equal(t, reason, csrStatus.Reason()) }
11-54
: Add negative test cases to TestNewCSRThe current tests only cover valid inputs. Consider adding tests for potential error cases or edge cases such as invalid CSR types to ensure robust validation.
func TestNewCSR(t *testing.T) { tests := []struct { name string csrType ca.CSRType content string metadata map[string]string }{ { name: "With type provided", csrType: ca.CSRTypePrivateServer, content: "test-content", metadata: map[string]string{"key": "value"}, }, { name: "With empty type", csrType: "", content: "test-content", metadata: map[string]string{"key": "value"}, }, { name: "With empty metadata", csrType: ca.CSRTypePrivateServer, content: "test-content", metadata: nil, }, + { + name: "With empty content", + csrType: ca.CSRTypePrivateServer, + content: "", + metadata: map[string]string{"key": "value"}, + }, + { + name: "With invalid CSR type", + csrType: "invalid_type", + content: "test-content", + metadata: map[string]string{"key": "value"}, + }, }
1-9
: Consider using testify for more assertion optionsThe current tests use
github.com/go-playground/assert/v2
, butgithub.com/stretchr/testify/assert
offers a wider range of assertion functions and is more commonly used in Go projects. Consider standardizing the assertion library across the project.
56-66
: TestCSR_Getters duplicates functionality already tested in TestNewCSRThis test largely duplicates what's already being tested in TestNewCSR. Consider either merging them or making this test focus on different aspects not covered by the table-driven tests.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
go.sum
is excluded by!**/*.sum
📒 Files selected for processing (2)
go.mod
(1 hunks)internal/csr/domain_test.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- go.mod
🔇 Additional comments (1)
internal/csr/domain_test.go (1)
68-86
:❓ Verification inconclusive
TestNewCSRStatus doesn't validate the reason getter
The test creates a CSRStatus with a reason parameter but doesn't verify it with an assertion. Consider adding an assertion to validate that the reason is properly stored and retrieved.
🏁 Script executed:
#!/bin/bash # Check if CSRStatus has a Reason getter method rg -A 1 -B 1 "func \(\w+ \*CSRStatus\) Reason\(\) string" internal/csr/domain.goLength of output: 82
Attention: Verify and Validate the "reason" Field in CSRStatus
The test currently creates a CSRStatus with a "reason" parameter but does not assert its retrieval. Our initial search in
internal/csr/domain.go
did not reveal a publicReason()
getter for CSRStatus. Please verify whether:
- The CSRStatus type is intended to expose a "reason" field through a public getter.
- If the getter is missing, either add the
Reason() string
method to CSRStatus or remove the unused "reason" parameter fromNewCSRStatus
.- If the getter exists (perhaps under a different pattern or in another part of the code), update
TestNewCSRStatus
to include an assertion for it.
Summary by CodeRabbit
New Features
Enhancements
Tests