Skip to content

Commit ee30a09

Browse files
Fix floating number issue (Azure#49094)
* fix the issue and introduce test cases * update * resolve comments * update to avoid the string parsing * add long cases
1 parent b636771 commit ee30a09

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

sdk/provisioning/Azure.Provisioning/src/Expressions/BicepTypeMapping.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public static string ToLiteralString(object value, string? format) =>
6060
bool b => b.ToString(),
6161
int i => i.ToString(),
6262
long i => i.ToString(),
63+
float f => f.ToString(),
64+
double d => d.ToString(),
6365
string s => s,
6466
Uri u => u.AbsoluteUri,
6567
DateTimeOffset d => d.ToString("o"),
@@ -92,10 +94,12 @@ public static BicepExpression ToBicep(object? value, string? format)
9294
null => BicepSyntax.Null(),
9395
bool b => BicepSyntax.Value(b),
9496
int i => BicepSyntax.Value(i),
95-
// Note: below cast is valid because bicep limits to int.Min/MaxValue
96-
// in bicep source and you need to use a parameter file for larger
97-
// values
98-
long i => BicepSyntax.Value((int)i),
97+
long l => FromLong(l),
98+
// Note: bicep does not offically support floating numbers
99+
// therefore for floating numbers we are taking a workaround from
100+
// https://github.com/Azure/bicep/issues/1386#issuecomment-818077233
101+
float f => FromDouble(f),
102+
double d => FromDouble(d),
99103
string s => BicepSyntax.Value(s),
100104
Uri u => BicepSyntax.Value(ToLiteralString(u, format)),
101105
DateTimeOffset d => BicepSyntax.Value(ToLiteralString(d, format)),
@@ -121,6 +125,28 @@ IBicepValue v when (v.Kind == BicepValueKind.Unset) => BicepSyntax.Null(),
121125
_ => throw new InvalidOperationException($"Cannot convert {value} to a Bicep expression.")
122126
};
123127

128+
BicepExpression FromLong(long l)
129+
{
130+
// see if the value falls into the int range
131+
if (l >= int.MinValue && l <= int.MaxValue)
132+
{
133+
return BicepSyntax.Value((int)l);
134+
}
135+
// otherwise we use the workaround from https://github.com/Azure/bicep/issues/1386#issuecomment-818077233
136+
return BicepFunction.ParseJson(BicepSyntax.Value(l.ToString())).Compile();
137+
}
138+
139+
BicepExpression FromDouble(double d)
140+
{
141+
// see if the value is a whole number
142+
if (d >= int.MinValue && d <= int.MaxValue && d == Math.Floor(d))
143+
{
144+
return BicepSyntax.Value((int)d);
145+
}
146+
// otherwise we use the workaround from https://github.com/Azure/bicep/issues/1386#issuecomment-818077233
147+
return BicepFunction.ParseJson(BicepSyntax.Value(d.ToString())).Compile();
148+
}
149+
124150
ArrayExpression ToArray(IEnumerable<object> seq) =>
125151
BicepSyntax.Array([.. seq.Select(v => ToBicep(v, v is BicepValue b ? b.Format : null))]);
126152

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using NUnit.Framework;
5+
6+
namespace Azure.Provisioning.Tests.BicepValues;
7+
8+
public class BicepValueTests
9+
{
10+
[Test]
11+
public void ValidateLiteralBicepValue()
12+
{
13+
// string value
14+
AssertExpression("'test'", new BicepValue<string>("test"));
15+
16+
// int value
17+
AssertExpression("42", new BicepValue<int>(42));
18+
AssertExpression("-42", new BicepValue<int>(-42));
19+
20+
// long value
21+
AssertExpression("42", new BicepValue<long>(42L));
22+
AssertExpression("2147483647", new BicepValue<long>(2147483647L));
23+
AssertExpression("json('2147483648')", new BicepValue<long>(2147483648));
24+
AssertExpression("-2147483648", new BicepValue<long>(-2147483648L));
25+
AssertExpression("json('-2147483649')", new BicepValue<long>(-2147483649));
26+
AssertExpression("json('9223372036854775807')", new BicepValue<long>(9223372036854775807));
27+
28+
// bool value
29+
AssertExpression("true", new BicepValue<bool>(true));
30+
AssertExpression("false", new BicepValue<bool>(false));
31+
32+
// double value
33+
AssertExpression("json('3.14')", new BicepValue<double>(3.14));
34+
AssertExpression("json('-3.14')", new BicepValue<double>(-3.14));
35+
// double value with whole numbers
36+
AssertExpression("314", new BicepValue<double>(314d));
37+
AssertExpression("2147483647", new BicepValue<double>(2147483647d));
38+
AssertExpression("json('2147483648')", new BicepValue<double>(2147483648d));
39+
AssertExpression("-2147483647", new BicepValue<double>(-2147483647d));
40+
AssertExpression("-2147483648", new BicepValue<double>(-2147483648d));
41+
AssertExpression("json('-2147483649')", new BicepValue<double>(-2147483649d));
42+
43+
static void AssertExpression(string expected, BicepValue bicepValue)
44+
{
45+
Assert.AreEqual(expected, bicepValue.ToString());
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)