microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/fix-broken-file-references

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

scripts/tests/security/SecurityClasses.Tests.ps1

202lines · modecode

1#Requires -Modules Pester
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4using module ..\..\security\Modules\SecurityClasses.psm1
5
6Describe 'DependencyViolation' -Tag 'Unit' {
7 Context 'Default constructor' {
8 It 'Initializes with empty Metadata hashtable' {
9 $v = [DependencyViolation]::new()
10 $v.Metadata | Should -BeOfType [hashtable]
11 $v.Metadata.Count | Should -Be 0
12 }
13
14 It 'Has null/default string properties' {
15 $v = [DependencyViolation]::new()
16 $v.File | Should -BeNullOrEmpty
17 $v.Name | Should -BeNullOrEmpty
18 $v.Line | Should -Be 0
19 }
20 }
21
22 Context 'Parameterized constructor' {
23 BeforeAll {
24 $script:violation = [DependencyViolation]::new(
25 'workflow.yml', 10, 'github-actions', 'actions/checkout', 'High', 'Not SHA-pinned'
26 )
27 }
28
29 It 'Sets File property' {
30 $script:violation.File | Should -Be 'workflow.yml'
31 }
32
33 It 'Sets Line property' {
34 $script:violation.Line | Should -Be 10
35 }
36
37 It 'Sets Type property' {
38 $script:violation.Type | Should -Be 'github-actions'
39 }
40
41 It 'Sets Name property' {
42 $script:violation.Name | Should -Be 'actions/checkout'
43 }
44
45 It 'Sets Severity property' {
46 $script:violation.Severity | Should -Be 'High'
47 }
48
49 It 'Sets Description property' {
50 $script:violation.Description | Should -Be 'Not SHA-pinned'
51 }
52
53 It 'Initializes Metadata as empty hashtable' {
54 $script:violation.Metadata | Should -BeOfType [hashtable]
55 $script:violation.Metadata.Count | Should -Be 0
56 }
57 }
58
59 Context 'ViolationType ValidateSet' {
60 It 'Accepts valid ViolationType values' -ForEach @(
61 @{ Value = 'Unpinned' }
62 @{ Value = 'Stale' }
63 @{ Value = 'VersionMismatch' }
64 @{ Value = 'MissingVersionComment' }
65 @{ Value = '' }
66 ) {
67 $v = [DependencyViolation]::new()
68 $v.ViolationType = $Value
69 $v.ViolationType | Should -Be $Value
70 }
71
72 It 'Rejects invalid ViolationType' {
73 $v = [DependencyViolation]::new()
74 { $v.ViolationType = 'InvalidType' } | Should -Throw
75 }
76 }
77}
78
79Describe 'ComplianceReport' -Tag 'Unit' {
80 Context 'Default constructor' {
81 BeforeAll {
82 $script:report = [ComplianceReport]::new()
83 }
84
85 It 'Sets Timestamp to current time' {
86 $script:report.Timestamp | Should -BeOfType [datetime]
87 ($script:report.Timestamp - (Get-Date)).TotalSeconds | Should -BeLessThan 5
88 }
89
90 It 'Initializes empty Violations array' {
91 $script:report.Violations | Should -HaveCount 0
92 }
93
94 It 'Initializes empty Summary hashtable' {
95 $script:report.Summary | Should -BeOfType [hashtable]
96 }
97
98 It 'Initializes empty Metadata hashtable' {
99 $script:report.Metadata | Should -BeOfType [hashtable]
100 }
101 }
102
103 Context 'Parameterized constructor' {
104 It 'Sets ScanPath' {
105 $report = [ComplianceReport]::new('/repo')
106 $report.ScanPath | Should -Be '/repo'
107 }
108
109 It 'Initializes collections' {
110 $report = [ComplianceReport]::new('/repo')
111 $report.Violations | Should -HaveCount 0
112 $report.Summary | Should -BeOfType [hashtable]
113 $report.Metadata | Should -BeOfType [hashtable]
114 }
115 }
116
117 Context 'AddViolation' {
118 It 'Appends violation and updates UnpinnedDependencies count' {
119 $report = [ComplianceReport]::new('/repo')
120 $v = [DependencyViolation]::new('f.yml', 1, 'github-actions', 'a/b', 'High', 'desc')
121 $report.AddViolation($v)
122 $report.Violations | Should -HaveCount 1
123 $report.UnpinnedDependencies | Should -Be 1
124 }
125
126 It 'Tracks multiple violations' {
127 $report = [ComplianceReport]::new('/repo')
128 $report.AddViolation([DependencyViolation]::new('a.yml', 1, 't', 'n1', 'High', 'd'))
129 $report.AddViolation([DependencyViolation]::new('b.yml', 2, 't', 'n2', 'Low', 'd'))
130 $report.Violations | Should -HaveCount 2
131 $report.UnpinnedDependencies | Should -Be 2
132 }
133 }
134
135 Context 'CalculateScore' {
136 It 'Computes percentage when TotalDependencies > 0' {
137 $report = [ComplianceReport]::new('/repo')
138 $report.TotalDependencies = 10
139 $report.PinnedDependencies = 8
140 $report.CalculateScore()
141 $report.ComplianceScore | Should -Be 80.0
142 }
143
144 It 'Returns 100 when TotalDependencies is zero' {
145 $report = [ComplianceReport]::new('/repo')
146 $report.TotalDependencies = 0
147 $report.CalculateScore()
148 $report.ComplianceScore | Should -Be 100.0
149 }
150
151 It 'Rounds to two decimal places' {
152 $report = [ComplianceReport]::new('/repo')
153 $report.TotalDependencies = 3
154 $report.PinnedDependencies = 1
155 $report.CalculateScore()
156 $report.ComplianceScore | Should -Be 33.33
157 }
158 }
159
160 Context 'ToHashtable' {
161 BeforeAll {
162 $script:report = [ComplianceReport]::new('/repo')
163 $script:report.TotalFiles = 5
164 $script:report.ScannedFiles = 3
165 $script:report.TotalDependencies = 10
166 $script:report.PinnedDependencies = 8
167 $script:report.UnpinnedDependencies = 2
168 $script:report.ComplianceScore = 80.0
169 $script:ht = $script:report.ToHashtable()
170 }
171
172 It 'Returns hashtable with 11 keys' {
173 $script:ht | Should -BeOfType [hashtable]
174 $script:ht.Keys.Count | Should -Be 11
175 }
176
177 It 'Includes all expected keys' -ForEach @(
178 @{ Key = 'ScanPath' }
179 @{ Key = 'Timestamp' }
180 @{ Key = 'TotalFiles' }
181 @{ Key = 'ScannedFiles' }
182 @{ Key = 'TotalDependencies' }
183 @{ Key = 'PinnedDependencies' }
184 @{ Key = 'UnpinnedDependencies' }
185 @{ Key = 'ComplianceScore' }
186 @{ Key = 'Violations' }
187 @{ Key = 'Summary' }
188 @{ Key = 'Metadata' }
189 ) {
190 $script:ht.ContainsKey($Key) | Should -BeTrue
191 }
192
193 It 'Formats Timestamp as ISO 8601 string' {
194 $script:ht['Timestamp'] | Should -Match '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$'
195 }
196
197 It 'Preserves numeric values' {
198 $script:ht['TotalFiles'] | Should -Be 5
199 $script:ht['ComplianceScore'] | Should -Be 80.0
200 }
201 }
202}
203