@@ -235,24 +235,129 @@ func TestExecuteTerraformQueryNoMatches(t *testing.T) {
235235
236236// TestWalkTerraformComponents verifies that walkTerraformComponents iterates over all components.
237237func TestWalkTerraformComponents (t * testing.T ) {
238- stacks := map [string ]any {
239- "stack1" : map [string ]any {
240- cfg .ComponentsSectionName : map [string ]any {
241- cfg .TerraformSectionName : map [string ]any {
242- "comp1" : map [string ]any {},
243- "comp2" : map [string ]any {},
238+ t .Run ("iterates all components" , func (t * testing.T ) {
239+ stacks := map [string ]any {
240+ "stack1" : map [string ]any {
241+ cfg .ComponentsSectionName : map [string ]any {
242+ cfg .TerraformSectionName : map [string ]any {
243+ "comp1" : map [string ]any {},
244+ "comp2" : map [string ]any {},
245+ },
244246 },
245247 },
246- },
247- }
248+ }
249+
250+ var visited []string
251+ err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
252+ visited = append (visited , stack + "-" + comp )
253+ return nil
254+ })
255+ assert .NoError (t , err )
256+ assert .ElementsMatch (t , []string {"stack1-comp1" , "stack1-comp2" }, visited )
257+ })
258+
259+ t .Run ("propagates callback error" , func (t * testing.T ) {
260+ stacks := map [string ]any {
261+ "stack1" : map [string ]any {
262+ cfg .ComponentsSectionName : map [string ]any {
263+ cfg .TerraformSectionName : map [string ]any {
264+ "comp1" : map [string ]any {},
265+ },
266+ },
267+ },
268+ }
269+
270+ expectedErr := assert .AnError
271+ err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
272+ return expectedErr
273+ })
274+ assert .Error (t , err )
275+ assert .Equal (t , expectedErr , err )
276+ })
277+
278+ t .Run ("skips invalid stack section type" , func (t * testing.T ) {
279+ stacks := map [string ]any {
280+ "stack1" : "not-a-map" ,
281+ }
282+
283+ var visited []string
284+ err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
285+ visited = append (visited , stack + "-" + comp )
286+ return nil
287+ })
288+ assert .NoError (t , err )
289+ assert .Empty (t , visited )
290+ })
291+
292+ t .Run ("skips invalid components section type" , func (t * testing.T ) {
293+ stacks := map [string ]any {
294+ "stack1" : map [string ]any {
295+ cfg .ComponentsSectionName : "not-a-map" ,
296+ },
297+ }
298+
299+ var visited []string
300+ err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
301+ visited = append (visited , stack + "-" + comp )
302+ return nil
303+ })
304+ assert .NoError (t , err )
305+ assert .Empty (t , visited )
306+ })
307+
308+ t .Run ("skips invalid terraform section type" , func (t * testing.T ) {
309+ stacks := map [string ]any {
310+ "stack1" : map [string ]any {
311+ cfg .ComponentsSectionName : map [string ]any {
312+ cfg .TerraformSectionName : "not-a-map" ,
313+ },
314+ },
315+ }
316+
317+ var visited []string
318+ err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
319+ visited = append (visited , stack + "-" + comp )
320+ return nil
321+ })
322+ assert .NoError (t , err )
323+ assert .Empty (t , visited )
324+ })
325+
326+ t .Run ("skips invalid component section type" , func (t * testing.T ) {
327+ stacks := map [string ]any {
328+ "stack1" : map [string ]any {
329+ cfg .ComponentsSectionName : map [string ]any {
330+ cfg .TerraformSectionName : map [string ]any {
331+ "comp1" : "not-a-map" ,
332+ },
333+ },
334+ },
335+ }
248336
249- var visited []string
250- err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
251- visited = append (visited , stack + "-" + comp )
252- return nil
337+ var visited []string
338+ err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
339+ visited = append (visited , stack + "-" + comp )
340+ return nil
341+ })
342+ assert .NoError (t , err )
343+ assert .Empty (t , visited )
344+ })
345+
346+ t .Run ("skips missing components section" , func (t * testing.T ) {
347+ stacks := map [string ]any {
348+ "stack1" : map [string ]any {
349+ "other_key" : "value" ,
350+ },
351+ }
352+
353+ var visited []string
354+ err := walkTerraformComponents (stacks , func (stack , comp string , section map [string ]any ) error {
355+ visited = append (visited , stack + "-" + comp )
356+ return nil
357+ })
358+ assert .NoError (t , err )
359+ assert .Empty (t , visited )
253360 })
254- assert .NoError (t , err )
255- assert .ElementsMatch (t , []string {"stack1-comp1" , "stack1-comp2" }, visited )
256361}
257362
258363// TestProcessTerraformComponent exercises the filtering logic of processTerraformComponent.
@@ -271,6 +376,45 @@ func TestProcessTerraformComponent(t *testing.T) {
271376 }
272377 }
273378
379+ t .Run ("no metadata section" , func (t * testing.T ) {
380+ // Section without metadata should return false, nil.
381+ section := map [string ]any {
382+ "vars" : map [string ]any {"key" : "value" },
383+ }
384+ called := false
385+ patch := gomonkey .ApplyFunc (ExecuteTerraform , func (i schema.ConfigAndStacksInfo ) error {
386+ called = true
387+ return nil
388+ })
389+ defer patch .Reset ()
390+
391+ info := schema.ConfigAndStacksInfo {SubCommand : "plan" }
392+ processed , err := processTerraformComponent (& atmosConfig , & info , stack , component , section , logFunc )
393+ assert .NoError (t , err )
394+ assert .False (t , processed )
395+ assert .False (t , called )
396+ })
397+
398+ t .Run ("metadata wrong type" , func (t * testing.T ) {
399+ // Section with metadata of wrong type should return false, nil.
400+ section := map [string ]any {
401+ cfg .MetadataSectionName : "string-not-map" ,
402+ "vars" : map [string ]any {"key" : "value" },
403+ }
404+ called := false
405+ patch := gomonkey .ApplyFunc (ExecuteTerraform , func (i schema.ConfigAndStacksInfo ) error {
406+ called = true
407+ return nil
408+ })
409+ defer patch .Reset ()
410+
411+ info := schema.ConfigAndStacksInfo {SubCommand : "plan" }
412+ processed , err := processTerraformComponent (& atmosConfig , & info , stack , component , section , logFunc )
413+ assert .NoError (t , err )
414+ assert .False (t , processed )
415+ assert .False (t , called )
416+ })
417+
274418 t .Run ("abstract" , func (t * testing.T ) {
275419 section := newSection (map [string ]any {"type" : "abstract" })
276420 called := false
@@ -353,6 +497,29 @@ func TestProcessTerraformComponent(t *testing.T) {
353497 assert .True (t , processed ) // Returns true in dry-run mode.
354498 assert .False (t , called ) // But doesn't call ExecuteTerraform.
355499 })
500+
501+ t .Run ("execute returns error" , func (t * testing.T ) {
502+ section := newSection (map [string ]any {"enabled" : true })
503+ expectedErr := assert .AnError
504+ called := false
505+ patch := gomonkey .ApplyFunc (ExecuteTerraform , func (i schema.ConfigAndStacksInfo ) error {
506+ called = true
507+ return expectedErr
508+ })
509+ defer patch .Reset ()
510+
511+ info := schema.ConfigAndStacksInfo {SubCommand : "plan" }
512+ processed , err := processTerraformComponent (& atmosConfig , & info , stack , component , section , logFunc )
513+
514+ // If gomonkey didn't work (common on macOS), skip the test.
515+ if ! called {
516+ t .Skip ("gomonkey function mocking failed (likely due to platform issues)" )
517+ }
518+
519+ assert .Error (t , err )
520+ assert .True (t , processed )
521+ assert .True (t , called )
522+ })
356523}
357524
358525func TestCheckTerraformConfig (t * testing.T ) {
0 commit comments