Skip to content

Commit fafb9aa

Browse files
sdseatonCopilot
andcommitted
Fix WorkloadGroup enum serialization: ResourceKind and QueryConsistency
ResourceKind in RateLimitProperties was missing the StringEnumConverter attribute, causing it to serialize as an integer (e.g. 1) instead of the string value (e.g. "TotalCpuSeconds"). Every other enum property in the file already had this converter. Also added StringEnumConverter to the QueryConsistency enum type definition, since it is used inside PolicyValue<T> where a property- level converter cannot be applied. Added 4 serialization tests covering: - ResourceKind TotalCpuSeconds serializes as string - ResourceKind RequestCount serializes as string - All enum properties across the policy serialize as strings - ToCreateScript output contains string enum values Fixes github/data#10509 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 662b7d0 commit fafb9aa

2 files changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
using KustoSchemaTools.Model;
2+
using Newtonsoft.Json.Linq;
3+
4+
namespace KustoSchemaTools.Tests.Serialization
5+
{
6+
public class WorkloadGroupSerializationTests
7+
{
8+
[Fact]
9+
public void ResourceKind_ShouldSerializeAsString_NotInteger()
10+
{
11+
// Arrange - matches the exact scenario from github/data#10509
12+
var policy = new WorkloadGroupPolicy
13+
{
14+
RequestRateLimitPolicies = new PolicyList<RequestRateLimitPolicy>
15+
{
16+
new RequestRateLimitPolicy
17+
{
18+
IsEnabled = true,
19+
Scope = RateLimitScope.Principal,
20+
LimitKind = RateLimitKind.ResourceUtilization,
21+
Properties = new RateLimitProperties
22+
{
23+
ResourceKind = RateLimitResourceKind.TotalCpuSeconds,
24+
MaxUtilization = 36000,
25+
TimeWindow = TimeSpan.FromMinutes(15)
26+
}
27+
}
28+
}
29+
};
30+
31+
// Act
32+
var json = policy.ToJson();
33+
var parsed = JObject.Parse(json);
34+
35+
// Assert - ResourceKind must be a string, not an integer
36+
var resourceKind = parsed["RequestRateLimitPolicies"]![0]!["Properties"]!["ResourceKind"]!;
37+
Assert.Equal(JTokenType.String, resourceKind.Type);
38+
Assert.Equal("TotalCpuSeconds", resourceKind.Value<string>());
39+
}
40+
41+
[Fact]
42+
public void ResourceKind_RequestCount_ShouldSerializeAsString()
43+
{
44+
var policy = new WorkloadGroupPolicy
45+
{
46+
RequestRateLimitPolicies = new PolicyList<RequestRateLimitPolicy>
47+
{
48+
new RequestRateLimitPolicy
49+
{
50+
IsEnabled = true,
51+
Scope = RateLimitScope.WorkloadGroup,
52+
LimitKind = RateLimitKind.ResourceUtilization,
53+
Properties = new RateLimitProperties
54+
{
55+
ResourceKind = RateLimitResourceKind.RequestCount,
56+
MaxUtilization = 100,
57+
TimeWindow = TimeSpan.FromMinutes(1)
58+
}
59+
}
60+
}
61+
};
62+
63+
var json = policy.ToJson();
64+
var parsed = JObject.Parse(json);
65+
66+
var resourceKind = parsed["RequestRateLimitPolicies"]![0]!["Properties"]!["ResourceKind"]!;
67+
Assert.Equal(JTokenType.String, resourceKind.Type);
68+
Assert.Equal("RequestCount", resourceKind.Value<string>());
69+
}
70+
71+
[Fact]
72+
public void AllEnumProperties_ShouldSerializeAsStrings()
73+
{
74+
// Arrange - a policy with every enum populated
75+
var policy = new WorkloadGroupPolicy
76+
{
77+
RequestRateLimitPolicies = new PolicyList<RequestRateLimitPolicy>
78+
{
79+
new RequestRateLimitPolicy
80+
{
81+
IsEnabled = true,
82+
Scope = RateLimitScope.Principal,
83+
LimitKind = RateLimitKind.ResourceUtilization,
84+
Properties = new RateLimitProperties
85+
{
86+
ResourceKind = RateLimitResourceKind.TotalCpuSeconds,
87+
MaxUtilization = 36000,
88+
TimeWindow = TimeSpan.FromMinutes(15)
89+
}
90+
}
91+
},
92+
RequestRateLimitsEnforcementPolicy = new RequestRateLimitsEnforcementPolicy
93+
{
94+
QueriesEnforcementLevel = QueriesEnforcementLevel.QueryHead,
95+
CommandsEnforcementLevel = CommandsEnforcementLevel.Database
96+
},
97+
QueryConsistencyPolicy = new QueryConsistencyPolicy
98+
{
99+
QueryConsistency = new PolicyValue<QueryConsistency>
100+
{
101+
Value = QueryConsistency.WeakAffinitizedByDatabase,
102+
IsRelaxable = true
103+
}
104+
}
105+
};
106+
107+
// Act
108+
var json = policy.ToJson();
109+
var parsed = JObject.Parse(json);
110+
111+
// Assert - every enum value is a string
112+
var rateLimitPolicy = parsed["RequestRateLimitPolicies"]![0]!;
113+
Assert.Equal("Principal", rateLimitPolicy["Scope"]!.Value<string>());
114+
Assert.Equal("ResourceUtilization", rateLimitPolicy["LimitKind"]!.Value<string>());
115+
Assert.Equal("TotalCpuSeconds", rateLimitPolicy["Properties"]!["ResourceKind"]!.Value<string>());
116+
117+
var enforcement = parsed["RequestRateLimitsEnforcementPolicy"]!;
118+
Assert.Equal("QueryHead", enforcement["QueriesEnforcementLevel"]!.Value<string>());
119+
Assert.Equal("Database", enforcement["CommandsEnforcementLevel"]!.Value<string>());
120+
121+
var consistency = parsed["QueryConsistencyPolicy"]!["QueryConsistency"]!;
122+
Assert.Equal("WeakAffinitizedByDatabase", consistency["Value"]!.Value<string>());
123+
}
124+
125+
[Fact]
126+
public void ToCreateScript_ShouldContainStringEnumValues()
127+
{
128+
// Arrange - the exact scenario from the issue
129+
var workloadGroup = new WorkloadGroup
130+
{
131+
WorkloadGroupName = "test-group",
132+
WorkloadGroupPolicy = new WorkloadGroupPolicy
133+
{
134+
RequestRateLimitPolicies = new PolicyList<RequestRateLimitPolicy>
135+
{
136+
new RequestRateLimitPolicy
137+
{
138+
IsEnabled = true,
139+
Scope = RateLimitScope.Principal,
140+
LimitKind = RateLimitKind.ResourceUtilization,
141+
Properties = new RateLimitProperties
142+
{
143+
ResourceKind = RateLimitResourceKind.TotalCpuSeconds,
144+
MaxUtilization = 36000,
145+
TimeWindow = TimeSpan.FromMinutes(15)
146+
}
147+
}
148+
}
149+
}
150+
};
151+
152+
// Act
153+
var script = workloadGroup.ToCreateScript();
154+
155+
// Assert - the script should contain string value, not integer
156+
Assert.Contains("\"ResourceKind\": \"TotalCpuSeconds\"", script);
157+
Assert.DoesNotContain("\"ResourceKind\": 1", script);
158+
Assert.Contains("\"Scope\": \"Principal\"", script);
159+
Assert.Contains("\"LimitKind\": \"ResourceUtilization\"", script);
160+
}
161+
}
162+
}

KustoSchemaTools/Model/WorkloadGroup.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public enum CommandsEnforcementLevel
2626
Database
2727
}
2828

29+
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
2930
public enum QueryConsistency
3031
{
3132
Strong,
@@ -244,6 +245,7 @@ public class RateLimitProperties : IEquatable<RateLimitProperties>
244245
public int? MaxConcurrentRequests { get; set; }
245246

246247
[JsonProperty("ResourceKind")]
248+
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
247249
public RateLimitResourceKind? ResourceKind { get; set; }
248250

249251
[JsonProperty("MaxUtilization")]

0 commit comments

Comments
 (0)