context: namespace Tests.Local
  {
      using System;
      using System.Linq;
  
      using Allors.Meta;
      using Allors.Server;
      using Allors.Workspace;
      using Allors.Workspace.Domain;
  
      using Xunit;
  
      public class SessionTests : LocalTest
      {
          [Fact]
          public void UnitGet()
          {
              this.Workspace.Sync(Fixture.loadData);
              var session = new Session(this.Workspace);
  
              var koen = session.Get(1) as Person;
  
              Assert.Equal("Koen", koen.FirstName);
              Assert.Null(koen.MiddleName);
              Assert.Equal("Van Exem", koen.LastName);
              Assert.Equal(DateTime.Parse("1973-03-27T18:00:00Z"), koen.BirthDate);
              Assert.True(koen.IsStudent);
  
              var patrick = session.Get(2) as Person;
  
              Assert.Equal("Patrick", patrick.FirstName);
              Assert.Equal("De Boeck", patrick.LastName);
              Assert.Null(patrick.MiddleName);
              Assert.Null(patrick.BirthDate);
              Assert.False(patrick.IsStudent);
  
              var martien = session.Get(3) as Person;
  
              Assert.Equal("Martien", martien.FirstName);
              Assert.Equal("Knippenberg", martien.LastName);
              Assert.Equal("van", martien.MiddleName);
              Assert.Null(martien.BirthDate);
              Assert.Null(martien.IsStudent);
          }
  
          [Fact]
          public void UnitSet()
          {
              this.Workspace.Sync(Fixture.loadData);
  
              var session1 = new Session(this.Workspace);
              var martien1 = session1.Get(3) as Person;
  
              var session2 = new Session(this.Workspace);
              var martien2 = session2.Get(3) as Person;
  
              martien2.FirstName = "Martinus";
              martien2.MiddleName = "X";
  
              Assert.Equal("Martien", martien1.FirstName);
              Assert.Equal("Knippenberg", martien1.LastName);
              Assert.Equal("van", martien1.MiddleName);
  
              Assert.Equal("Martinus", martien2.FirstName);
              Assert.Equal("Knippenberg", martien2.LastName);
              Assert.Equal("X", martien2.MiddleName);
          }
  
          [Fact]
          public void HasChanges()
          {
              this.Workspace.Sync(Fixture.loadData);
  
              var session = new Session(this.Workspace);
              var martien = session.Get(3) as Person;
              var acme = session.Get(101) as Organisation;
  
              Assert.False(session.HasChanges);
  
              var firstName = martien.FirstName;
              martien.FirstName = firstName;
  
              Assert.False(session.HasChanges);
  
              martien.UserName = null;
  
              Assert.False(session.HasChanges);
  
              var owner = acme.Owner;
              acme.Owner = owner;
  
              Assert.False(session.HasChanges);
  
              acme.CycleOne = null;
  
              Assert.False(session.HasChanges);
  
              var employees = acme.Employees;
              acme.Employees = employees;
  
              Assert.False(session.HasChanges);
  
              employees = employees.Reverse().ToArray();
              acme.Employees = employees;
  
              Assert.False(session.HasChanges);
  
              acme.CycleMany = null;
  
              Assert.False(session.HasChanges);
          }
          
          [Fact]
          public void UnitSave()
          {
              this.Workspace.Sync(Fixture.loadData);
              var session = new Session(this.Workspace);
  
              var koen = session.Get(1) as Person;
              var patrick = session.Get(2) as Person;
              var martien = session.Get(3) as Person;
  
              koen.FirstName = "K";
              koen.LastName = "VE";
              martien.FirstName = "Martinus";
              martien.MiddleName = "X";
  
              var save = session.PushRequest();
  
              Assert.Equal(2, save.Objects.Length);
  
              var savedKoen = save.Objects.First(v => (v.I == "1"));
  
              Assert.Equal("1001", savedKoen.V);
              Assert.Equal(2, savedKoen.Roles.Length);
  
              var savedKoenFirstName = savedKoen.Roles.First(v => v.T == "FirstName");
              var savedKoenLastName = savedKoen.Roles.First(v => v.T == "LastName");
  
              Assert.Equal("K", savedKoenFirstName.S);
              Assert.Null(savedKoenFirstName.A);
              Assert.Null(savedKoenFirstName.R);
              Assert.Equal("VE", savedKoenLastName.S);
              Assert.Null(savedKoenLastName.A);
              Assert.Null(savedKoenLastName.R);
  
              var savedMartien = save.Objects.First(v => v.I == "3");
  
              Assert.Equal("1003", savedMartien.V);
              Assert.Equal(2, savedMartien.Roles.Length);
  
              var savedMartienFirstName = savedMartien.Roles.First(v => v.T == "FirstName");
              var savedMartienMiddleName = savedMartien.Roles.First(v => v.T == "MiddleName");
  
              Assert.Equal("Martinus", savedMartienFirstName.S);
              Assert.Null(savedMartienFirstName.A);
              Assert.Null(savedMartienFirstName.R);
              Assert.Equal("X", savedMartienMiddleName.S);
              Assert.Null(savedMartienMiddleName.A);
              Assert.Null(savedMartienMiddleName.R);
          }
  
          [Fact]
          public void OneGet()
          {
              this.Workspace.Sync(Fixture.loadData);
              var session = new Session(this.Workspace);
  
              var koen = session.Get(1) as Person;
              var patrick = session.Get(2) as Person;
              var martien = session.Get(3) as Person;
  
              var acme = session.Get(101) as Organisation;
              var ocme = session.Get(102) as Organisation;
              var icme = session.Get(103) as Organisation;
  
              Assert.Equal(koen, acme.Owner);
              Assert.Equal(patrick, ocme.Owner);
              Assert.Equal(martien, icme.Owner);
  
              Assert.Null(acme.Manager);
              Assert.Null(ocme.Manager);
              Assert.Null(icme.Manager);
          }
  
          [Fact]
          public void OneSet()
          {
              this.Workspace.Sync(Fixture.loadData);
  
              var session1 = new Session(this.Workspace);
  
              var session2 = new Session(this.Workspace);
  
              var koen1 = session1.Get(1) as Person;
              var patrick1 = session1.Get(2) as Person;
              var martien1 = session1.Get(3) as Person;
  
              var acme1 = session1.Get(101) as Organisation;
              var ocme1 = session1.Get(102) as Organisation;
              var icme1 = session1.Get(103) as Organisation;
  
              var koen2 = session2.Get(1) as Person;
              var patrick2 = session2.Get(2) as Person;
              var martien2 = session2.Get(3) as Person;
  
              var acme2 = session2.Get(101) as Organisation;
              var ocme2 = session2.Get(102) as Organisation;
              var icme2 = session2.Get(103) as Organisation;
  
              acme2.Owner = martien2;
              ocme2.Owner = null;
              acme2.Manager = patrick2;
  
              Assert.Equal(koen1, acme1.Owner);
              Assert.Equal(patrick1, ocme1.Owner);
              Assert.Equal(martien1, icme1.Owner);
  
              Assert.Null(acme1.Manager);
              Assert.Null(ocme1.Manager);
              Assert.Null(icme1.Manager);
  
              Assert.Equal(martien2, acme2.Owner); //x
              Assert.Null(ocme2.Owner);
              Assert.Equal(martien2, icme2.Owner);
  
              Assert.Equal(patrick2, acme2.Manager); //x
              Assert.Null(ocme2.Manager);
              Assert.Null(icme2.Manager);
          }
  
          [Fact]
          public void OneSave()
          {
              this.Workspace.Sync(Fixture.loadData);
              var session = new Session(this.Workspace);
  
              var koen = session.Get(1) as Person;
              var patrick = session.Get(2) as Person;
              var martien = session.Get(3) as Person;
  
              var acme = session.Get(101) as Organisation;
              var ocme = session.Get(102) as Organisation;
              var icme = session.Get(103) as Organisation;
  
              acme.Owner = martien;
              ocme.Owner = null;
  
              acme.Manager = patrick;
  
              var save = session.PushRequest();
  
              Assert.Equal(2, save.Objects.Length);
  
              var savedAcme = save.Objects.First(v => v.I == "101");
  
              Assert.Equal("1101", savedAcme.V);
              Assert.Equal(2, savedAcme.Roles.Length);
  
              var savedAcmeOwner = savedAcme.Roles.First(v => v.T == "Owner");
              var savedAcmeManager = savedAcme.Roles.First(v => v.T == "Manager");
  
              Assert.Equal("3", savedAcmeOwner.S);
              Assert.Null(savedAcmeOwner.A);
              Assert.Null(savedAcmeOwner.R);
              Assert.Equal("2", savedAcmeManager.S);
              Assert.Null(savedAcmeManager.A);
              Assert.Null(savedAcmeManager.R);
  
              var savedOcme = save.Objects.First(v => v.I == "102");
  
              Assert.Equal("1102", savedOcme.V);
              Assert.Single(savedOcme.Roles);
  
              var savedOcmeOwner = savedOcme.Roles.First(v => v.T == "Owner");
  
              Assert.Null(savedOcmeOwner.S);
              Assert.Null(savedOcmeOwner.A);
              Assert.Null(savedOcmeOwner.R);
          }
  
          [Fact]
          public void ManyGet()
          {
              this.Workspace.Sync(Fixture.loadData);
              var session = new Session(this.Workspace);
  
              var koen = (Person)session.Get(1);
              var patrick = (Person)session.Get(2);
              var martien = (Person)session.Get(3);
  
              var acme = (Organisation)session.Get(101);
              var ocme = (Organisation)session.Get(102);
              var icme = (Organisation)session.Get(103);
  
              Assert.Equal(3, acme.Employees.Length);
              Assert.Contains(koen, acme.Employees);
              Assert.Contains(martien, acme.Employees);
              Assert.Contains(patrick, acme.Employees);
  
              Assert.Single(ocme.Employees);
              Assert.Contains(koen, ocme.Employees);
  
              Assert.Empty(icme.Employees);
  
              Assert.Empty(acme.Shareholders);
              Assert.Empty(ocme.Shareholders);
              Assert.Empty(icme.Shareholders);
          }
  
          [Fact]
          public void ManySet()
          {
              this.Workspace.Sync(Fixture.loadData);
  
              var session1 = new Session(this.Workspace);
  
              var session2 = new Session(this.Workspace);
  
              var koen1 = session1.Get(1) as Person;
              var patrick1 = session1.Get(2) as Person;
              var martien1 = session1.Get(3) as Person;
  
              var acme1 = session1.Get(101) as Organisation;
              var ocme1 = session1.Get(102) as Organisation;
              var icme1 = session1.Get(103) as Organisation;
  
              var koen2 = session2.Get(1) as Person;
              var patrick2 = session2.Get(2) as Person;
              var martien2 = session2.Get(3) as Person;
  
              var acme2 = session2.Get(101) as Organisation;
              var ocme2 = session2.Get(102) as Organisation;
              var icme2 = session2.Get(103) as Organisation;
  
              acme2.Employees = null;
              icme2.Employees = new[] { koen2, patrick2, martien2 };
  
              Assert.Equal(3, acme1.Employees.Length);
              Assert.Contains(koen1, acme1.Employees);
              Assert.Contains(martien1, acme1.Employees);
              Assert.Contains(patrick1, acme1.Employees);
  
              Assert.Single(ocme1.Employees);
              Assert.Contains(koen1, ocme1.Employees);
  
              Assert.Empty(icme1.Employees);
  
              Assert.Empty(acme2.Employees);
  
              Assert.Single(ocme2.Employees);
              Assert.Contains(koen2, ocme2.Employees);
  
              Assert.Equal(3, icme2.Employees.Length);
              Assert.Contains(koen2, icme2.Employees);
              Assert.Contains(martien2, icme2.Employees);
              Assert.Contains(patrick2, icme2.Employees);
          }
  
          [Fact]
          public void ManySaveWithExistingObjects()
          {
              this.Workspace.Sync(Fixture.loadData);
  
              var session = new Session(this.Workspace);
  
              var koen = session.Get(1) as Person;
  
gt:             var patrick = session.Get(2) as Person;