@@ -2,8 +2,12 @@ package cmd
22
33import (
44 "bytes"
5+ "dnsmag/internal"
6+ "encoding/json"
7+ "fmt"
58 "os"
69 "regexp"
10+ "strings"
711 "testing"
812)
913
@@ -62,6 +66,194 @@ func TestViewCmd_Integration(t *testing.T) {
6266 t .Logf ("View command output:\n %s" , output )
6367}
6468
69+ func TestViewCmd_JSON (t * testing.T ) {
70+ // Create temporary DNSMAG file
71+ tmpDnsmag , err := os .CreateTemp ("" , "test_view_json_*.dnsmag" )
72+ if err != nil {
73+ t .Fatalf ("Failed to create temp DNSMAG file: %v" , err )
74+ }
75+ defer os .Remove (tmpDnsmag .Name ())
76+ tmpDnsmag .Close ()
77+
78+ // Collect data into temporary DNSMAG file
79+ executeCollectAndVerify (t , []string {
80+ "../../testdata/test1.pcap.gz" ,
81+ "--output" , tmpDnsmag .Name (),
82+ }, 100 , "PCAP" )
83+
84+ // View the data with JSON output
85+ viewCmd := newViewCmd ()
86+ viewCmd .SetArgs ([]string {
87+ tmpDnsmag .Name (),
88+ "--json" ,
89+ })
90+
91+ var viewBuf bytes.Buffer
92+ viewCmd .SetOut (& viewBuf )
93+ viewCmd .SetErr (& viewBuf )
94+
95+ err = viewCmd .Execute ()
96+ if err != nil {
97+ t .Fatalf ("View command with --json failed: %v\n Output: %s" , err , viewBuf .String ())
98+ }
99+
100+ output := viewBuf .String ()
101+
102+ // Parse JSON output
103+ var stats internal.DatasetStatsJSON
104+ if err := json .Unmarshal (viewBuf .Bytes (), & stats ); err != nil {
105+ t .Fatalf ("Failed to parse JSON output: %v\n Output: %s" , err , output )
106+ }
107+
108+ // Verify ID is non-empty before overwriting
109+ if stats .DatasetStatistics .ID == "" {
110+ t .Error ("Expected non-empty ID" )
111+ }
112+
113+ // Overwrite random ID field for comparison
114+ stats .DatasetStatistics .ID = ""
115+
116+ expected := internal.DatasetStatsJSON {
117+ DatasetStatistics : internal.DatasetStats {
118+ ID : "" ,
119+ Generator : fmt .Sprintf ("dnsmag %s" , internal .Version ),
120+ Date : "2000-01-01" ,
121+ TotalUniqueClients : 70 ,
122+ TotalQueryVolume : 100 ,
123+ TotalDomainCount : 4 ,
124+ },
125+ }
126+
127+ if stats != expected {
128+ t .Errorf ("JSON output mismatch.\n Got: %+v\n Expected: %+v" , stats , expected )
129+ }
130+
131+ t .Logf ("View --json output:\n %s" , output )
132+ }
133+
134+ func TestViewCmd_OutputDestination (t * testing.T ) {
135+ // Create temporary DNSMAG file
136+ tmpDnsmag , err := os .CreateTemp ("" , "test_view_output_*.dnsmag" )
137+ if err != nil {
138+ t .Fatalf ("Failed to create temp DNSMAG file: %v" , err )
139+ }
140+ defer os .Remove (tmpDnsmag .Name ())
141+ tmpDnsmag .Close ()
142+
143+ // Collect data into temporary DNSMAG file
144+ executeCollectAndVerify (t , []string {
145+ "../../testdata/test1.pcap.gz" ,
146+ "--output" , tmpDnsmag .Name (),
147+ }, 100 , "PCAP" )
148+
149+ tests := []struct {
150+ name string
151+ outputFlag string
152+ jsonFlag bool
153+ expectIn string // "stdout", "stderr", or "file"
154+ searchString string
155+ }{
156+ {
157+ name : "text output to stderr (default)" ,
158+ outputFlag : "" ,
159+ jsonFlag : false ,
160+ expectIn : "stderr" ,
161+ searchString : "Dataset statistics" ,
162+ },
163+ {
164+ name : "text output to file" ,
165+ outputFlag : "output.txt" ,
166+ jsonFlag : false ,
167+ expectIn : "file" ,
168+ searchString : "Dataset statistics" ,
169+ },
170+ {
171+ name : "text output to stdout" ,
172+ outputFlag : "-" ,
173+ jsonFlag : false ,
174+ expectIn : "stdout" ,
175+ searchString : "Dataset statistics" ,
176+ },
177+ {
178+ name : "JSON output to stderr (default)" ,
179+ outputFlag : "" ,
180+ jsonFlag : true ,
181+ expectIn : "stderr" ,
182+ searchString : "datasetStatistics" ,
183+ },
184+ {
185+ name : "JSON output to file" ,
186+ outputFlag : "output.json" ,
187+ jsonFlag : true ,
188+ expectIn : "file" ,
189+ searchString : "datasetStatistics" ,
190+ },
191+ {
192+ name : "JSON output to stdout" ,
193+ outputFlag : "-" ,
194+ jsonFlag : true ,
195+ expectIn : "stdout" ,
196+ searchString : "datasetStatistics" ,
197+ },
198+ }
199+
200+ for _ , tt := range tests {
201+ t .Run (tt .name , func (t * testing.T ) {
202+ viewCmd := newViewCmd ()
203+ args := []string {tmpDnsmag .Name ()}
204+ if tt .jsonFlag {
205+ args = append (args , "--json" )
206+ }
207+
208+ var outputPath string
209+ if tt .outputFlag != "" {
210+ if tt .expectIn == "file" {
211+ tmpFile , err := os .CreateTemp ("" , tt .outputFlag )
212+ if err != nil {
213+ t .Fatalf ("Failed to create temp file: %v" , err )
214+ }
215+ outputPath = tmpFile .Name ()
216+ tmpFile .Close ()
217+ defer os .Remove (outputPath )
218+ args = append (args , "--output" , outputPath )
219+ } else {
220+ args = append (args , "--output" , tt .outputFlag )
221+ }
222+ }
223+ viewCmd .SetArgs (args )
224+
225+ var stdout , stderr bytes.Buffer
226+ viewCmd .SetOut (& stdout )
227+ viewCmd .SetErr (& stderr )
228+
229+ err := viewCmd .Execute ()
230+ if err != nil {
231+ t .Fatalf ("View command failed: %v\n Stdout: %s\n Stderr: %s" , err , stdout .String (), stderr .String ())
232+ }
233+
234+ // Check output appears in expected location
235+ switch tt .expectIn {
236+ case "stdout" :
237+ if ! strings .Contains (stdout .String (), tt .searchString ) {
238+ t .Errorf ("Expected %q in stdout" , tt .searchString )
239+ }
240+ case "stderr" :
241+ if ! strings .Contains (stderr .String (), tt .searchString ) {
242+ t .Errorf ("Expected %q in stderr" , tt .searchString )
243+ }
244+ case "file" :
245+ fileContent , err := os .ReadFile (outputPath )
246+ if err != nil {
247+ t .Fatalf ("Failed to read output file: %v" , err )
248+ }
249+ if ! strings .Contains (string (fileContent ), tt .searchString ) {
250+ t .Errorf ("Expected %q in file" , tt .searchString )
251+ }
252+ }
253+ })
254+ }
255+ }
256+
65257func TestViewCmd_NonExistentFile (t * testing.T ) {
66258 viewCmd := newViewCmd ()
67259 viewCmd .SetArgs ([]string {"non-existent.dnsmag" })
0 commit comments