|
41 | 41 | import hosh.modules.text.TextModule.Trim; |
42 | 42 | import hosh.spi.test.support.RecordMatcher; |
43 | 43 | import hosh.spi.CommandArguments; |
| 44 | +import net.jqwik.api.Arbitrary; |
| 45 | +import net.jqwik.api.Arbitraries; |
| 46 | +import net.jqwik.api.Assume; |
| 47 | +import net.jqwik.api.ForAll; |
| 48 | +import net.jqwik.api.Property; |
| 49 | +import net.jqwik.api.Provide; |
| 50 | +import net.jqwik.api.constraints.IntRange; |
44 | 51 | import org.junit.jupiter.api.BeforeEach; |
45 | 52 | import org.junit.jupiter.api.Nested; |
46 | 53 | import org.junit.jupiter.api.Test; |
|
54 | 61 |
|
55 | 62 | import java.time.Clock; |
56 | 63 | import java.time.Instant; |
| 64 | +import java.util.ArrayList; |
| 65 | +import java.util.Iterator; |
| 66 | +import java.util.List; |
57 | 67 | import java.util.Optional; |
58 | 68 |
|
59 | 69 | import static hosh.spi.test.support.ExitStatusAssert.assertThat; |
@@ -1933,4 +1943,57 @@ void zeroArgs() { |
1933 | 1943 | } |
1934 | 1944 | } |
1935 | 1945 |
|
| 1946 | + @Nested |
| 1947 | + class SortPropertyTest { |
| 1948 | + |
| 1949 | + @Property |
| 1950 | + void sortIsIdempotent(@ForAll("textRecordLists") List<Record> input) { |
| 1951 | + Sort sut = new Sort(); |
| 1952 | + List<Record> firstSort = runSort(sut, input); |
| 1953 | + List<Record> secondSort = runSort(sut, firstSort); |
| 1954 | + assertThat(firstSort).containsExactlyElementsOf(secondSort); |
| 1955 | + } |
| 1956 | + |
| 1957 | + private List<Record> runSort(Sort sut, List<Record> input) { |
| 1958 | + List<Record> result = new ArrayList<>(); |
| 1959 | + sut.run(CommandArguments.of("name"), fromList(input), result::add, record -> {}); |
| 1960 | + return result; |
| 1961 | + } |
| 1962 | + } |
| 1963 | + |
| 1964 | + @Nested |
| 1965 | + class TakeDropPropertyTest { |
| 1966 | + |
| 1967 | + @Property |
| 1968 | + void takeAndDropPartitionInput(@ForAll("textRecordLists") List<Record> input, |
| 1969 | + @ForAll @IntRange(min = 0, max = 20) int n) { |
| 1970 | + Assume.that(n <= input.size()); |
| 1971 | + Take takeSut = new Take(); |
| 1972 | + Drop dropSut = new Drop(); |
| 1973 | + OutputChannel noopErr = record -> {}; |
| 1974 | + |
| 1975 | + List<Record> taken = new ArrayList<>(); |
| 1976 | + takeSut.run(CommandArguments.of(String.valueOf(n)), fromList(input), taken::add, noopErr); |
| 1977 | + |
| 1978 | + List<Record> dropped = new ArrayList<>(); |
| 1979 | + dropSut.run(CommandArguments.of(String.valueOf(n)), fromList(input), dropped::add, noopErr); |
| 1980 | + |
| 1981 | + List<Record> combined = new ArrayList<>(taken); |
| 1982 | + combined.addAll(dropped); |
| 1983 | + assertThat(combined).containsExactlyElementsOf(input); |
| 1984 | + } |
| 1985 | + } |
| 1986 | + |
| 1987 | + @Provide |
| 1988 | + Arbitrary<List<Record>> textRecordLists() { |
| 1989 | + return Arbitraries.strings().alpha().ofMinLength(0).ofMaxLength(10) |
| 1990 | + .map(s -> Records.singleton(Keys.NAME, Values.ofText(s))) |
| 1991 | + .list().ofMinSize(0).ofMaxSize(20); |
| 1992 | + } |
| 1993 | + |
| 1994 | + private static InputChannel fromList(List<Record> records) { |
| 1995 | + Iterator<Record> it = records.iterator(); |
| 1996 | + return () -> it.hasNext() ? Optional.of(it.next()) : Optional.empty(); |
| 1997 | + } |
| 1998 | + |
1936 | 1999 | } |
0 commit comments