facts sample
continuous-integration/drone/push Build is passing Details

master
Marc CHEVALDONNE 7 months ago
parent dae9e9d2c5
commit 77a679411d

@ -13,14 +13,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UTests2", "mocks\UTests2\UT
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UTests3", "mocks\UTests3\UTests3.csproj", "{A9FE0291-58A1-42E5-9768-34B3A33F4116}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "basics", "basics", "{DFAECDF9-BEF0-4D05-B7C7-238D78986BD0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "basics\Model\Model.csproj", "{12D9ED1E-4A8C-4A67-B56D-16D8AF1287F5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stub", "basics\Stub\Stub.csproj", "{E0A3410E-10BC-4E6C-B280-5CD389E36E4E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{162D6E80-9B72-4A78-8481-39E3AC255C99}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestModel", "basics\Tests\TestModel\TestModel.csproj", "{DA282291-A2AD-428B-8899-C6EC2299C4FF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{12FE8D34-611E-4AB9-93BE-C74A7D947405}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12FE8D34-611E-4AB9-93BE-C74A7D947405}.Debug|Any CPU.Build.0 = Debug|Any CPU
@ -38,11 +45,30 @@ Global
{A9FE0291-58A1-42E5-9768-34B3A33F4116}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9FE0291-58A1-42E5-9768-34B3A33F4116}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9FE0291-58A1-42E5-9768-34B3A33F4116}.Release|Any CPU.Build.0 = Release|Any CPU
{12D9ED1E-4A8C-4A67-B56D-16D8AF1287F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12D9ED1E-4A8C-4A67-B56D-16D8AF1287F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12D9ED1E-4A8C-4A67-B56D-16D8AF1287F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12D9ED1E-4A8C-4A67-B56D-16D8AF1287F5}.Release|Any CPU.Build.0 = Release|Any CPU
{E0A3410E-10BC-4E6C-B280-5CD389E36E4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E0A3410E-10BC-4E6C-B280-5CD389E36E4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0A3410E-10BC-4E6C-B280-5CD389E36E4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0A3410E-10BC-4E6C-B280-5CD389E36E4E}.Release|Any CPU.Build.0 = Release|Any CPU
{DA282291-A2AD-428B-8899-C6EC2299C4FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA282291-A2AD-428B-8899-C6EC2299C4FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA282291-A2AD-428B-8899-C6EC2299C4FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA282291-A2AD-428B-8899-C6EC2299C4FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{12FE8D34-611E-4AB9-93BE-C74A7D947405} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
{93AA2CF9-A29A-41D2-9ECC-87BE7BD121A4} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
{991E0C4E-48DE-4699-BCF7-070029923143} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
{A9FE0291-58A1-42E5-9768-34B3A33F4116} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
{12D9ED1E-4A8C-4A67-B56D-16D8AF1287F5} = {DFAECDF9-BEF0-4D05-B7C7-238D78986BD0}
{E0A3410E-10BC-4E6C-B280-5CD389E36E4E} = {DFAECDF9-BEF0-4D05-B7C7-238D78986BD0}
{162D6E80-9B72-4A78-8481-39E3AC255C99} = {DFAECDF9-BEF0-4D05-B7C7-238D78986BD0}
{DA282291-A2AD-428B-8899-C6EC2299C4FF} = {162D6E80-9B72-4A78-8481-39E3AC255C99}
EndGlobalSection
EndGlobal

@ -0,0 +1,70 @@
namespace Model;
public class Book : IEquatable<Book>
{
public long Id { get; private init; }
public string Title
{
get => title;
set => title = value ?? "";
}
private string title = null!;
public string Author
{
get => author;
set => author = value ?? "";
}
private string author = null!;
public string Isbn
{
get => isbn;
set => isbn = value ?? "";
}
private string isbn = null!;
public Person? Borrower { get; set; }
public Book(long id, string title, string author, string isbn)
{
Id = id;
Title = title;
Author = author;
Isbn = isbn;
}
public Book(string title, string author, string isbn)
: this(0, title, author, isbn)
{
}
public bool Equals(Book? other)
{
if (Id != 0)
return Id == (other?.Id ?? 0);
else
return Title.Equals(other?.Title)
&& Author.Equals(other?.Author)
&& Isbn.Equals(other?.Isbn);
}
public override bool Equals(object? obj)
{
if(ReferenceEquals(obj, null)) return false;
if(ReferenceEquals(obj, this)) return true;
if(GetType() != obj.GetType()) return false;
return Equals(obj as Book);
}
public override int GetHashCode()
{
if(Id != 0)
return (int)(Id % 7879);
else
return Isbn.GetHashCode();
}
public override string ToString()
=> $"{Id} - {Title} ({Isbn}) // {Author}";
}

@ -0,0 +1,26 @@
namespace Model;
public interface IDataManager
{
Task<IEnumerable<Book>> GetBooks(int index, int count);
Task<IEnumerable<Book>> GetBooksByTitle(string title, int index, int count);
Task<IEnumerable<Book>> GetBooksByAuthor(string author, int index, int count);
Task<IEnumerable<Book>> GetBooksByIsbn(string isbn, int index, int count);
Task<Book?> GetBookById(long id);
Task<IEnumerable<Person>> GetPersons(int index, int count);
Task<IEnumerable<Person>> GetPersonsByName(string name, int index, int count);
Task<Person?> GetPersonById(long id);
Task<IEnumerable<Book>> GetBooksBorrowedBy(Person person, int index, int count);
Task<Book> CreateBook(string title, string author, string isbn);
Task<Book?> UpdateBook(long id, Book book);
Task<bool> DeleteBook(long id);
Task<Person> CreatePerson(string firstName, string lastName);
Task<Person?> UpdatePerson(long id, Person person);
Task<bool> DeletePerson(long id);
Task<bool> BorrowBook(Book book, Person person);
Task<bool> ReturnBook(Book book, Person person);
}

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -0,0 +1,77 @@
using System.Collections.ObjectModel;
namespace Model;
public class Person : IEquatable<Person>
{
public long Id { get; private init; }
public string FirstName
{
get => firstName;
set => firstName = !string.IsNullOrWhiteSpace(value) ? value : "Jane";
}
private string firstName = null!;
public string LastName
{
get => lastName;
set => lastName = value ?? "";
}
private string lastName = null!;
public ReadOnlyCollection<Book> Books { get; private init; }
private List<Book> books = new List<Book>();
public Person(string firstName, string lastName)
: this(0, firstName, lastName)
{ }
public Person(long id, string firstName, string lastName)
{
Id = id;
FirstName = firstName;
LastName = lastName;
Books = new ReadOnlyCollection<Book>(books);
}
public bool BorrowBook(Book book)
{
if(books.Contains(book))
return false;
books.Add(book);
return true;
}
public bool ReturnBook(Book book)
{
return books.Remove(book);
}
public bool Equals(Person? other)
{
if(Id != 0)
return Id == (other?.Id ?? 0);
else
return FirstName.Equals(other?.FirstName)
&& LastName.Equals(other?.LastName);
}
public override bool Equals(object? obj)
{
if(ReferenceEquals(obj, null)) return false;
if(ReferenceEquals(this, obj)) return true;
if(GetType() != obj?.GetType()) return false;
return Equals(obj as Person);
}
public override int GetHashCode()
{
if(Id != 0)
return (int)(Id % 7879);
else
return FirstName.GetHashCode() + LastName.GetHashCode();
}
public override string ToString()
=> $"{Id} - {FirstName} {LastName} (#books: {Books.Count})";
}

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\Model\Model.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -0,0 +1,225 @@
using Model;
namespace Stub;
public class StubDataManager : IDataManager
{
private readonly static List<Book> books = new()
{
new Book(1, "Les Trois Mousquetaires", "Alexandre Dumas", "979-8415441792"),
new Book(2, "Vingt Ans Après", "Alexandre Dumas", "979-8805372019"),
new Book(3, "Le Vicomte de Bragelonne - Livre Premier", "Alexandre Dumas", "979-8376127575"),
new Book(4, "Le Vicomte de Bragelonne - Livre Second", "Alexandre Dumas", "979-8376430019"),
new Book(5, "Vingt mille lieues sous les Mers", "Jules Verne", "979-8489937313"),
new Book(6, "L'île mystérieuse", "Jules Verne", "979-8492533861"),
new Book(7, "Les enfants du capitaine Grant", "Jules Verne", "979-8757717418"),
new Book(8, "Les Misérables", "Victor Hugo", "979-8850172916"),
new Book(9, "Notre-Dame de Paris", "Victor Hugo", "979-8863757285"),
new Book(10, "Quatrevingt-treize", "Victor Hugo", "979-8863954202"),
new Book(11, "Han d'Islande", "Victor Hugo", "979-8864251553"),
};
private readonly static List<Person> persons = new()
{
new Person(1, "Chick", "Corea"),
new Person(2, "Stanley", "Clarke"),
new Person(3, "Lenny", "White"),
new Person(4, "Frank", "Gambale"),
new Person(5, "Jean-Luc", "Ponty"),
new Person(6, "Al", "Di Meola"),
new Person(7, "Steve", "Gadd"),
};
private long bookId = 12;
private long personId = 8;
static StubDataManager()
{
books[0].Borrower = persons[0];
persons[0].BorrowBook(books[0]);
books[1].Borrower = persons[0];
persons[0].BorrowBook(books[1]);
books[2].Borrower = persons[0];
persons[0].BorrowBook(books[2]);
books[3].Borrower = persons[0];
persons[0].BorrowBook(books[3]);
books[4].Borrower = persons[1];
persons[1].BorrowBook(books[4]);
books[5].Borrower = persons[1];
persons[1].BorrowBook(books[5]);
books[6].Borrower = persons[1];
persons[1].BorrowBook(books[6]);
books[8].Borrower = persons[2];
persons[2].BorrowBook(books[8]);
books[10].Borrower = persons[3];
persons[3].BorrowBook(books[10]);
}
public Task<bool> BorrowBook(Book book, Person person)
{
var foundBook = GetBookById(book.Id).Result;
var foundPerson = GetPersonById(person.Id).Result;
if(foundBook == null || foundPerson == null)
return Task.FromResult(false);
if(foundBook.Borrower != null)
{
return Task.FromResult(false);
}
foundBook.Borrower = foundPerson;
foundPerson.BorrowBook(foundBook);
return Task.FromResult(true);
}
public Task<Book> CreateBook(string title, string author, string isbn)
{
Book book = new Book(bookId, title, author, isbn);
books.Add(book);
bookId++;
return Task.FromResult(book);
}
public Task<Person> CreatePerson(string firstName, string lastName)
{
Person person = new Person(personId, firstName, lastName);
persons.Add(person);
personId++;
return Task.FromResult(person);
}
public Task<bool> DeleteBook(long id)
{
Book? book = books.SingleOrDefault(b => b.Id == id);
if(book == null)
{
return Task.FromResult(false);
}
book.Borrower?.ReturnBook(book);
books.Remove(book);
return Task.FromResult(true);
}
public Task<bool> DeletePerson(long id)
{
Person? person = persons.SingleOrDefault(p => p.Id == id);
if(person == null)
{
return Task.FromResult(false);
}
foreach(var book in person.Books)
{
book.Borrower = null;
}
persons.Remove(person);
return Task.FromResult(true);
}
public Task<Book?> GetBookById(long id)
{
return Task.FromResult(books.SingleOrDefault(b => b.Id == id));
}
public Task<IEnumerable<Book>> GetBooks(int index, int count)
{
var foundBooks = books.Skip(index*count).Take(count);
return Task.FromResult(foundBooks);
}
public Task<IEnumerable<Book>> GetBooksBorrowedBy(Person person, int index, int count)
{
var foundBooks = books.Where(b => person.Equals(b.Borrower))
.Skip(index*count).Take(count);
return Task.FromResult(foundBooks);
}
public Task<IEnumerable<Book>> GetBooksByAuthor(string author, int index, int count)
{
var foundBooks = books.Where(b => b.Author.Contains(author, StringComparison.InvariantCultureIgnoreCase))
.Skip(index*count).Take(count);
return Task.FromResult(foundBooks);
}
public Task<IEnumerable<Book>> GetBooksByIsbn(string isbn, int index, int count)
{
var foundBooks = books.Where(b => b.Isbn.Equals(isbn))
.Skip(index*count).Take(count);
return Task.FromResult(foundBooks);
}
public Task<IEnumerable<Book>> GetBooksByTitle(string title, int index, int count)
{
var foundBooks = books.Where(b => b.Title.Contains(title, StringComparison.InvariantCultureIgnoreCase))
.Skip(index*count).Take(count);
return Task.FromResult(foundBooks);
}
public Task<Person?> GetPersonById(long id)
{
return Task.FromResult(persons.SingleOrDefault(p => p.Id == id));
}
public Task<IEnumerable<Person>> GetPersons(int index, int count)
{
var foundPersons = persons.Skip(index*count).Take(count);
return Task.FromResult(foundPersons);
}
public Task<IEnumerable<Person>> GetPersonsByName(string name, int index, int count)
{
var foundPersons = persons.Where(b => b.FirstName.Contains(name, StringComparison.InvariantCultureIgnoreCase)
|| b.LastName.Contains(name, StringComparison.InvariantCultureIgnoreCase))
.Skip(index*count).Take(count);
return Task.FromResult(foundPersons);
}
public Task<bool> ReturnBook(Book book, Person person)
{
var foundBook = GetBookById(book.Id).Result;
var foundPerson = GetPersonById(person.Id).Result;
if(foundBook == null || foundPerson == null)
return Task.FromResult(false);
if(!foundPerson.Books.Contains(foundBook) || !foundPerson.Equals(foundBook.Borrower))
return Task.FromResult(false);
foundPerson.ReturnBook(foundBook);
foundBook.Borrower = null;
return Task.FromResult(true);
}
public Task<Book?> UpdateBook(long id, Book book)
{
var foundBook = GetBookById(id).Result;
if(foundBook == null)
return Task.FromResult((Book?)null);
foundBook.Author = book.Author;
foundBook.Isbn = book.Isbn;
foundBook.Title = book.Title;
return Task.FromResult((Book?)foundBook);
}
public Task<Person?> UpdatePerson(long id, Person person)
{
var foundPerson = GetPersonById(id).Result;
if(foundPerson == null)
return Task.FromResult((Person?)null);
foundPerson.FirstName = person.FirstName;
foundPerson.LastName = person.LastName;
return Task.FromResult((Person?)foundPerson);
}
}

@ -0,0 +1,46 @@
using Model;
namespace TestModel;
public class PersonTest
{
[Fact]
public void TestFirstName_CorrectValue()
{
Person person = new Person("Chuck", "McGill");
Assert.Equal("Chuck", person.FirstName);
person.FirstName = "Jimmy";
Assert.Equal("Jimmy", person.FirstName);
}
[Fact]
public void TestFirstName_NullValue()
{
Person person = new Person("Jimmy", "McGill");
Assert.Equal("Jimmy", person.FirstName);
person.FirstName = null;
Assert.Equal("Jane", person.FirstName);
}
[Fact]
public void TestFirstName_EmptyValue()
{
Person person = new Person("Jimmy", "McGill");
Assert.Equal("Jimmy", person.FirstName);
person.FirstName = "";
Assert.Equal("Jane", person.FirstName);
}
[Fact]
public void TestFirstName_WhiteSpacesValue()
{
Person person = new Person("Jimmy", "McGill");
Assert.Equal("Jimmy", person.FirstName);
person.FirstName = " ";
Assert.Equal("Jane", person.FirstName);
}
}

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Model\Model.csproj" />
</ItemGroup>
</Project>
Loading…
Cancel
Save