diff --git a/Sources/Samples.sln b/Sources/Samples.sln index bb5bb73..d7c16d4 100644 --- a/Sources/Samples.sln +++ b/Sources/Samples.sln @@ -23,6 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{162D6E80 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestModel", "basics\Tests\TestModel\TestModel.csproj", "{DA282291-A2AD-428B-8899-C6EC2299C4FF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestDataManager", "basics\Tests\TestDataManager\TestDataManager.csproj", "{0BD88157-82ED-4C52-A74C-3A7A046B2D13}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +59,10 @@ Global {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 + {0BD88157-82ED-4C52-A74C-3A7A046B2D13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0BD88157-82ED-4C52-A74C-3A7A046B2D13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0BD88157-82ED-4C52-A74C-3A7A046B2D13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0BD88157-82ED-4C52-A74C-3A7A046B2D13}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -70,5 +76,6 @@ Global {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} + {0BD88157-82ED-4C52-A74C-3A7A046B2D13} = {162D6E80-9B72-4A78-8481-39E3AC255C99} EndGlobalSection EndGlobal diff --git a/Sources/basics/Model/IDataManager.cs b/Sources/basics/Model/IDataManager.cs index cd98e46..f3fe3ba 100644 --- a/Sources/basics/Model/IDataManager.cs +++ b/Sources/basics/Model/IDataManager.cs @@ -3,15 +3,15 @@ namespace Model; public interface IDataManager { Task> GetBooks(int index, int count); - Task> GetBooksByTitle(string title, int index, int count); - Task> GetBooksByAuthor(string author, int index, int count); - Task> GetBooksByIsbn(string isbn, int index, int count); + Task> GetBooksByTitle(string? title, int index, int count); + Task> GetBooksByAuthor(string? author, int index, int count); + Task> GetBooksByIsbn(string? isbn, int index, int count); Task GetBookById(long id); Task> GetPersons(int index, int count); - Task> GetPersonsByName(string name, int index, int count); + Task> GetPersonsByName(string? name, int index, int count); Task GetPersonById(long id); - Task> GetBooksBorrowedBy(Person person, int index, int count); + Task> GetBooksBorrowedBy(Person? person, int index, int count); Task CreateBook(string title, string author, string isbn); Task UpdateBook(long id, Book book); diff --git a/Sources/basics/Stub/EmptyStubDataManager.cs b/Sources/basics/Stub/EmptyStubDataManager.cs new file mode 100644 index 0000000..b1f9f11 --- /dev/null +++ b/Sources/basics/Stub/EmptyStubDataManager.cs @@ -0,0 +1,186 @@ +using System; +using Model; + +namespace Stub; + +public class EmptyStubDataManager : IDataManager +{ + protected readonly List books = new(); + + protected readonly List persons = new(); + + protected long bookId; + + protected long personId; + + public Task BorrowBook(Book book, Person person) + { + if(book == null || person == null) return Task.FromResult(false); + + 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 && !foundBook.Borrower.Equals(foundPerson)) + { + return Task.FromResult(false); + } + foundBook.Borrower = foundPerson; + foundPerson.BorrowBook(foundBook); + return Task.FromResult(true); + } + + public Task 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 CreatePerson(string firstName, string lastName) + { + Person person = new Person(personId, firstName, lastName); + persons.Add(person); + personId++; + return Task.FromResult(person); + } + + public Task 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 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 GetBookById(long id) + { + return Task.FromResult(books.SingleOrDefault(b => b.Id == id)); + } + + public Task> GetBooks(int index, int count) + { + var foundBooks = books.Skip(index*count).Take(count); + return Task.FromResult(foundBooks); + } + + public Task> GetBooksBorrowedBy(Person? person, int index, int count) + { + if(person == null) return Task.FromResult(Enumerable.Empty()); + + var foundBooks = books.Where(b => person.Equals(b.Borrower)) + .Skip(index*count).Take(count); + return Task.FromResult(foundBooks); + } + + public Task> GetBooksByAuthor(string? author, int index, int count) + { + if(string.IsNullOrWhiteSpace(author)) return Task.FromResult(Enumerable.Empty()); + + var foundBooks = books.Where(b => b.Author.Contains(author, StringComparison.InvariantCultureIgnoreCase)) + .Skip(index*count).Take(count); + return Task.FromResult(foundBooks); + } + + public Task> GetBooksByIsbn(string? isbn, int index, int count) + { + if(string.IsNullOrWhiteSpace(isbn)) return Task.FromResult(Enumerable.Empty()); + + var foundBooks = books.Where(b => b.Isbn.Equals(isbn)) + .Skip(index*count).Take(count); + return Task.FromResult(foundBooks); + } + + public Task> GetBooksByTitle(string? title, int index, int count) + { + if(string.IsNullOrWhiteSpace(title)) return Task.FromResult(Enumerable.Empty()); + + var foundBooks = books.Where(b => b.Title.Contains(title, StringComparison.InvariantCultureIgnoreCase)) + .Skip(index*count).Take(count); + return Task.FromResult(foundBooks); + } + + public Task GetPersonById(long id) + { + return Task.FromResult(persons.SingleOrDefault(p => p.Id == id)); + } + + public Task> GetPersons(int index, int count) + { + var foundPersons = persons.Skip(index*count).Take(count); + return Task.FromResult(foundPersons); + } + + public Task> GetPersonsByName(string? name, int index, int count) + { + if(string.IsNullOrWhiteSpace(name)) return Task.FromResult(Enumerable.Empty()); + + 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 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 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 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); + } +} diff --git a/Sources/basics/Stub/StubDataManager.cs b/Sources/basics/Stub/StubDataManager.cs index bfad991..657299c 100644 --- a/Sources/basics/Stub/StubDataManager.cs +++ b/Sources/basics/Stub/StubDataManager.cs @@ -2,40 +2,38 @@ namespace Stub; -public class StubDataManager : IDataManager +public class StubDataManager : EmptyStubDataManager { - private readonly static List 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 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; + public StubDataManager() : base() + { + books.AddRange([ + 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") + ]); + + bookId = 12; + + persons.AddRange([ + 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") + ]); + + personId = 8; - static StubDataManager() - { books[0].Borrower = persons[0]; persons[0].BorrowBook(books[0]); @@ -63,163 +61,4 @@ public class StubDataManager : IDataManager books[10].Borrower = persons[3]; persons[3].BorrowBook(books[10]); } - - public Task 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 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 CreatePerson(string firstName, string lastName) - { - Person person = new Person(personId, firstName, lastName); - persons.Add(person); - personId++; - return Task.FromResult(person); - } - - public Task 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 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 GetBookById(long id) - { - return Task.FromResult(books.SingleOrDefault(b => b.Id == id)); - } - - public Task> GetBooks(int index, int count) - { - var foundBooks = books.Skip(index*count).Take(count); - return Task.FromResult(foundBooks); - } - - public Task> 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> 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> 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> 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 GetPersonById(long id) - { - return Task.FromResult(persons.SingleOrDefault(p => p.Id == id)); - } - - public Task> GetPersons(int index, int count) - { - var foundPersons = persons.Skip(index*count).Take(count); - return Task.FromResult(foundPersons); - } - - public Task> 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 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 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 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); - } } diff --git a/Sources/basics/Tests/TestDataManager/DataManagerTest.cs b/Sources/basics/Tests/TestDataManager/DataManagerTest.cs new file mode 100644 index 0000000..58b8d06 --- /dev/null +++ b/Sources/basics/Tests/TestDataManager/DataManagerTest.cs @@ -0,0 +1,33 @@ +using Model; + +namespace TestDataManager; + +public class DataManagerTest +{ + [Theory] + [ClassData(typeof(TestData_BorrowBook))] + public async void TestBorrowBook(bool expectedResult, Book bookToBorrow, Person borrower, IDataManager dataManager) + { + bool result = await dataManager.BorrowBook(bookToBorrow, borrower); + Book? book = (await dataManager.GetBooksByIsbn(bookToBorrow?.Isbn, 0, 100)).SingleOrDefault(); + Person? person = (await dataManager.GetPersonsByName(borrower?.LastName, 0, 100)).SingleOrDefault(); + + Assert.Equal(expectedResult, result); + + if(result) + { + Assert.NotNull(book); + Assert.NotNull(person); + Assert.Contains(book, person.Books); + Assert.Equal(person, book.Borrower); + } + else + { + if(person != null && book != null) + { + Assert.DoesNotContain(book, person.Books); + Assert.NotEqual(person, book.Borrower); + } + } + } +} \ No newline at end of file diff --git a/Sources/basics/Tests/TestDataManager/TestDataManager.csproj b/Sources/basics/Tests/TestDataManager/TestDataManager.csproj new file mode 100644 index 0000000..6f9d82f --- /dev/null +++ b/Sources/basics/Tests/TestDataManager/TestDataManager.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + diff --git a/Sources/basics/Tests/TestDataManager/TestData_BorrowBook.cs b/Sources/basics/Tests/TestDataManager/TestData_BorrowBook.cs new file mode 100644 index 0000000..5a5a46f --- /dev/null +++ b/Sources/basics/Tests/TestDataManager/TestData_BorrowBook.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections; +using Model; +using Stub; + +namespace TestDataManager; + +public class BorrowBookStub : EmptyStubDataManager +{ + public BorrowBookStub() : base() + { + books.AddRange([ + new Book(1, "Les Trois Mousquetaires", "Alexandre Dumas", "979-8415441792"), + new Book(2, "Les Misérables", "Victor Hugo", "979-8850172916") + ]); + + bookId = 3; + + persons.AddRange([ + new Person(1, "Chick", "Corea"), + new Person(2, "Stanley", "Clarke") + ]); + + personId = 3; + + books[0].Borrower = persons[0]; + persons[0].BorrowBook(books[0]); + } +} + +public class TestData_BorrowBook : IEnumerable +{ + public IEnumerator GetEnumerator() + { + //no book and no borrower + yield return new object[] { false, null, null, new BorrowBookStub() }; + + //no book + yield return new object[] { false, null, new Person("John", "Coltrane"), new StubDataManager() }; + + //no borrower + yield return new object[] { false, new Book( "Les Pardaillan", "Michel Zévaco", "978-2221098417"), null, new BorrowBookStub() }; + + //new book and new borrower + yield return new object[] { false, new Book( "Les Pardaillan", "Michel Zévaco", "978-2221098417"), new Person("John", "Coltrane"), new BorrowBookStub() }; + + //new book and already known borrower + yield return new object[] { false, new Book( "Les Pardaillan", "Michel Zévaco", "978-2221098417"), new Person(1, "Chick", "Corea"), new BorrowBookStub() }; + + //already known but free book and new borrower + yield return new object[] { false, new Book(2, "Les Misérables", "Victor Hugo", "979-8850172916"), new Person("John", "Coltrane"), new BorrowBookStub() }; + + //already known but already borrowed book and new borrower + yield return new object[] { false, new Book(1, "Les Trois Mousquetaires", "Alexandre Dumas", "979-8415441792"), new Person("John", "Coltrane"), new BorrowBookStub() }; + + //already known but free book and already known borrower + yield return new object[] { true, new Book(2, "Les Misérables", "Victor Hugo", "979-8850172916"), new Person(1, "Chick", "Corea"), new BorrowBookStub() }; + + //already known but already borrowed book by another borrower and already known borrower + yield return new object[] { false, new Book(1, "Les Trois Mousquetaires", "Alexandre Dumas", "979-8415441792"), new Person(2, "Stanley", "Clarke"), new BorrowBookStub() }; + + //already known but already borrowed book by this borrower and already known borrower + yield return new object[] { true, new Book(1, "Les Trois Mousquetaires", "Alexandre Dumas", "979-8415441792"), new Person(1, "Chick", "Corea"), new BorrowBookStub() }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +}