avrotize 2.20.3__py3-none-any.whl → 2.20.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- avrotize/__init__.py +2 -0
- avrotize/_version.py +2 -2
- avrotize/avrotocsharp/README.md.jinja +166 -0
- avrotize/avrotocsharp/class_test.cs.jinja +126 -0
- avrotize/avrotocsharp/dataclass_core.jinja +67 -5
- avrotize/avrotocsharp/project.csproj.jinja +6 -0
- avrotize/avrotocsharp/run_coverage.ps1.jinja +98 -0
- avrotize/avrotocsharp/run_coverage.sh.jinja +149 -0
- avrotize/avrotocsharp/testproject.csproj.jinja +4 -0
- avrotize/avrotocsharp.py +121 -16
- avrotize/commands.json +168 -9
- avrotize/constants.py +15 -0
- avrotize/dependencies/cs/net90/dependencies.csproj +2 -0
- avrotize/dependencies/java/jdk21/pom.xml +1 -1
- avrotize/jsonstostructure.py +234 -12
- avrotize/openapitostructure.py +717 -0
- avrotize/structuretojs/class_core.js.jinja +33 -0
- avrotize/structuretojs/enum_core.js.jinja +10 -0
- avrotize/structuretojs/package.json.jinja +12 -0
- avrotize/structuretojs/test_class.js.jinja +84 -0
- avrotize/structuretojs/test_enum.js.jinja +58 -0
- avrotize/structuretojs/test_runner.js.jinja +45 -0
- avrotize/structuretojs.py +657 -0
- avrotize/structuretots.py +26 -2
- {avrotize-2.20.3.dist-info → avrotize-2.20.4.dist-info}/METADATA +66 -1
- {avrotize-2.20.3.dist-info → avrotize-2.20.4.dist-info}/RECORD +29 -18
- {avrotize-2.20.3.dist-info → avrotize-2.20.4.dist-info}/WHEEL +0 -0
- {avrotize-2.20.3.dist-info → avrotize-2.20.4.dist-info}/entry_points.txt +0 -0
- {avrotize-2.20.3.dist-info → avrotize-2.20.4.dist-info}/licenses/LICENSE +0 -0
avrotize/__init__.py
CHANGED
|
@@ -56,6 +56,8 @@ _mappings = {
|
|
|
56
56
|
"convert_avro_to_rust": (f"{mod}.avrotorust", "convert_avro_to_rust"),
|
|
57
57
|
"convert_avro_schema_to_rust": (f"{mod}.avrotorust", "convert_avro_schema_to_rust"),
|
|
58
58
|
"convert_avro_to_datapackage": (f"{mod}.avrotodatapackage", "convert_avro_to_datapackage"),
|
|
59
|
+
"convert_structure_to_javascript": (f"{mod}.structuretojs", "convert_structure_to_javascript"),
|
|
60
|
+
"convert_structure_schema_to_javascript": (f"{mod}.structuretojs", "convert_structure_schema_to_javascript"),
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
_lazy_loader = LazyLoader(_mappings)
|
avrotize/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '2.20.
|
|
32
|
-
__version_tuple__ = version_tuple = (2, 20,
|
|
31
|
+
__version__ = version = '2.20.4'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 20, 4)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# {{ project_name }}
|
|
2
|
+
|
|
3
|
+
This is a generated C# project from an Avro schema using [avrotize](https://github.com/clemensv/avrotize).
|
|
4
|
+
|
|
5
|
+
## Project Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
{{ project_name }}/
|
|
9
|
+
├── src/ # Generated C# classes from Avro schema
|
|
10
|
+
│ └── {{ project_name | pascal }}.csproj
|
|
11
|
+
├── test/ # Generated unit tests
|
|
12
|
+
│ └── {{ project_name | pascal }}.Test.csproj
|
|
13
|
+
├── run_coverage.ps1 # PowerShell coverage script
|
|
14
|
+
├── run_coverage.sh # Bash coverage script (Linux/macOS)
|
|
15
|
+
└── {{ project_name }}.sln # Visual Studio solution file
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Building and Running
|
|
19
|
+
|
|
20
|
+
### Quick Start
|
|
21
|
+
```bash
|
|
22
|
+
# Build the project
|
|
23
|
+
dotnet build
|
|
24
|
+
|
|
25
|
+
# Run tests
|
|
26
|
+
dotnet test
|
|
27
|
+
|
|
28
|
+
# Run tests with coverage
|
|
29
|
+
dotnet test --collect:"XPlat Code Coverage"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Code Coverage
|
|
33
|
+
|
|
34
|
+
This project includes automated code coverage collection and reporting.
|
|
35
|
+
|
|
36
|
+
#### Using the Coverage Scripts
|
|
37
|
+
|
|
38
|
+
**PowerShell (Windows):**
|
|
39
|
+
```powershell
|
|
40
|
+
# Run tests with default 85% coverage threshold
|
|
41
|
+
.\run_coverage.ps1
|
|
42
|
+
|
|
43
|
+
# Set custom coverage threshold
|
|
44
|
+
.\run_coverage.ps1 -Threshold 90
|
|
45
|
+
|
|
46
|
+
# Generate HTML coverage report
|
|
47
|
+
.\run_coverage.ps1 -HtmlReport
|
|
48
|
+
|
|
49
|
+
# Generate and open HTML report in browser
|
|
50
|
+
.\run_coverage.ps1 -HtmlReport -OpenReport
|
|
51
|
+
|
|
52
|
+
# Run without failing on low coverage
|
|
53
|
+
.\run_coverage.ps1 -FailOnLowCoverage:$false
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Bash (Linux/macOS):**
|
|
57
|
+
```bash
|
|
58
|
+
# Run tests with default 85% coverage threshold
|
|
59
|
+
./run_coverage.sh
|
|
60
|
+
|
|
61
|
+
# Set custom coverage threshold
|
|
62
|
+
./run_coverage.sh --threshold 90
|
|
63
|
+
|
|
64
|
+
# Generate HTML coverage report
|
|
65
|
+
./run_coverage.sh --html-report
|
|
66
|
+
|
|
67
|
+
# Generate and open HTML report in browser
|
|
68
|
+
./run_coverage.sh --open-report
|
|
69
|
+
|
|
70
|
+
# Run without failing on low coverage
|
|
71
|
+
./run_coverage.sh --no-fail
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### Coverage Configuration
|
|
75
|
+
|
|
76
|
+
The test project is configured with the following coverage settings in `test/{{ project_name | pascal }}.Test.csproj`:
|
|
77
|
+
|
|
78
|
+
- **Default Threshold**: 85% line coverage
|
|
79
|
+
- **Output Format**: Cobertura XML
|
|
80
|
+
- **Coverage Output**: `./coverage/` directory
|
|
81
|
+
- **Includes**: All `{{ project_name | pascal }}` namespace code
|
|
82
|
+
- **Excludes**: Test projects
|
|
83
|
+
|
|
84
|
+
#### Coverage Reports
|
|
85
|
+
|
|
86
|
+
Coverage reports are generated in the following formats:
|
|
87
|
+
|
|
88
|
+
1. **Cobertura XML**: `./coverage/[guid]/coverage.cobertura.xml`
|
|
89
|
+
2. **HTML Report** (when requested): `./coverage/html/index.html`
|
|
90
|
+
|
|
91
|
+
#### Continuous Integration
|
|
92
|
+
|
|
93
|
+
For CI/CD pipelines, use:
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
# Example GitHub Actions step
|
|
97
|
+
- name: Run tests with coverage
|
|
98
|
+
run: |
|
|
99
|
+
dotnet test --collect:"XPlat Code Coverage" --results-directory:"./coverage"
|
|
100
|
+
|
|
101
|
+
# Or use the coverage script for threshold enforcement
|
|
102
|
+
- name: Run tests with coverage threshold
|
|
103
|
+
run: ./run_coverage.sh --threshold 85
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Generated Code Features
|
|
107
|
+
|
|
108
|
+
This project includes generated C# classes with the following features:
|
|
109
|
+
|
|
110
|
+
- **Value Equality**: Generated `Equals()` and `GetHashCode()` methods
|
|
111
|
+
- **Comprehensive Unit Tests**: Property tests, equality tests, and serialization tests
|
|
112
|
+
- **Multiple Serialization Support**: JSON, XML, and Avro serialization (if enabled)
|
|
113
|
+
- **Nullable Reference Types**: Full C# nullable reference type support
|
|
114
|
+
|
|
115
|
+
## Test Coverage Goals
|
|
116
|
+
|
|
117
|
+
The generated tests aim to provide comprehensive coverage of:
|
|
118
|
+
|
|
119
|
+
- ✅ **Property Access**: All public properties
|
|
120
|
+
- ✅ **Equality Methods**: `Equals()` and `GetHashCode()`
|
|
121
|
+
- ✅ **Constructors**: Default and parameterized constructors
|
|
122
|
+
- ✅ **Serialization**: JSON/XML/Avro serialization (when enabled)
|
|
123
|
+
- ✅ **Edge Cases**: Null handling and type conversion
|
|
124
|
+
|
|
125
|
+
### Typical Coverage Results
|
|
126
|
+
|
|
127
|
+
The generated tests typically achieve:
|
|
128
|
+
- **Line Coverage**: 95%+
|
|
129
|
+
- **Branch Coverage**: 90%+
|
|
130
|
+
|
|
131
|
+
## Customizing Coverage
|
|
132
|
+
|
|
133
|
+
To modify coverage settings, edit the `test/{{ project_name | pascal }}.Test.csproj` file:
|
|
134
|
+
|
|
135
|
+
```xml
|
|
136
|
+
<PropertyGroup>
|
|
137
|
+
<!-- Modify these values -->
|
|
138
|
+
<Threshold>85</Threshold> <!-- Minimum coverage % -->
|
|
139
|
+
<ThresholdType>line</ThresholdType> <!-- line, branch, or method -->
|
|
140
|
+
<ThresholdStat>minimum</ThresholdStat> <!-- minimum, average, or total -->
|
|
141
|
+
</PropertyGroup>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Dependencies
|
|
145
|
+
|
|
146
|
+
### Runtime
|
|
147
|
+
- .NET 9.0
|
|
148
|
+
- Newtonsoft.Json (if JSON serialization enabled)
|
|
149
|
+
- Apache.Avro (if Avro serialization enabled)
|
|
150
|
+
|
|
151
|
+
### Testing
|
|
152
|
+
- NUnit 4.3.2
|
|
153
|
+
- NUnit3TestAdapter 5.0.0
|
|
154
|
+
- Microsoft.NET.Test.Sdk 17.13.0
|
|
155
|
+
- coverlet.collector 6.0.4
|
|
156
|
+
- coverlet.msbuild 6.0.4
|
|
157
|
+
|
|
158
|
+
## Additional Tools
|
|
159
|
+
|
|
160
|
+
For enhanced coverage reporting, install ReportGenerator globally:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
dotnet tool install -g dotnet-reportgenerator-globaltool
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
This enables HTML report generation with the `-HtmlReport` option.
|
|
@@ -122,6 +122,17 @@ public class {{ test_class_name }}
|
|
|
122
122
|
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
123
123
|
}
|
|
124
124
|
{%- endif %}
|
|
125
|
+
{%- if protobuf_net_annotation %}
|
|
126
|
+
/// <summary> Testing Protobuf serializer </summary>
|
|
127
|
+
[Test]
|
|
128
|
+
public void Test_ToByteArray_FromData_Protobuf()
|
|
129
|
+
{
|
|
130
|
+
var mediaType = "application/x-protobuf";
|
|
131
|
+
var bytes = _instance.ToByteArray(mediaType);
|
|
132
|
+
var newInstance = {{ class_base_name }}.FromData(bytes, mediaType);
|
|
133
|
+
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
134
|
+
}
|
|
135
|
+
{%- endif %}
|
|
125
136
|
{%- if system_xml_annotation %}
|
|
126
137
|
/// <summary> Testing XML serializer </summary>
|
|
127
138
|
[Test]
|
|
@@ -133,6 +144,121 @@ public class {{ test_class_name }}
|
|
|
133
144
|
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
134
145
|
}
|
|
135
146
|
{%- endif %}
|
|
147
|
+
{%- if system_text_json_annotation %}
|
|
148
|
+
/// <summary> Testing JSON serializer </summary>
|
|
149
|
+
[Test]
|
|
150
|
+
public void Test_ToByteArray_FromData_Json()
|
|
151
|
+
{
|
|
152
|
+
var mediaType = "application/json";
|
|
153
|
+
var bytes = _instance.ToByteArray(mediaType);
|
|
154
|
+
var newInstance = {{ class_base_name }}.FromData(bytes, mediaType);
|
|
155
|
+
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
156
|
+
}
|
|
157
|
+
{%- endif %}
|
|
158
|
+
{%- if msgpack_annotation %}
|
|
159
|
+
/// <summary> Testing MsgPack serializer </summary>
|
|
160
|
+
[Test]
|
|
161
|
+
public void Test_ToByteArray_FromData_MsgPack()
|
|
162
|
+
{
|
|
163
|
+
var mediaType = "application/msgpack";
|
|
164
|
+
var bytes = _instance.ToByteArray(mediaType);
|
|
165
|
+
var newInstance = {{ class_base_name }}.FromData(bytes, mediaType);
|
|
166
|
+
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
167
|
+
}
|
|
168
|
+
{%- endif %}
|
|
169
|
+
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation or msgpack_annotation or protobuf_net_annotation %}
|
|
170
|
+
|
|
171
|
+
/// <summary> Testing FromData with edge cases </summary>
|
|
172
|
+
[Test]
|
|
173
|
+
public void Test_FromData_EdgeCases()
|
|
174
|
+
{
|
|
175
|
+
{%- if system_text_json_annotation %}
|
|
176
|
+
// Test null data - FromData returns null for null input
|
|
177
|
+
Assert.That({{ class_base_name }}.FromData((byte[])null!, "application/json"), Is.Null);
|
|
178
|
+
// Test empty data - should throw JsonException for invalid JSON
|
|
179
|
+
Assert.Throws<System.Text.Json.JsonException>(() => {{ class_base_name }}.FromData(Array.Empty<byte>(), "application/json"));
|
|
180
|
+
{%- elif newtonsoft_json_annotation %}
|
|
181
|
+
// Test null data - FromData returns null for null input
|
|
182
|
+
Assert.That({{ class_base_name }}.FromData((byte[])null!, "application/json"), Is.Null);
|
|
183
|
+
// Test empty data - Newtonsoft.Json returns null for empty string
|
|
184
|
+
Assert.That({{ class_base_name }}.FromData(Array.Empty<byte>(), "application/json"), Is.Null);
|
|
185
|
+
{%- elif avro_annotation %}
|
|
186
|
+
// Test null data - FromData returns null for null input
|
|
187
|
+
Assert.That({{ class_base_name }}.FromData((byte[])null!, "avro/binary"), Is.Null);
|
|
188
|
+
{%- elif msgpack_annotation %}
|
|
189
|
+
// Test null data - FromData returns null for null input
|
|
190
|
+
Assert.That({{ class_base_name }}.FromData((byte[])null!, "application/msgpack"), Is.Null);
|
|
191
|
+
{%- elif protobuf_net_annotation %}
|
|
192
|
+
// Test null data - FromData returns null for null input
|
|
193
|
+
Assert.That({{ class_base_name }}.FromData((byte[])null!, "application/x-protobuf"), Is.Null);
|
|
194
|
+
{%- elif system_xml_annotation %}
|
|
195
|
+
// Test null data - FromData returns null for null input
|
|
196
|
+
Assert.That({{ class_base_name }}.FromData((byte[])null!, "application/xml"), Is.Null);
|
|
197
|
+
{%- endif %}
|
|
198
|
+
}
|
|
199
|
+
{%- endif %}
|
|
200
|
+
{%- if system_text_json_annotation %}
|
|
201
|
+
|
|
202
|
+
/// <summary> Testing IsJsonMatch </summary>
|
|
203
|
+
[Test]
|
|
204
|
+
public void Test_IsJsonMatch()
|
|
205
|
+
{
|
|
206
|
+
var json = System.Text.Json.JsonSerializer.Serialize(_instance);
|
|
207
|
+
using var doc = System.Text.Json.JsonDocument.Parse(json);
|
|
208
|
+
Assert.That({{ class_base_name }}.IsJsonMatch(doc.RootElement), Is.True);
|
|
209
|
+
}
|
|
210
|
+
{%- endif %}
|
|
211
|
+
{%- if system_text_json_annotation or newtonsoft_json_annotation %}
|
|
212
|
+
|
|
213
|
+
/// <summary> Testing Gzip compression </summary>
|
|
214
|
+
[Test]
|
|
215
|
+
public void Test_ToByteArray_Gzip()
|
|
216
|
+
{
|
|
217
|
+
var mediaType = "application/json";
|
|
218
|
+
var gzipMediaType = "application/json+gzip";
|
|
219
|
+
var plainBytes = _instance.ToByteArray(mediaType);
|
|
220
|
+
var gzipBytes = _instance.ToByteArray(gzipMediaType);
|
|
221
|
+
// Gzip compressed data should start with magic bytes 0x1f 0x8b
|
|
222
|
+
Assert.That(gzipBytes.Length >= 2 && gzipBytes[0] == 0x1f && gzipBytes[1] == 0x8b, Is.True,
|
|
223
|
+
"Gzip compressed data should have correct magic bytes");
|
|
224
|
+
var newInstance = {{ class_base_name }}.FromData(gzipBytes, gzipMediaType);
|
|
225
|
+
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
226
|
+
}
|
|
227
|
+
{%- endif %}
|
|
228
|
+
{%- if msgpack_annotation and not (system_text_json_annotation or newtonsoft_json_annotation) %}
|
|
229
|
+
|
|
230
|
+
/// <summary> Testing Gzip compression with MessagePack </summary>
|
|
231
|
+
[Test]
|
|
232
|
+
public void Test_ToByteArray_Gzip_MsgPack()
|
|
233
|
+
{
|
|
234
|
+
var mediaType = "application/msgpack";
|
|
235
|
+
var gzipMediaType = "application/msgpack+gzip";
|
|
236
|
+
var plainBytes = _instance.ToByteArray(mediaType);
|
|
237
|
+
var gzipBytes = _instance.ToByteArray(gzipMediaType);
|
|
238
|
+
// Gzip compressed data should start with magic bytes 0x1f 0x8b
|
|
239
|
+
Assert.That(gzipBytes.Length >= 2 && gzipBytes[0] == 0x1f && gzipBytes[1] == 0x8b, Is.True,
|
|
240
|
+
"Gzip compressed data should have correct magic bytes");
|
|
241
|
+
var newInstance = {{ class_base_name }}.FromData(gzipBytes, gzipMediaType);
|
|
242
|
+
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
243
|
+
}
|
|
244
|
+
{%- endif %}
|
|
245
|
+
{%- if protobuf_net_annotation and not (system_text_json_annotation or newtonsoft_json_annotation or msgpack_annotation) %}
|
|
246
|
+
|
|
247
|
+
/// <summary> Testing Gzip compression with Protobuf </summary>
|
|
248
|
+
[Test]
|
|
249
|
+
public void Test_ToByteArray_Gzip_Protobuf()
|
|
250
|
+
{
|
|
251
|
+
var mediaType = "application/x-protobuf";
|
|
252
|
+
var gzipMediaType = "application/x-protobuf+gzip";
|
|
253
|
+
var plainBytes = _instance.ToByteArray(mediaType);
|
|
254
|
+
var gzipBytes = _instance.ToByteArray(gzipMediaType);
|
|
255
|
+
// Gzip compressed data should start with magic bytes 0x1f 0x8b
|
|
256
|
+
Assert.That(gzipBytes.Length >= 2 && gzipBytes[0] == 0x1f && gzipBytes[1] == 0x8b, Is.True,
|
|
257
|
+
"Gzip compressed data should have correct magic bytes");
|
|
258
|
+
var newInstance = {{ class_base_name }}.FromData(gzipBytes, gzipMediaType);
|
|
259
|
+
Assert.That(newInstance, Is.EqualTo(_instance));
|
|
260
|
+
}
|
|
261
|
+
{%- endif %}
|
|
136
262
|
}
|
|
137
263
|
{% endfilter %}
|
|
138
264
|
{% if namespace %}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation %}
|
|
1
|
+
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation or protobuf_net_annotation or msgpack_annotation %}
|
|
2
2
|
/// <summary>
|
|
3
3
|
/// Creates an object from the data
|
|
4
4
|
/// </summary>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
if ( data is {{ class_name }}) return ({{ class_name }})data;
|
|
12
12
|
if ( contentTypeString == null ) contentTypeString = System.Net.Mime.MediaTypeNames.Application.Octet;
|
|
13
13
|
var contentType = new System.Net.Mime.ContentType(contentTypeString);
|
|
14
|
-
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation %}
|
|
14
|
+
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation or protobuf_net_annotation or msgpack_annotation %}
|
|
15
15
|
if ( contentType.MediaType.EndsWith("+gzip"))
|
|
16
16
|
{
|
|
17
17
|
var stream = data switch
|
|
@@ -84,10 +84,32 @@
|
|
|
84
84
|
}
|
|
85
85
|
else if (data is System.BinaryData)
|
|
86
86
|
{
|
|
87
|
-
return
|
|
87
|
+
return Newtonsoft.Json.JsonConvert.DeserializeObject<{{ class_name }}>(((System.BinaryData)data).ToString());
|
|
88
|
+
}
|
|
89
|
+
else if (data is byte[])
|
|
90
|
+
{
|
|
91
|
+
return Newtonsoft.Json.JsonConvert.DeserializeObject<{{ class_name }}>(System.Text.Encoding.UTF8.GetString((byte[])data));
|
|
92
|
+
}
|
|
93
|
+
else if (data is System.IO.Stream)
|
|
94
|
+
{
|
|
95
|
+
using (var reader = new System.IO.StreamReader((System.IO.Stream)data))
|
|
96
|
+
{
|
|
97
|
+
return Newtonsoft.Json.JsonConvert.DeserializeObject<{{ class_name }}>(reader.ReadToEnd());
|
|
98
|
+
}
|
|
88
99
|
}
|
|
89
100
|
}
|
|
90
101
|
{%- endif %}
|
|
102
|
+
{%- if protobuf_net_annotation %}
|
|
103
|
+
if ( contentType.MediaType.StartsWith("application/x-protobuf") || contentType.MediaType.StartsWith("application/protobuf") || contentType.MediaType.StartsWith("application/vnd.google.protobuf"))
|
|
104
|
+
{
|
|
105
|
+
var stream = data switch
|
|
106
|
+
{
|
|
107
|
+
System.IO.Stream s => s, System.BinaryData bd => bd.ToStream(), byte[] bytes => new System.IO.MemoryStream(bytes),
|
|
108
|
+
_ => throw new NotSupportedException("Data is not of a supported type for conversion to Stream")
|
|
109
|
+
};
|
|
110
|
+
return global::ProtoBuf.Serializer.Deserialize<{{ class_name }}>(stream);
|
|
111
|
+
}
|
|
112
|
+
{%- endif %}
|
|
91
113
|
{%- if system_xml_annotation %}
|
|
92
114
|
if ( contentType.MediaType.StartsWith(System.Net.Mime.MediaTypeNames.Text.Xml) || contentType.MediaType.StartsWith(System.Net.Mime.MediaTypeNames.Application.Xml) || contentType.MediaType.EndsWith("+xml"))
|
|
93
115
|
{
|
|
@@ -114,11 +136,35 @@
|
|
|
114
136
|
return ({{ class_name }}?)serializer.Deserialize(memoryStream);
|
|
115
137
|
}
|
|
116
138
|
}
|
|
139
|
+
{%- endif %}
|
|
140
|
+
{%- if msgpack_annotation %}
|
|
141
|
+
if (contentType.MediaType.StartsWith("application/msgpack") || contentType.MediaType.StartsWith("application/x-msgpack"))
|
|
142
|
+
{
|
|
143
|
+
var bytes = data switch
|
|
144
|
+
{
|
|
145
|
+
byte[] b => b,
|
|
146
|
+
System.IO.Stream s => ReadStreamToBytes(s),
|
|
147
|
+
System.BinaryData bd => bd.ToArray(),
|
|
148
|
+
_ => throw new NotSupportedException("Data type not supported for MsgPack")
|
|
149
|
+
};
|
|
150
|
+
return MessagePack.MessagePackSerializer.Deserialize<{{ class_name }}>(bytes);
|
|
151
|
+
}
|
|
117
152
|
{%- endif %}
|
|
118
153
|
throw new System.NotSupportedException($"Unsupported media type {contentType.MediaType}");
|
|
119
154
|
}
|
|
120
155
|
{%- endif %}
|
|
121
156
|
|
|
157
|
+
{%- if msgpack_annotation %}
|
|
158
|
+
private static byte[] ReadStreamToBytes(System.IO.Stream stream)
|
|
159
|
+
{
|
|
160
|
+
using (var memoryStream = new System.IO.MemoryStream())
|
|
161
|
+
{
|
|
162
|
+
stream.CopyTo(memoryStream);
|
|
163
|
+
return memoryStream.ToArray();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
{%- endif %}
|
|
167
|
+
|
|
122
168
|
{%- if avro_annotation %}
|
|
123
169
|
private class SpecificDatumWriter : global::Avro.Specific.SpecificDatumWriter<{{ class_name }}>
|
|
124
170
|
{
|
|
@@ -144,7 +190,7 @@
|
|
|
144
190
|
{%- if avro_annotation %}
|
|
145
191
|
{%- endif%}
|
|
146
192
|
|
|
147
|
-
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation %}
|
|
193
|
+
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation or protobuf_net_annotation or msgpack_annotation %}
|
|
148
194
|
/// <summary>
|
|
149
195
|
/// Converts the object to a byte array
|
|
150
196
|
/// </summary>
|
|
@@ -201,7 +247,23 @@
|
|
|
201
247
|
}
|
|
202
248
|
}
|
|
203
249
|
{%- endif %}
|
|
204
|
-
{%- if
|
|
250
|
+
{%- if protobuf_net_annotation %}
|
|
251
|
+
if (contentType.MediaType.StartsWith("application/x-protobuf") || contentType.MediaType.StartsWith("application/protobuf") || contentType.MediaType.StartsWith("application/vnd.google.protobuf"))
|
|
252
|
+
{
|
|
253
|
+
using (var stream = new System.IO.MemoryStream())
|
|
254
|
+
{
|
|
255
|
+
global::ProtoBuf.Serializer.Serialize(stream, this);
|
|
256
|
+
result = stream.ToArray();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
{%- endif %}
|
|
260
|
+
{%- if msgpack_annotation %}
|
|
261
|
+
if (contentType.MediaType.StartsWith("application/msgpack") || contentType.MediaType.StartsWith("application/x-msgpack"))
|
|
262
|
+
{
|
|
263
|
+
result = MessagePack.MessagePackSerializer.Serialize(this);
|
|
264
|
+
}
|
|
265
|
+
{%- endif %}
|
|
266
|
+
{%- if avro_annotation or system_text_json_annotation or newtonsoft_json_annotation or system_xml_annotation or protobuf_net_annotation or msgpack_annotation %}
|
|
205
267
|
if (result != null && contentType.MediaType.EndsWith("+gzip"))
|
|
206
268
|
{
|
|
207
269
|
var stream = new System.IO.MemoryStream();
|
|
@@ -8,12 +8,18 @@
|
|
|
8
8
|
{%- if avro_annotation %}
|
|
9
9
|
<PackageReference Include="Apache.Avro" Version="{{ CSHARP_AVRO_VERSION }}" />
|
|
10
10
|
{%- endif %}
|
|
11
|
+
{%- if protobuf_net_annotation %}
|
|
12
|
+
<PackageReference Include="protobuf-net" Version="{{ PROTOBUF_NET_VERSION }}" />
|
|
13
|
+
{%- endif %}
|
|
11
14
|
{%- if newtonsoft_json_annotation %}
|
|
12
15
|
<PackageReference Include="Newtonsoft.Json" Version="{{ NEWTONSOFT_JSON_VERSION }}" />
|
|
13
16
|
{%- endif %}
|
|
14
17
|
{%- if system_text_json_annotation %}
|
|
15
18
|
<PackageReference Include="System.Text.Json" Version="{{ SYSTEM_TEXT_JSON_VERSION }}" />
|
|
16
19
|
{%- endif %}
|
|
20
|
+
{%- if msgpack_annotation %}
|
|
21
|
+
<PackageReference Include="MessagePack" Version="{{ MSGPACK_VERSION }}" />
|
|
22
|
+
{%- endif %}
|
|
17
23
|
<PackageReference Include="System.Memory.Data" Version="{{ SYSTEM_MEMORY_DATA_VERSION }}" />
|
|
18
24
|
</ItemGroup>
|
|
19
25
|
<ItemGroup>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env pwsh
|
|
2
|
+
# PowerShell script to run tests with code coverage and generate reports
|
|
3
|
+
# Generated for project: {{ project_name }}
|
|
4
|
+
|
|
5
|
+
param(
|
|
6
|
+
[Parameter(HelpMessage="Minimum coverage threshold (default: 85)")]
|
|
7
|
+
[int]$Threshold = 85,
|
|
8
|
+
|
|
9
|
+
[Parameter(HelpMessage="Generate HTML report")]
|
|
10
|
+
[switch]$HtmlReport = $false,
|
|
11
|
+
|
|
12
|
+
[Parameter(HelpMessage="Open HTML report in browser")]
|
|
13
|
+
[switch]$OpenReport = $false,
|
|
14
|
+
|
|
15
|
+
[Parameter(HelpMessage="Fail build if coverage below threshold")]
|
|
16
|
+
[switch]$FailOnLowCoverage = $true
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
Write-Host "🧪 Running tests with code coverage for {{ project_name }}..." -ForegroundColor Green
|
|
20
|
+
|
|
21
|
+
# Clean previous coverage results
|
|
22
|
+
$coverageDir = "./coverage"
|
|
23
|
+
if (Test-Path $coverageDir) {
|
|
24
|
+
Remove-Item $coverageDir -Recurse -Force
|
|
25
|
+
Write-Host "🧹 Cleaned previous coverage results" -ForegroundColor Yellow
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Run tests with coverage collection
|
|
29
|
+
Write-Host "📊 Collecting code coverage..." -ForegroundColor Blue
|
|
30
|
+
$testResult = dotnet test --collect:"XPlat Code Coverage" --results-directory:"$coverageDir" --logger:"console;verbosity=detailed"
|
|
31
|
+
$testExitCode = $LASTEXITCODE
|
|
32
|
+
|
|
33
|
+
if ($testExitCode -ne 0) {
|
|
34
|
+
Write-Host "❌ Tests failed!" -ForegroundColor Red
|
|
35
|
+
exit $testExitCode
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Find coverage file
|
|
39
|
+
$coverageFile = Get-ChildItem -Recurse -Path $coverageDir -Name "*.cobertura.xml" | Select-Object -First 1
|
|
40
|
+
if (-not $coverageFile) {
|
|
41
|
+
Write-Host "❌ No coverage file found!" -ForegroundColor Red
|
|
42
|
+
exit 1
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
$coverageFilePath = Join-Path $coverageDir $coverageFile
|
|
46
|
+
Write-Host "📄 Coverage file: $coverageFilePath" -ForegroundColor Green
|
|
47
|
+
|
|
48
|
+
# Parse coverage percentage
|
|
49
|
+
$coverage = Select-Xml -Path $coverageFilePath -XPath "/coverage/@line-rate"
|
|
50
|
+
$coveragePercent = [math]::Round([double]$coverage.Node.Value * 100, 2)
|
|
51
|
+
|
|
52
|
+
Write-Host "📈 Line Coverage: $coveragePercent%" -ForegroundColor $(if ($coveragePercent -ge $Threshold) { "Green" } else { "Red" })
|
|
53
|
+
|
|
54
|
+
# Parse branch coverage
|
|
55
|
+
$branchCoverage = Select-Xml -Path $coverageFilePath -XPath "/coverage/@branch-rate"
|
|
56
|
+
$branchPercent = [math]::Round([double]$branchCoverage.Node.Value * 100, 2)
|
|
57
|
+
Write-Host "🌿 Branch Coverage: $branchPercent%" -ForegroundColor $(if ($branchPercent -ge $Threshold) { "Green" } else { "Red" })
|
|
58
|
+
|
|
59
|
+
# Generate HTML report if requested
|
|
60
|
+
if ($HtmlReport) {
|
|
61
|
+
Write-Host "📊 Generating HTML coverage report..." -ForegroundColor Blue
|
|
62
|
+
|
|
63
|
+
# Check if reportgenerator is installed
|
|
64
|
+
$reportGenExists = Get-Command reportgenerator -ErrorAction SilentlyContinue
|
|
65
|
+
if (-not $reportGenExists) {
|
|
66
|
+
Write-Host "⬇️ Installing ReportGenerator..." -ForegroundColor Yellow
|
|
67
|
+
dotnet tool install -g dotnet-reportgenerator-globaltool
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
$htmlReportPath = Join-Path $coverageDir "html"
|
|
71
|
+
reportgenerator "-reports:$coverageFilePath" "-targetdir:$htmlReportPath" "-reporttypes:Html"
|
|
72
|
+
|
|
73
|
+
Write-Host "📊 HTML report generated: $htmlReportPath/index.html" -ForegroundColor Green
|
|
74
|
+
|
|
75
|
+
if ($OpenReport) {
|
|
76
|
+
$indexPath = Join-Path $htmlReportPath "index.html"
|
|
77
|
+
Start-Process $indexPath
|
|
78
|
+
Write-Host "🌐 Opened coverage report in browser" -ForegroundColor Green
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Coverage summary
|
|
83
|
+
Write-Host ""
|
|
84
|
+
Write-Host "📊 Coverage Summary:" -ForegroundColor Cyan
|
|
85
|
+
Write-Host " Line Coverage: $coveragePercent% (Threshold: $Threshold%)" -ForegroundColor White
|
|
86
|
+
Write-Host " Branch Coverage: $branchPercent%" -ForegroundColor White
|
|
87
|
+
Write-Host " Status: $(if ($coveragePercent -ge $Threshold) { "✅ PASSED" } else { "❌ FAILED" })" -ForegroundColor $(if ($coveragePercent -ge $Threshold) { "Green" } else { "Red" })
|
|
88
|
+
|
|
89
|
+
# Fail if coverage is below threshold and FailOnLowCoverage is set
|
|
90
|
+
if ($FailOnLowCoverage -and $coveragePercent -lt $Threshold) {
|
|
91
|
+
Write-Host ""
|
|
92
|
+
Write-Host "❌ Coverage $coveragePercent% is below the required threshold of $Threshold%" -ForegroundColor Red
|
|
93
|
+
exit 1
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
Write-Host ""
|
|
97
|
+
Write-Host "✅ Coverage analysis completed successfully!" -ForegroundColor Green
|
|
98
|
+
exit 0
|