Skip to content

Commit 960165f

Browse files
committed
fix: suppress linker warnings, improve CI, and fix integration tests
- Add macOS linker flag to suppress duplicate library warnings - Add test-pure and setup targets to Makefile - Fix integration test to work without API key (tests local commands) - Add .env.example for environment configuration - Add setup.sh script for development environment setup - Move PATTERNS.md to docs/ directory
1 parent 7f77057 commit 960165f

6 files changed

Lines changed: 680 additions & 52 deletions

File tree

.env.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# CIMIS CLI Environment Configuration
2+
# Copy this file to .env and fill in your values
3+
4+
# CIMIS API App Key (required for fetching data)
5+
# Get yours at: https://cimis.water.ca.gov/Default.aspx
6+
CIMIS_APP_KEY=your-api-key-here
7+
8+
# Data directory path (optional, defaults to ./data)
9+
# CIMIS_DATA_DIR=./data
10+
11+
# Enable debug logging (optional)
12+
# CIMIS_DEBUG=true

Makefile

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
.PHONY: all build build-pure clean test bench fmt vet lint security checksums version c-lib deps format install-hooks
1+
.PHONY: all build build-pure clean test test-pure bench fmt vet lint security checksums version c-lib deps format install-hooks setup
22

33
# Build settings
44
BINARY_NAME=cimis
55
BUILD_DIR=./build
66
GO=go
77
CGO_ENABLED=1
88

9+
# macOS linker flag to suppress duplicate library warnings
10+
UNAME_S := $(shell uname -s)
11+
ifeq ($(UNAME_S),Darwin)
12+
CGO_LDFLAGS_EXTRA=-Wl,-no_warn_duplicate_libraries
13+
endif
14+
915
# C Library settings
1016
C_DIR=./c
1117
C_OBJ=$(C_DIR)/cimis_storage.o
@@ -28,7 +34,7 @@ $(C_LIB): $(C_DIR)/cimis_storage.c $(C_DIR)/cimis_storage.h
2834
# Build Go binary with C library
2935
build: $(C_LIB)
3036
@mkdir -p $(BUILD_DIR)
31-
CGO_ENABLED=$(CGO_ENABLED) CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage" \
37+
CGO_ENABLED=$(CGO_ENABLED) CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage $(CGO_LDFLAGS_EXTRA)" \
3238
$(GO) build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME) ./cmd/cimis
3339

3440
# Build without C library (pure Go, no C compiler required)
@@ -42,18 +48,26 @@ clean:
4248
@$(GO) clean
4349

4450
test:
45-
CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage" \
51+
CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage $(CGO_LDFLAGS_EXTRA)" \
4652
$(GO) test -v ./...
4753

54+
# Run tests without CGO (pure Go, no C compiler required)
55+
test-pure:
56+
CGO_ENABLED=0 $(GO) test -v ./internal/api/... ./internal/profile/...
57+
58+
# Setup development environment
59+
setup:
60+
@./scripts/setup.sh
61+
4862
bench:
49-
CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage" \
63+
CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage $(CGO_LDFLAGS_EXTRA)" \
5064
$(GO) test -bench=. -benchmem ./internal/...
5165

5266
fmt:
5367
$(GO) fmt ./...
5468

5569
vet:
56-
CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage" \
70+
CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage $(CGO_LDFLAGS_EXTRA)" \
5771
$(GO) vet ./...
5872

5973
lint:
@@ -72,7 +86,7 @@ security:
7286

7387
# Development helpers
7488
dev:
75-
CGO_ENABLED=$(CGO_ENABLED) CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage" \
89+
CGO_ENABLED=$(CGO_ENABLED) CGO_CFLAGS="-I$(PWD)/$(C_DIR)" CGO_LDFLAGS="-L$(PWD)/$(C_DIR) -lcimis_storage $(CGO_LDFLAGS_EXTRA)" \
7690
$(GO) run ./cmd/cimis
7791

7892
checksums:

cmd/cimis/integration_test.go

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,49 @@ import (
44
"os"
55
"os/exec"
66
"path/filepath"
7+
"runtime"
78
"strings"
89
"testing"
910
"time"
1011
)
1112

1213
// TestEndToEndIntegration performs a full integration test
1314
func TestEndToEndIntegration(t *testing.T) {
14-
// Skip if no API key available
15-
appKey := os.Getenv("CIMIS_APP_KEY")
16-
if appKey == "" {
17-
t.Skip("CIMIS_APP_KEY not set, skipping integration test")
18-
}
19-
2015
// Create temporary directory for test data
2116
tmpDir := t.TempDir()
2217
dataDir := filepath.Join(tmpDir, "data")
2318

24-
// Build CLI
19+
// Build CLI - get project root from current file location
20+
_, testFile, _, _ := runtime.Caller(0)
21+
projectRoot := filepath.Join(filepath.Dir(testFile), "..", "..")
22+
2523
cliPath := filepath.Join(tmpDir, "cimis")
26-
buildCmd := exec.Command("go", "build", "-o", cliPath, ".")
27-
buildCmd.Dir = ".." // Project root
24+
buildCmd := exec.Command("go", "build", "-o", cliPath, "./cmd/cimis")
25+
buildCmd.Dir = projectRoot
2826
if output, err := buildCmd.CombinedOutput(); err != nil {
2927
t.Fatalf("Failed to build CLI: %v\nOutput: %s", err, output)
3028
}
3129

30+
t.Run("Version", func(t *testing.T) {
31+
cmd := exec.Command(cliPath, "version")
32+
cmd.Dir = tmpDir
33+
34+
output, err := cmd.CombinedOutput()
35+
if err != nil {
36+
t.Fatalf("Version failed: %v\nOutput: %s", err, output)
37+
}
38+
39+
outputStr := string(output)
40+
if !strings.Contains(outputStr, "cimis") {
41+
t.Errorf("Expected 'cimis' in version output, got: %s", outputStr)
42+
}
43+
44+
t.Logf("Version output: %s", outputStr)
45+
})
46+
3247
t.Run("InitDatabase", func(t *testing.T) {
3348
cmd := exec.Command(cliPath, "init")
34-
cmd.Env = append(os.Environ(), "CIMIS_APP_KEY="+appKey)
49+
cmd.Env = os.Environ()
3550
cmd.Dir = tmpDir
3651

3752
output, err := cmd.CombinedOutput()
@@ -53,6 +68,48 @@ func TestEndToEndIntegration(t *testing.T) {
5368
t.Log("Database initialized successfully")
5469
})
5570

71+
t.Run("Stats", func(t *testing.T) {
72+
cmd := exec.Command(cliPath, "stats")
73+
cmd.Env = os.Environ()
74+
cmd.Dir = tmpDir
75+
76+
output, err := cmd.CombinedOutput()
77+
if err != nil {
78+
t.Fatalf("Stats failed: %v\nOutput: %s", err, output)
79+
}
80+
81+
outputStr := string(output)
82+
if !strings.Contains(outputStr, "Statistics") {
83+
t.Errorf("Expected 'Statistics' in output, got: %s", outputStr)
84+
}
85+
86+
t.Logf("Stats output: %s", outputStr)
87+
})
88+
89+
t.Run("Verify", func(t *testing.T) {
90+
cmd := exec.Command(cliPath, "verify")
91+
cmd.Env = os.Environ()
92+
cmd.Dir = tmpDir
93+
94+
output, err := cmd.CombinedOutput()
95+
if err != nil {
96+
t.Fatalf("Verify failed: %v\nOutput: %s", err, output)
97+
}
98+
99+
outputStr := string(output)
100+
if !strings.Contains(outputStr, "OK") && !strings.Contains(outputStr, "complete") && !strings.Contains(outputStr, "verified") {
101+
t.Errorf("Expected verification result in output, got: %s", outputStr)
102+
}
103+
104+
t.Logf("Verify output: %s", outputStr)
105+
})
106+
107+
// Skip API-dependent tests if no key is available
108+
appKey := os.Getenv("CIMIS_APP_KEY")
109+
if appKey == "" {
110+
t.Skip("Skipping API-dependent tests - CIMIS_APP_KEY not set")
111+
}
112+
56113
t.Run("FetchData", func(t *testing.T) {
57114
cmd := exec.Command(cliPath, "fetch", "-station", "2", "-days", "7")
58115
cmd.Env = append(os.Environ(), "CIMIS_APP_KEY="+appKey)
@@ -123,42 +180,6 @@ func TestEndToEndIntegration(t *testing.T) {
123180

124181
t.Logf("Query output: %s", outputStr)
125182
})
126-
127-
t.Run("Stats", func(t *testing.T) {
128-
cmd := exec.Command(cliPath, "stats")
129-
cmd.Env = append(os.Environ(), "CIMIS_APP_KEY="+appKey)
130-
cmd.Dir = tmpDir
131-
132-
output, err := cmd.CombinedOutput()
133-
if err != nil {
134-
t.Fatalf("Stats failed: %v\nOutput: %s", err, output)
135-
}
136-
137-
outputStr := string(output)
138-
if !strings.Contains(outputStr, "Statistics") {
139-
t.Errorf("Expected 'Statistics' in output, got: %s", outputStr)
140-
}
141-
142-
t.Logf("Stats output: %s", outputStr)
143-
})
144-
145-
t.Run("Verify", func(t *testing.T) {
146-
cmd := exec.Command(cliPath, "verify")
147-
cmd.Env = append(os.Environ(), "CIMIS_APP_KEY="+appKey)
148-
cmd.Dir = tmpDir
149-
150-
output, err := cmd.CombinedOutput()
151-
if err != nil {
152-
t.Fatalf("Verify failed: %v\nOutput: %s", err, output)
153-
}
154-
155-
outputStr := string(output)
156-
if !strings.Contains(outputStr, "OK") && !strings.Contains(outputStr, "complete") {
157-
t.Errorf("Expected verification result in output, got: %s", outputStr)
158-
}
159-
160-
t.Logf("Verify output: %s", outputStr)
161-
})
162183
}
163184

164185
// TestCompressionBenchmarks runs benchmarks and validates performance

0 commit comments

Comments
 (0)