// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using Xunit; namespace Microsoft.AspNetCore.Routing.DecisionTree { public class DecisionTreeBuilderTest { [Fact] public void BuildTree_Empty() { // Arrange var items = new List(); // Act var tree = DecisionTreeBuilder.GenerateTree(items, new ItemClassifier()); // Assert Assert.Empty(tree.Criteria); Assert.Empty(tree.Matches); } [Fact] public void BuildTree_TrivialMatch() { // Arrange var items = new List(); var item = new Item(); items.Add(item); // Act var tree = DecisionTreeBuilder.GenerateTree(items, new ItemClassifier()); // Assert Assert.Empty(tree.Criteria); Assert.Same(item, Assert.Single(tree.Matches)); } [Fact] public void BuildTree_WithMultipleCriteria() { // Arrange var items = new List(); var item = new Item(); item.Criteria.Add("area", new DecisionCriterionValue(value: "Admin")); item.Criteria.Add("controller", new DecisionCriterionValue(value: "Users")); item.Criteria.Add("action", new DecisionCriterionValue(value: "AddUser")); items.Add(item); // Act var tree = DecisionTreeBuilder.GenerateTree(items, new ItemClassifier()); // Assert Assert.Empty(tree.Matches); var area = Assert.Single(tree.Criteria); Assert.Equal("area", area.Key); var admin = Assert.Single(area.Branches); Assert.Equal("Admin", admin.Key); Assert.Empty(admin.Value.Matches); var controller = Assert.Single(admin.Value.Criteria); Assert.Equal("controller", controller.Key); var users = Assert.Single(controller.Branches); Assert.Equal("Users", users.Key); Assert.Empty(users.Value.Matches); var action = Assert.Single(users.Value.Criteria); Assert.Equal("action", action.Key); var addUser = Assert.Single(action.Branches); Assert.Equal("AddUser", addUser.Key); Assert.Empty(addUser.Value.Criteria); Assert.Same(item, Assert.Single(addUser.Value.Matches)); } [Fact] public void BuildTree_WithMultipleItems() { // Arrange var items = new List(); var item1 = new Item(); item1.Criteria.Add("controller", new DecisionCriterionValue(value: "Store")); item1.Criteria.Add("action", new DecisionCriterionValue(value: "Buy")); items.Add(item1); var item2 = new Item(); item2.Criteria.Add("controller", new DecisionCriterionValue(value: "Store")); item2.Criteria.Add("action", new DecisionCriterionValue(value: "Checkout")); items.Add(item2); // Act var tree = DecisionTreeBuilder.GenerateTree(items, new ItemClassifier()); // Assert Assert.Empty(tree.Matches); var action = Assert.Single(tree.Criteria); Assert.Equal("action", action.Key); var buy = action.Branches["Buy"]; Assert.Empty(buy.Matches); var controller = Assert.Single(buy.Criteria); Assert.Equal("controller", controller.Key); var store = Assert.Single(controller.Branches); Assert.Equal("Store", store.Key); Assert.Empty(store.Value.Criteria); Assert.Same(item1, Assert.Single(store.Value.Matches)); var checkout = action.Branches["Checkout"]; Assert.Empty(checkout.Matches); controller = Assert.Single(checkout.Criteria); Assert.Equal("controller", controller.Key); store = Assert.Single(controller.Branches); Assert.Equal("Store", store.Key); Assert.Empty(store.Value.Criteria); Assert.Same(item2, Assert.Single(store.Value.Matches)); } [Fact] public void BuildTree_WithInteriorMatch() { // Arrange var items = new List(); var item1 = new Item(); item1.Criteria.Add("controller", new DecisionCriterionValue(value: "Store")); item1.Criteria.Add("action", new DecisionCriterionValue(value: "Buy")); items.Add(item1); var item2 = new Item(); item2.Criteria.Add("controller", new DecisionCriterionValue(value: "Store")); item2.Criteria.Add("action", new DecisionCriterionValue(value: "Checkout")); items.Add(item2); var item3 = new Item(); item3.Criteria.Add("action", new DecisionCriterionValue(value: "Buy")); items.Add(item3); // Act var tree = DecisionTreeBuilder.GenerateTree(items, new ItemClassifier()); // Assert Assert.Empty(tree.Matches); var action = Assert.Single(tree.Criteria); Assert.Equal("action", action.Key); var buy = action.Branches["Buy"]; Assert.Same(item3, Assert.Single(buy.Matches)); } [Fact] public void BuildTree_WithDivergentCriteria() { // Arrange var items = new List(); var item1 = new Item(); item1.Criteria.Add("controller", new DecisionCriterionValue(value: "Store")); item1.Criteria.Add("action", new DecisionCriterionValue(value: "Buy")); items.Add(item1); var item2 = new Item(); item2.Criteria.Add("controller", new DecisionCriterionValue(value: "Store")); item2.Criteria.Add("action", new DecisionCriterionValue(value: "Checkout")); items.Add(item2); var item3 = new Item(); item3.Criteria.Add("stub", new DecisionCriterionValue(value: "Bleh")); items.Add(item3); // Act var tree = DecisionTreeBuilder.GenerateTree(items, new ItemClassifier()); // Assert Assert.Empty(tree.Matches); var action = tree.Criteria[0]; Assert.Equal("action", action.Key); var stub = tree.Criteria[1]; Assert.Equal("stub", stub.Key); } private class Item { public Item() { Criteria = new Dictionary(StringComparer.OrdinalIgnoreCase); } public Dictionary Criteria { get; private set; } } private class ItemClassifier : IClassifier { public IEqualityComparer ValueComparer { get { return new RouteValueEqualityComparer(); } } public IDictionary GetCriteria(Item item) { return item.Criteria; } } } }