/* * Sone - Matchers.java - Copyright © 2013–2016 David Roden * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package net.pterodactylus.sone; import static java.util.regex.Pattern.compile; import java.io.IOException; import java.io.InputStream; import net.pterodactylus.sone.data.Album; import net.pterodactylus.sone.data.Image; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.PostReply; import com.google.common.base.Optional; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeDiagnosingMatcher; import org.hamcrest.TypeSafeMatcher; /** * Matchers used throughout the tests. * * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a> */ public class Matchers { public static Matcher<String> matchesRegex(final String regex) { return new TypeSafeMatcher<String>() { @Override protected boolean matchesSafely(String item) { return compile(regex).matcher(item).matches(); } @Override public void describeTo(Description description) { description.appendText("matches: ").appendValue(regex); } }; } public static Matcher<InputStream> delivers(final byte[] data) { return new TypeSafeMatcher<InputStream>() { byte[] readData = new byte[data.length]; @Override protected boolean matchesSafely(InputStream inputStream) { int offset = 0; try { while (true) { int r = inputStream.read(); if (r == -1) { return offset == data.length; } if (offset == data.length) { return false; } if (data[offset] != (readData[offset] = (byte) r)) { return false; } offset++; } } catch (IOException ioe1) { return false; } } @Override public void describeTo(Description description) { description.appendValue(data); } @Override protected void describeMismatchSafely(InputStream item, Description mismatchDescription) { mismatchDescription.appendValue(readData); } }; } public static Matcher<Post> isPost(String postId, long time, String text, Optional<String> recipient) { return new PostMatcher(postId, time, text, recipient); } public static Matcher<Post> isPostWithId(String postId) { return new PostIdMatcher(postId); } public static Matcher<PostReply> isPostReply(String postReplyId, String postId, long time, String text) { return new PostReplyMatcher(postReplyId, postId, time, text); } public static Matcher<Album> isAlbum(final String albumId, final String parentAlbumId, final String title, final String albumDescription) { return new TypeSafeDiagnosingMatcher<Album>() { @Override protected boolean matchesSafely(Album album, Description mismatchDescription) { if (!album.getId().equals(albumId)) { mismatchDescription.appendText("ID is ") .appendValue(album.getId()); return false; } if (parentAlbumId == null) { if (album.getParent() != null) { mismatchDescription.appendText("has parent album"); return false; } } else { if (album.getParent() == null) { mismatchDescription.appendText("has no parent album"); return false; } if (!album.getParent().getId().equals(parentAlbumId)) { mismatchDescription.appendText("parent album is ") .appendValue(album.getParent().getId()); return false; } } if (!title.equals(album.getTitle())) { mismatchDescription.appendText("has title ") .appendValue(album.getTitle()); return false; } if (!albumDescription.equals(album.getDescription())) { mismatchDescription.appendText("has description ") .appendValue(album.getDescription()); return false; } return true; } @Override public void describeTo(Description description) { description.appendText("is album ").appendValue(albumId); if (parentAlbumId == null) { description.appendText(", has no parent"); } else { description.appendText(", has parent ") .appendValue(parentAlbumId); } description.appendText(", has title ").appendValue(title); description.appendText(", has description ") .appendValue(albumDescription); } }; } public static Matcher<Image> isImage(final String id, final long creationTime, final String key, final String title, final String imageDescription, final int width, final int height) { return new TypeSafeDiagnosingMatcher<Image>() { @Override protected boolean matchesSafely(Image image, Description mismatchDescription) { if (!image.getId().equals(id)) { mismatchDescription.appendText("ID is ") .appendValue(image.getId()); return false; } if (image.getCreationTime() != creationTime) { mismatchDescription.appendText("created at @") .appendValue(image.getCreationTime()); return false; } if (!image.getKey().equals(key)) { mismatchDescription.appendText("key is ") .appendValue(image.getKey()); return false; } if (!image.getTitle().equals(title)) { mismatchDescription.appendText("title is ") .appendValue(image.getTitle()); return false; } if (!image.getDescription().equals(imageDescription)) { mismatchDescription.appendText("description is ") .appendValue(image.getDescription()); return false; } if (image.getWidth() != width) { mismatchDescription.appendText("width is ") .appendValue(image.getWidth()); return false; } if (image.getHeight() != height) { mismatchDescription.appendText("height is ") .appendValue(image.getHeight()); return false; } return true; } @Override public void describeTo(Description description) { description.appendText("image with ID ").appendValue(id); description.appendText(", created at @") .appendValue(creationTime); description.appendText(", has key ").appendValue(key); description.appendText(", has title ").appendValue(title); description.appendText(", has description ") .appendValue(imageDescription); description.appendText(", has width ").appendValue(width); description.appendText(", has height ").appendValue(height); } }; } private static class PostMatcher extends TypeSafeDiagnosingMatcher<Post> { private final String postId; private final long time; private final String text; private final Optional<String> recipient; private PostMatcher(String postId, long time, String text, Optional<String> recipient) { this.postId = postId; this.time = time; this.text = text; this.recipient = recipient; } @Override protected boolean matchesSafely(Post post, Description mismatchDescription) { if (!post.getId().equals(postId)) { mismatchDescription.appendText("ID is not ") .appendValue(postId); return false; } if (post.getTime() != time) { mismatchDescription.appendText("Time is not @") .appendValue(time); return false; } if (!post.getText().equals(text)) { mismatchDescription.appendText("Text is not ") .appendValue(text); return false; } if (recipient.isPresent()) { if (!post.getRecipientId().isPresent()) { mismatchDescription.appendText( "Recipient not present"); return false; } if (!post.getRecipientId().get().equals(recipient.get())) { mismatchDescription.appendText("Recipient is not ") .appendValue(recipient.get()); return false; } } else { if (post.getRecipientId().isPresent()) { mismatchDescription.appendText("Recipient is present"); return false; } } return true; } @Override public void describeTo(Description description) { description.appendText("is post with ID ") .appendValue(postId); description.appendText(", created at @").appendValue(time); description.appendText(", text ").appendValue(text); if (recipient.isPresent()) { description.appendText(", directed at ") .appendValue(recipient.get()); } } } private static class PostIdMatcher extends TypeSafeDiagnosingMatcher<Post> { private final String id; private PostIdMatcher(String id) { this.id = id; } @Override protected boolean matchesSafely(Post item, Description mismatchDescription) { if (!item.getId().equals(id)) { mismatchDescription.appendText("post has ID ").appendValue(item.getId()); return false; } return true; } @Override public void describeTo(Description description) { description.appendText("post with ID ").appendValue(id); } } private static class PostReplyMatcher extends TypeSafeDiagnosingMatcher<PostReply> { private final String postReplyId; private final String postId; private final long time; private final String text; private PostReplyMatcher(String postReplyId, String postId, long time, String text) { this.postReplyId = postReplyId; this.postId = postId; this.time = time; this.text = text; } @Override protected boolean matchesSafely(PostReply postReply, Description mismatchDescription) { if (!postReply.getId().equals(postReplyId)) { mismatchDescription.appendText("is post reply ") .appendValue(postReply.getId()); return false; } if (!postReply.getPostId().equals(postId)) { mismatchDescription.appendText("is reply to ") .appendValue(postReply.getPostId()); return false; } if (postReply.getTime() != time) { mismatchDescription.appendText("is created at @").appendValue( postReply.getTime()); return false; } if (!postReply.getText().equals(text)) { mismatchDescription.appendText("says ") .appendValue(postReply.getText()); return false; } return true; } @Override public void describeTo(Description description) { description.appendText("is post reply ").appendValue(postReplyId); description.appendText(", replies to post ").appendValue(postId); description.appendText(", is created at @").appendValue(time); description.appendText(", says ").appendValue(text); } } }