4141main (void ) {
4242 int rc = 0 ;
4343
44- dsd_opts opts ;
45- memset (& opts , 0 , sizeof (opts ));
44+ // dsd_opts is sizeable enough to keep off the function stack in tests.
45+ dsd_opts * opts = (dsd_opts * )calloc (1 , sizeof (* opts ));
46+ if (!opts ) {
47+ fprintf (stderr , "alloc-failed: dsd_opts\n" );
48+ return 1 ;
49+ }
4650
4751 dsd_state * st = (dsd_state * )calloc (1 , sizeof (* st ));
4852 if (!st ) {
4953 fprintf (stderr , "alloc-failed: dsd_state\n" );
54+ free (opts );
5055 return 1 ;
5156 }
5257
@@ -56,45 +61,45 @@ main(void) {
5661 set_group (st , 1 , 200UL , "B" , "BLOCK" );
5762 {
5863 int outL = -1 , outR = -1 ;
59- rc |= expect_eq ("case1-ret" , dsd_audio_group_gate_dual (& opts , st , 100UL , 200UL , 0 , 0 , & outL , & outR ), 0 );
64+ rc |= expect_eq ("case1-ret" , dsd_audio_group_gate_dual (opts , st , 100UL , 200UL , 0 , 0 , & outL , & outR ), 0 );
6065 rc |= expect_eq ("case1-outL" , outL , 0 );
6166 rc |= expect_eq ("case1-outR" , outR , 1 );
6267 }
6368
6469 // Case 2: Allow-list mode defaults unknown TGs to blocked.
65- memset (& opts , 0 , sizeof (opts ));
70+ memset (opts , 0 , sizeof (* opts ));
6671 memset (st , 0 , sizeof (* st ));
67- opts . trunk_use_allow_list = 1 ;
72+ opts -> trunk_use_allow_list = 1 ;
6873 st -> group_tally = 1 ;
6974 set_group (st , 0 , 300UL , "A" , "ONLY" );
7075 {
7176 int outL = -1 , outR = -1 ;
72- rc |= expect_eq ("case2-ret" , dsd_audio_group_gate_dual (& opts , st , 300UL , 301UL , 0 , 0 , & outL , & outR ), 0 );
77+ rc |= expect_eq ("case2-ret" , dsd_audio_group_gate_dual (opts , st , 300UL , 301UL , 0 , 0 , & outL , & outR ), 0 );
7378 rc |= expect_eq ("case2-outL" , outL , 0 );
7479 rc |= expect_eq ("case2-outR" , outR , 1 );
7580 }
7681
7782 // Case 2b: "DE" lockout mode should be treated as blocked by audio gate.
78- memset (& opts , 0 , sizeof (opts ));
83+ memset (opts , 0 , sizeof (* opts ));
7984 memset (st , 0 , sizeof (* st ));
8085 st -> group_tally = 1 ;
8186 set_group (st , 0 , 310UL , "DE" , "ENC-LOCKOUT" );
8287 {
8388 int outL = -1 ;
84- rc |= expect_eq ("case2b-ret" , dsd_audio_group_gate_mono (& opts , st , 310UL , 0 , & outL ), 0 );
89+ rc |= expect_eq ("case2b-ret" , dsd_audio_group_gate_mono (opts , st , 310UL , 0 , & outL ), 0 );
8590 rc |= expect_eq ("case2b-outL" , outL , 1 );
8691 }
8792
8893 // Case 3: TG hold mutes non-matching slot and force-unmutes matching slot.
89- memset (& opts , 0 , sizeof (opts ));
94+ memset (opts , 0 , sizeof (* opts ));
9095 memset (st , 0 , sizeof (* st ));
9196 st -> group_tally = 2 ;
9297 set_group (st , 0 , 400UL , "A" , "LEFT" );
9398 set_group (st , 1 , 401UL , "B" , "RIGHT-BLOCKED" );
9499 st -> tg_hold = 401U ;
95100 {
96101 int outL = -1 , outR = -1 ;
97- rc |= expect_eq ("case3-ret" , dsd_audio_group_gate_dual (& opts , st , 400UL , 401UL , 0 , 0 , & outL , & outR ), 0 );
102+ rc |= expect_eq ("case3-ret" , dsd_audio_group_gate_dual (opts , st , 400UL , 401UL , 0 , 0 , & outL , & outR ), 0 );
98103 rc |= expect_eq ("case3-outL" , outL , 1 );
99104 rc |= expect_eq ("case3-outR" , outR , 0 );
100105 }
@@ -103,27 +108,27 @@ main(void) {
103108 {
104109 int out = 0 ;
105110 rc |= expect_eq ("null-mono" , dsd_audio_group_gate_mono (NULL , st , 0UL , 0 , & out ), -1 );
106- rc |= expect_eq ("null-dual" , dsd_audio_group_gate_dual (& opts , st , 0UL , 0UL , 0 , 0 , NULL , & out ), -1 );
107- rc |= expect_eq ("null-record-mono" , dsd_audio_record_gate_mono (& opts , NULL , & out ), -1 );
111+ rc |= expect_eq ("null-dual" , dsd_audio_group_gate_dual (opts , st , 0UL , 0UL , 0 , 0 , NULL , & out ), -1 );
112+ rc |= expect_eq ("null-record-mono" , dsd_audio_record_gate_mono (opts , NULL , & out ), -1 );
108113 }
109114
110115 // Case 4: Mono per-call recording gate respects block mode.
111- memset (& opts , 0 , sizeof (opts ));
116+ memset (opts , 0 , sizeof (* opts ));
112117 memset (st , 0 , sizeof (* st ));
113118 st -> group_tally = 1 ;
114119 st -> lasttg = 500UL ;
115120 st -> dmr_encL = 0 ;
116121 set_group (st , 0 , 500UL , "B" , "REC-BLOCK" );
117122 {
118123 int allow = -1 ;
119- rc |= expect_eq ("case4-rec-ret" , dsd_audio_record_gate_mono (& opts , st , & allow ), 0 );
124+ rc |= expect_eq ("case4-rec-ret" , dsd_audio_record_gate_mono (opts , st , & allow ), 0 );
120125 rc |= expect_eq ("case4-rec-allow" , allow , 0 );
121126 }
122127
123128 // Case 5: Mono per-call recording gate uses slot-specific TG/encryption state.
124- memset (& opts , 0 , sizeof (opts ));
129+ memset (opts , 0 , sizeof (* opts ));
125130 memset (st , 0 , sizeof (* st ));
126- opts . trunk_use_allow_list = 1 ;
131+ opts -> trunk_use_allow_list = 1 ;
127132 st -> currentslot = 1 ;
128133 st -> group_tally = 1 ;
129134 st -> lasttg = 600UL ;
@@ -133,26 +138,27 @@ main(void) {
133138 set_group (st , 0 , 601UL , "A" , "RIGHT-ONLY" );
134139 {
135140 int allow = -1 ;
136- rc |= expect_eq ("case5-rec-ret" , dsd_audio_record_gate_mono (& opts , st , & allow ), 0 );
141+ rc |= expect_eq ("case5-rec-ret" , dsd_audio_record_gate_mono (opts , st , & allow ), 0 );
137142 rc |= expect_eq ("case5-rec-allow" , allow , 1 );
138143 }
139144
140145 // Case 6: P25 Phase 2 recording gate follows the per-slot audio-allowed flag.
141- memset (& opts , 0 , sizeof (opts ));
146+ memset (opts , 0 , sizeof (* opts ));
142147 memset (st , 0 , sizeof (* st ));
143148 st -> synctype = DSD_SYNC_P25P2_POS ;
144149 st -> currentslot = 1 ;
145150 st -> p25_p2_audio_allowed [0 ] = 0 ;
146151 st -> p25_p2_audio_allowed [1 ] = 1 ;
147152 {
148153 int allow = -1 ;
149- rc |= expect_eq ("case6-rec-ret" , dsd_audio_record_gate_mono (& opts , st , & allow ), 0 );
154+ rc |= expect_eq ("case6-rec-ret" , dsd_audio_record_gate_mono (opts , st , & allow ), 0 );
150155 rc |= expect_eq ("case6-rec-allow" , allow , 1 );
151156 }
152157
153158 if (rc == 0 ) {
154159 printf ("CORE_AUDIO_GROUP_GATE: OK\n" );
155160 }
161+ free (opts );
156162 free (st );
157163 return rc ;
158164}
0 commit comments