diff --git a/src/ConfigCat.Client.Tests/ConfigCat.Client.Tests.csproj b/src/ConfigCat.Client.Tests/ConfigCat.Client.Tests.csproj index 4f36397f..6005ee66 100644 --- a/src/ConfigCat.Client.Tests/ConfigCat.Client.Tests.csproj +++ b/src/ConfigCat.Client.Tests/ConfigCat.Client.Tests.csproj @@ -32,6 +32,9 @@ Always + + Always + Always @@ -53,6 +56,9 @@ Always + + Always + diff --git a/src/ConfigCat.Client.Tests/SemanticVersion2ConfigEvaluatorTests.cs b/src/ConfigCat.Client.Tests/SemanticVersion2ConfigEvaluatorTests.cs new file mode 100644 index 00000000..0fee5fc0 --- /dev/null +++ b/src/ConfigCat.Client.Tests/SemanticVersion2ConfigEvaluatorTests.cs @@ -0,0 +1,12 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ConfigCat.Client.Tests +{ + [TestClass] + public class SemanticVersion2ConfigEvaluatorTests : ConfigEvaluatorTestsBase + { + protected override string SampleJsonFileName => "sample_semantic_2_v3.json"; + + protected override string MatrixResultFileName => "testmatrix_semantic_2.csv"; + } +} diff --git a/src/ConfigCat.Client.Tests/data/sample_semantic_2_v3.json b/src/ConfigCat.Client.Tests/data/sample_semantic_2_v3.json new file mode 100644 index 00000000..3d97f125 --- /dev/null +++ b/src/ConfigCat.Client.Tests/data/sample_semantic_2_v3.json @@ -0,0 +1 @@ +{"precedenceTests":{"v":"DEFAULT-FROM-CC-APP","t":1,"p":[],"r":[{"o":0,"a":"AppVersion","t":6,"c":"1.9.1-2","v":"< 1.9.1-2"},{"o":1,"a":"AppVersion","t":6,"c":"1.9.1-10","v":"< 1.9.1-10"},{"o":2,"a":"AppVersion","t":6,"c":"1.9.1-10a","v":"< 1.9.1-10a"},{"o":3,"a":"AppVersion","t":6,"c":"1.9.1-1a","v":"< 1.9.1-1a"},{"o":4,"a":"AppVersion","t":6,"c":"1.9.1-alpha","v":"< 1.9.1-alpha"},{"o":5,"a":"AppVersion","t":6,"c":"1.9.99-alpha","v":"< 1.9.99-alpha"},{"o":6,"a":"AppVersion","t":4,"c":"1.9.99-alpha","v":"= 1.9.99-alpha"},{"o":7,"a":"AppVersion","t":6,"c":"1.9.99-beta","v":"< 1.9.99-beta"},{"o":8,"a":"AppVersion","t":6,"c":"1.9.99-rc","v":"< 1.9.99-rc"},{"o":9,"a":"AppVersion","t":6,"c":"1.9.99-rc.1","v":"< 1.9.99-rc.1"},{"o":10,"a":"AppVersion","t":6,"c":"1.9.99-rc.2","v":"< 1.9.99-rc.2"},{"o":11,"a":"AppVersion","t":6,"c":"1.9.99-rc.20","v":"< 1.9.99-rc.20"},{"o":12,"a":"AppVersion","t":6,"c":"1.9.99-rc.20a","v":"< 1.9.99-rc.20a"},{"o":13,"a":"AppVersion","t":6,"c":"1.9.99-rc.2a","v":"< 1.9.99-rc.2a"},{"o":14,"a":"AppVersion","t":6,"c":"1.9.99","v":"< 1.9.99"},{"o":15,"a":"AppVersion","t":6,"c":"1.9.100","v":"< 1.9.100"},{"o":16,"a":"AppVersion","t":6,"c":"1.10.0-alpha","v":"< 1.10.0-alpha"},{"o":17,"a":"AppVersion","t":7,"c":"1.10.0-alpha","v":"<= 1.10.0-alpha"},{"o":18,"a":"AppVersion","t":6,"c":"1.10.0","v":"< 1.10.0"},{"o":19,"a":"AppVersion","t":7,"c":"1.10.0","v":"<= 1.10.0"},{"o":20,"a":"AppVersion","t":7,"c":"1.10.1","v":"<= 1.10.1"},{"o":21,"a":"AppVersion","t":7,"c":"1.10.3","v":"<= 1.10.3"},{"o":22,"a":"AppVersion","t":6,"c":"2.0.0","v":"< 2.0.0"},{"o":23,"a":"AppVersion","t":4,"c":"2.0.0","v":"= 2.0.0"},{"o":24,"a":"AppVersion","t":4,"c":"3.0.0+build3","v":"= 3.0.0+build3"},{"o":25,"a":"AppVersion","t":4,"c":"4.0.0+001","v":"= 4.0.0+001"},{"o":26,"a":"AppVersion","t":4,"c":"5.0.0+20130313144700","v":"= 5.0.0+20130313144700"},{"o":27,"a":"AppVersion","t":4,"c":"6.0.0+exp.sha.5114f85","v":"= 6.0.0+exp.sha.5114f85"},{"o":28,"a":"AppVersion","t":4,"c":"7.0.0-patch","v":"= 7.0.0-patch"},{"o":29,"a":"AppVersion","t":4,"c":"8.0.0-patch+anothermetadata","v":"= 8.0.0-patch+anothermetadata"},{"o":30,"a":"AppVersion","t":4,"c":"9.0.0-patch+metadata","v":"= 9.0.0-patch+metadata"},{"o":31,"a":"AppVersion","t":8,"c":"103.0.0","v":"> 103.0.0"},{"o":32,"a":"AppVersion","t":9,"c":"103.0.0","v":">= 103.0.0"},{"o":33,"a":"AppVersion","t":9,"c":"101.0.0","v":">= 101.0.0"},{"o":34,"a":"AppVersion","t":8,"c":"90.103.0","v":"> 90.103.0"},{"o":35,"a":"AppVersion","t":9,"c":"90.103.0","v":">= 90.103.0"},{"o":36,"a":"AppVersion","t":9,"c":"90.101.0","v":">= 90.101.0"},{"o":37,"a":"AppVersion","t":8,"c":"80.0.103","v":"> 80.0.103"},{"o":38,"a":"AppVersion","t":9,"c":"80.0.103","v":">= 80.0.103"},{"o":39,"a":"AppVersion","t":9,"c":"80.0.101","v":">= 80.0.101"},{"o":40,"a":"AppVersion","t":9,"c":"73.0.0-beta.2","v":">= 73.0.0-beta.2"},{"o":41,"a":"AppVersion","t":8,"c":"72.0.0-beta.2","v":"> 72.0.0-beta.2"},{"o":42,"a":"AppVersion","t":8,"c":"72.0.0-beta.1","v":"> 72.0.0-beta.1"},{"o":43,"a":"AppVersion","t":8,"c":"72.0.0-beta","v":"> 72.0.0-beta"},{"o":44,"a":"AppVersion","t":8,"c":"72.0.0-alpha","v":"> 72.0.0-alpha"},{"o":45,"a":"AppVersion","t":8,"c":"72.0.0-1a","v":"> 72.0.0-1a"},{"o":46,"a":"AppVersion","t":8,"c":"72.0.0-10a","v":"> 72.0.0-10a"},{"o":47,"a":"AppVersion","t":8,"c":"72.0.0-2","v":"> 72.0.0-2"},{"o":48,"a":"AppVersion","t":8,"c":"72.0.0-1","v":"> 72.0.0-1"},{"o":49,"a":"AppVersion","t":9,"c":"71.0.0+anothermetadata","v":">= 71.0.0+anothermetadata"},{"o":50,"a":"AppVersion","t":9,"c":"71.0.0-patch3+anothermetadata","v":">= 71.0.0-patch3+anothermetadata"},{"o":51,"a":"AppVersion","t":9,"c":"71.0.0-patch2","v":">= 71.0.0-patch2"},{"o":52,"a":"AppVersion","t":9,"c":"71.0.0-patch1+metadata","v":">= 71.0.0-patch1+metadata"},{"o":53,"a":"AppVersion","t":9,"c":"60.73.0-beta.2","v":">= 60.73.0-beta.2"},{"o":54,"a":"AppVersion","t":8,"c":"60.72.0-beta.2","v":"> 60.72.0-beta.2"},{"o":55,"a":"AppVersion","t":8,"c":"60.72.0-beta.1","v":"> 60.72.0-beta.1"},{"o":56,"a":"AppVersion","t":8,"c":"60.72.0-beta","v":"> 60.72.0-beta"},{"o":57,"a":"AppVersion","t":8,"c":"60.72.0-alpha","v":"> 60.72.0-alpha"},{"o":58,"a":"AppVersion","t":8,"c":"60.72.0-1a","v":"> 60.72.0-1a"},{"o":59,"a":"AppVersion","t":8,"c":"60.72.0-10a","v":"> 60.72.0-10a"},{"o":60,"a":"AppVersion","t":8,"c":"60.72.0-2","v":"> 60.72.0-2"},{"o":61,"a":"AppVersion","t":8,"c":"60.72.0-1","v":"> 60.72.0-1"},{"o":62,"a":"AppVersion","t":9,"c":"60.71.0+anothermetadata","v":">= 60.71.0+anothermetadata"},{"o":63,"a":"AppVersion","t":9,"c":"60.71.0-patch3+anothermetadata","v":">= 60.71.0-patch3+anothermetadata"},{"o":64,"a":"AppVersion","t":9,"c":"60.71.0-patch2","v":">= 60.71.0-patch2"},{"o":65,"a":"AppVersion","t":9,"c":"60.71.0-patch1+metadata","v":">= 60.71.0-patch1+metadata"},{"o":66,"a":"AppVersion","t":9,"c":"50.60.73-beta.2","v":">= 50.60.73-beta.2"},{"o":67,"a":"AppVersion","t":8,"c":"50.60.72-beta.2","v":"> 50.60.72-beta.2"},{"o":68,"a":"AppVersion","t":8,"c":"50.60.72-beta.1","v":"> 50.60.72-beta.1"},{"o":69,"a":"AppVersion","t":8,"c":"50.60.72-beta","v":"> 50.60.72-beta"},{"o":70,"a":"AppVersion","t":8,"c":"50.60.72-alpha","v":"> 50.60.72-alpha"},{"o":71,"a":"AppVersion","t":8,"c":"50.60.72-1a","v":"> 50.60.72-1a"},{"o":72,"a":"AppVersion","t":8,"c":"50.60.72-10a","v":"> 50.60.72-10a"},{"o":73,"a":"AppVersion","t":8,"c":"50.60.72-2","v":"> 50.60.72-2"},{"o":74,"a":"AppVersion","t":8,"c":"50.60.72-1","v":"> 50.60.72-1"},{"o":75,"a":"AppVersion","t":9,"c":"50.60.71+anothermetadata","v":">= 50.60.71+anothermetadata"},{"o":76,"a":"AppVersion","t":9,"c":"50.60.71-patch3+anothermetadata","v":">= 50.60.71-patch3+anothermetadata"},{"o":77,"a":"AppVersion","t":9,"c":"50.60.71-patch2","v":">= 50.60.71-patch2"},{"o":78,"a":"AppVersion","t":9,"c":"50.60.71-patch1+metadata","v":">= 50.60.71-patch1+metadata"},{"o":79,"a":"AppVersion","t":9,"c":"40.0.0-patch","v":">= 40.0.0-patch"},{"o":80,"a":"AppVersion","t":9,"c":"30.0.0-alpha","v":">= 30.0.0-alpha"}]}} \ No newline at end of file diff --git a/src/ConfigCat.Client.Tests/data/testmatrix_semantic_2.csv b/src/ConfigCat.Client.Tests/data/testmatrix_semantic_2.csv new file mode 100644 index 00000000..e0da30c9 --- /dev/null +++ b/src/ConfigCat.Client.Tests/data/testmatrix_semantic_2.csv @@ -0,0 +1,95 @@ +Identifier;Email;Country;AppVersion;precedenceTests +dontcare;;;1.9.1-1;< 1.9.1-2 +dontcare;;;1.9.1-2;< 1.9.1-10 +dontcare;;;1.9.1-10;< 1.9.1-10a +dontcare;;;1.9.1-10a;< 1.9.1-1a +dontcare;;;1.9.1-1a;< 1.9.1-alpha +dontcare;;;1.9.1-alpha;< 1.9.99-alpha +dontcare;;;1.9.99-alpha;= 1.9.99-alpha +dontcare;;;1.9.99-alpha+build1;= 1.9.99-alpha +dontcare;;;1.9.99-alpha+build2;= 1.9.99-alpha +dontcare;;;1.9.99-alpha2;< 1.9.99-beta +dontcare;;;1.9.99-beta;< 1.9.99-rc +dontcare;;;1.9.99-rc;< 1.9.99-rc.1 +dontcare;;;1.9.99-rc.1;< 1.9.99-rc.2 +dontcare;;;1.9.99-rc.2;< 1.9.99-rc.20 +dontcare;;;1.9.99-rc.9;< 1.9.99-rc.20 +dontcare;;;1.9.99-rc.20;< 1.9.99-rc.20a +dontcare;;;1.9.99-rc.20a;< 1.9.99-rc.2a +dontcare;;;1.9.99-rc.2a;< 1.9.99 +dontcare;;;1.9.99;< 1.9.100 +dontcare;;;1.9.100;< 1.10.0-alpha +dontcare;;;1.10.0-alpha;<= 1.10.0-alpha +dontcare;;;1.10.0;<= 1.10.0 +dontcare;;;1.10.1;<= 1.10.1 +dontcare;;;1.10.2;<= 1.10.3 +dontcare;;;2.0.0;= 2.0.0 +dontcare;;;2.0.0+build3;= 2.0.0 +dontcare;;;2.0.0+001;= 2.0.0 +dontcare;;;2.0.0+20130313144700;= 2.0.0 +dontcare;;;2.0.0+exp.sha.5114f85;= 2.0.0 +dontcare;;;3.0.0;= 3.0.0+build3 +dontcare;;;4.0.0;= 4.0.0+001 +dontcare;;;5.0.0;= 5.0.0+20130313144700 +dontcare;;;6.0.0;= 6.0.0+exp.sha.5114f85 +dontcare;;;7.0.0-patch+metadata;= 7.0.0-patch +dontcare;;;8.0.0-patch+metadata;= 8.0.0-patch+anothermetadata +dontcare;;;9.0.0-patch;= 9.0.0-patch+metadata +dontcare;;;10.0.0;DEFAULT-FROM-CC-APP +dontcare;;;104.0.0;> 103.0.0 +dontcare;;;103.0.0;>= 103.0.0 +dontcare;;;102.0.0;>= 101.0.0 +dontcare;;;101.0.0;>= 101.0.0 +dontcare;;;90.104.0;> 90.103.0 +dontcare;;;90.103.0;>= 90.103.0 +dontcare;;;90.102.0;>= 90.101.0 +dontcare;;;90.101.0;>= 90.101.0 +dontcare;;;80.0.104;> 80.0.103 +dontcare;;;80.0.103;>= 80.0.103 +dontcare;;;80.0.102;>= 80.0.101 +dontcare;;;80.0.101;>= 80.0.101 +dontcare;;;73.0.0;>= 73.0.0-beta.2 +dontcare;;;72.0.0;> 72.0.0-beta.2 +dontcare;;;72.0.0-beta.2;> 72.0.0-beta.1 +dontcare;;;72.0.0-beta.1;> 72.0.0-beta +dontcare;;;72.0.0-beta;> 72.0.0-alpha +dontcare;;;72.0.0-alpha;> 72.0.0-1a +dontcare;;;72.0.0-1a;> 72.0.0-10a +dontcare;;;72.0.0-10aa;> 72.0.0-10a +dontcare;;;72.0.0-10a;> 72.0.0-2 +dontcare;;;72.0.0-2;> 72.0.0-1 +dontcare;;;71.0.0+metadata;>= 71.0.0+anothermetadata +dontcare;;;71.0.0-patch3+metadata;>= 71.0.0-patch3+anothermetadata +dontcare;;;71.0.0-patch2+metadata;>= 71.0.0-patch2 +dontcare;;;71.0.0-patch1;>= 71.0.0-patch1+metadata +dontcare;;;60.73.0;>= 60.73.0-beta.2 +dontcare;;;60.72.0;> 60.72.0-beta.2 +dontcare;;;60.72.0-beta.2;> 60.72.0-beta.1 +dontcare;;;60.72.0-beta.1;> 60.72.0-beta +dontcare;;;60.72.0-beta;> 60.72.0-alpha +dontcare;;;60.72.0-alpha;> 60.72.0-1a +dontcare;;;60.72.0-1a;> 60.72.0-10a +dontcare;;;60.72.0-10aa;> 60.72.0-10a +dontcare;;;60.72.0-10a;> 60.72.0-2 +dontcare;;;60.72.0-2;> 60.72.0-1 +dontcare;;;60.71.0+metadata;>= 60.71.0+anothermetadata +dontcare;;;60.71.0-patch3+metadata;>= 60.71.0-patch3+anothermetadata +dontcare;;;60.71.0-patch2+metadata;>= 60.71.0-patch2 +dontcare;;;60.71.0-patch1;>= 60.71.0-patch1+metadata +dontcare;;;50.60.73;>= 50.60.73-beta.2 +dontcare;;;50.60.72;> 50.60.72-beta.2 +dontcare;;;50.60.72-beta.2;> 50.60.72-beta.1 +dontcare;;;50.60.72-beta.1;> 50.60.72-beta +dontcare;;;50.60.72-beta;> 50.60.72-alpha +dontcare;;;50.60.72-alpha;> 50.60.72-1a +dontcare;;;50.60.72-1a;> 50.60.72-10a +dontcare;;;50.60.72-10aa;> 50.60.72-10a +dontcare;;;50.60.72-10a;> 50.60.72-2 +dontcare;;;50.60.72-2;> 50.60.72-1 +dontcare;;;50.60.71+metadata;>= 50.60.71+anothermetadata +dontcare;;;50.60.71-patch3+metadata;>= 50.60.71-patch3+anothermetadata +dontcare;;;50.60.71-patch2+metadata;>= 50.60.71-patch2 +dontcare;;;50.60.71-patch1;>= 50.60.71-patch1+metadata +dontcare;;;50.60.71-patch1+anothermetadata;>= 50.60.71-patch1+metadata +dontcare;;;40.0.0-patch;>= 40.0.0-patch +dontcare;;;30.0.0-beta;>= 30.0.0-alpha \ No newline at end of file diff --git a/src/ConfigCatClient/Evaluate/RolloutEvaluator.cs b/src/ConfigCatClient/Evaluate/RolloutEvaluator.cs index 6d52a405..f8cef10f 100644 --- a/src/ConfigCatClient/Evaluate/RolloutEvaluator.cs +++ b/src/ConfigCatClient/Evaluate/RolloutEvaluator.cs @@ -308,9 +308,10 @@ private static bool EvaluateSemVer(string s1, string s2, ComparatorEnum comparat } return null; - }); + }) + .ToList(); - return !rsvi.Contains(null) && rsvi.Contains(v1); + return !rsvi.Contains(null) && rsvi.Any(v => v.PrecedenceMatches(v1)); case ComparatorEnum.SemVerNotIn: @@ -324,15 +325,16 @@ private static bool EvaluateSemVer(string s1, string s2, ComparatorEnum comparat } return null; - }); + }) + .ToList(); - return !rsvni.Contains(null) && !rsvni.Contains(v1); + return !rsvni.Contains(null) && !rsvni.Any(v => v.PrecedenceMatches(v1)); case ComparatorEnum.SemVerLessThan: if (SemVersion.TryParse(s2, out SemVersion v20, true)) { - return v1 < v20; + return v1.CompareByPrecedence(v20) < 0; } break; @@ -340,7 +342,7 @@ private static bool EvaluateSemVer(string s1, string s2, ComparatorEnum comparat if (SemVersion.TryParse(s2, out SemVersion v21, true)) { - return v1 <= v21; + return v1.CompareByPrecedence(v21) <= 0; } break; @@ -348,7 +350,7 @@ private static bool EvaluateSemVer(string s1, string s2, ComparatorEnum comparat if (SemVersion.TryParse(s2, out SemVersion v22, true)) { - return v1 > v22; + return v1.CompareByPrecedence(v22) > 0; } break; @@ -356,7 +358,7 @@ private static bool EvaluateSemVer(string s1, string s2, ComparatorEnum comparat if (SemVersion.TryParse(s2, out SemVersion v23, true)) { - return v1 >= v23; + return v1.CompareByPrecedence(v23) >= 0; } break;