From a1e01741c26cd6c0bf68342233673234ce3558d9 Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Wed, 3 Jan 2024 16:17:18 +0000 Subject: [PATCH 1/4] typos --- message/README.md | 8 ++++---- message/message-http/README.md | 2 +- message/message-http/pom.xml | 2 +- message/message-json/README.md | 2 +- message/message-json/pom.xml | 2 +- message/message-text/README.md | 2 +- message/message-text/pom.xml | 2 +- message/message-xml/README.md | 2 +- message/message-xml/pom.xml | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/message/README.md b/message/README.md index 31c7138513..058b45c427 100644 --- a/message/README.md +++ b/message/README.md @@ -9,12 +9,12 @@ Implementations of the Message interface * [../flow](https://github.com/Mastercard/flow) Testing framework * [message-core](message-core) Message implementation utilities - * [message-http](message-http) HypterText Transfer Protocol messages - * [message-json](message-json) JavaScript Object Notation Messages + * [message-http](message-http) HyperText Transfer Protocol messages + * [message-json](message-json) JavaScript Object Notation messages * [message-sql](message-sql) Structured Query Language messages - * [message-text](message-text) Freeform text Message + * [message-text](message-text) Freeform text messages * [message-web](message-web) Browser interaction messages - * [message-xml](message-xml) Extensible Markup Language Messages + * [message-xml](message-xml) Extensible Markup Language messages diff --git a/message/message-http/README.md b/message/message-http/README.md index 7da3ea2d55..95bef41703 100644 --- a/message/message-http/README.md +++ b/message/message-http/README.md @@ -3,7 +3,7 @@ # message-http -HypterText Transfer Protocol messages +HyperText Transfer Protocol messages [![javadoc](https://javadoc.io/badge2/com.mastercard.test.flow/message-http/javadoc.svg)](https://javadoc.io/doc/com.mastercard.test.flow/message-http) diff --git a/message/message-http/pom.xml b/message/message-http/pom.xml index 6dd3d063a6..8cca311209 100644 --- a/message/message-http/pom.xml +++ b/message/message-http/pom.xml @@ -8,7 +8,7 @@ message-http jar - HypterText Transfer Protocol messages + HyperText Transfer Protocol messages diff --git a/message/message-json/README.md b/message/message-json/README.md index 671c76e497..3972114957 100644 --- a/message/message-json/README.md +++ b/message/message-json/README.md @@ -3,7 +3,7 @@ # message-json -JavaScript Object Notation Messages +JavaScript Object Notation messages [![javadoc](https://javadoc.io/badge2/com.mastercard.test.flow/message-json/javadoc.svg)](https://javadoc.io/doc/com.mastercard.test.flow/message-json) diff --git a/message/message-json/pom.xml b/message/message-json/pom.xml index 789f7fd64e..0e7536181a 100644 --- a/message/message-json/pom.xml +++ b/message/message-json/pom.xml @@ -8,7 +8,7 @@ message-json jar - JavaScript Object Notation Messages + JavaScript Object Notation messages diff --git a/message/message-text/README.md b/message/message-text/README.md index e40199d6ee..50a2a24c02 100644 --- a/message/message-text/README.md +++ b/message/message-text/README.md @@ -3,7 +3,7 @@ # message-text -Freeform text Message +Freeform text messages [![javadoc](https://javadoc.io/badge2/com.mastercard.test.flow/message-text/javadoc.svg)](https://javadoc.io/doc/com.mastercard.test.flow/message-text) diff --git a/message/message-text/pom.xml b/message/message-text/pom.xml index e96e8d2077..ab7cd26f79 100644 --- a/message/message-text/pom.xml +++ b/message/message-text/pom.xml @@ -8,7 +8,7 @@ message-text jar - Freeform text Message + Freeform text messages diff --git a/message/message-xml/README.md b/message/message-xml/README.md index a04e145ec6..c7c56a88ad 100644 --- a/message/message-xml/README.md +++ b/message/message-xml/README.md @@ -3,7 +3,7 @@ # message-xml -Extensible Markup Language Messages +Extensible Markup Language messages [![javadoc](https://javadoc.io/badge2/com.mastercard.test.flow/message-xml/javadoc.svg)](https://javadoc.io/doc/com.mastercard.test.flow/message-xml) diff --git a/message/message-xml/pom.xml b/message/message-xml/pom.xml index bb0c9b3f8e..4ecf679761 100644 --- a/message/message-xml/pom.xml +++ b/message/message-xml/pom.xml @@ -8,7 +8,7 @@ message-xml jar - Extensible Markup Language Messages + Extensible Markup Language messages From 7972fe45e8b5cbff146dd8e64b6ddaf804ac1fe3 Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Thu, 4 Jan 2024 10:07:33 +0000 Subject: [PATCH 2/4] Allowed masking operations before hashing --- doc/src/main/markdown/further.md | 3 ++ .../test/flow/validation/MessageHash.java | 31 +++++++++-- .../test/flow/validation/MessageHashTest.java | 53 +++++++++++++++++++ 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/doc/src/main/markdown/further.md b/doc/src/main/markdown/further.md index d9a2c7bf80..b617d57ea2 100644 --- a/doc/src/main/markdown/further.md +++ b/doc/src/main/markdown/further.md @@ -325,6 +325,8 @@ For an example of this usage, see the [`ExampleSystemTest.hashes()`][ExampleSyst This test will fail if the expected hash values are not updated as the system model is changed, so the change reviewer can look at the diff on this test to see at a glance which parts of the system have been impacted by a change. +Note that [field-masking operations can be supplied][MessageHash.hashing(Actor,Include,Consumer)] when you specify your message hashes - this allows you remove or overwrite dynamic fields in your model to achieve consistent hashing results. + ### Report diff tool The flow framework uses an inheritance mechanism (deriving a new flow from an existing one) to effectively compress the set of test data that we use to exercise a tested system. This compression makes it easier to make sweeping changes to test data with small edits to the flow construction code, but by the same token it can be difficult to understand the impact of those small changes. @@ -338,6 +340,7 @@ Full instructions for using the diff tool are provided [here](../../../../report [MessageHash]: ../../../../validation/validation-core/src/main/java/com/mastercard/test/flow/validation/MessageHash.java [ExampleSystemTest]: ../../../../example/app-model/src/test/java/com/mastercard/test/flow/example/app/model/ExampleSystemTest.java +[MessageHash.hashing(Actor,Include,Consumer)]: ../../../../validation/validation-core/src/main/java/com/mastercard/test/flow/validation/MessageHash.java#L140-L154,140-154 diff --git a/validation/validation-core/src/main/java/com/mastercard/test/flow/validation/MessageHash.java b/validation/validation-core/src/main/java/com/mastercard/test/flow/validation/MessageHash.java index 6c7da517ef..bff7a34330 100644 --- a/validation/validation-core/src/main/java/com/mastercard/test/flow/validation/MessageHash.java +++ b/validation/validation-core/src/main/java/com/mastercard/test/flow/validation/MessageHash.java @@ -152,7 +152,7 @@ public MessageHash hashing( String name, Predicate interaction, Function> messages, Function content ) { - hashes.add( new Hash( name, flows, interaction, messages ) ); + hashes.add( new Hash( name, flows, interaction, messages, content ) ); return this; } @@ -181,6 +181,29 @@ public MessageHash hashing( Actor responder, Include messages ) { Message::content ); } + /** + * Adds a comparison to hash requests to and/or responses from a particular + * {@link Actor}, while masking out dynamic fields that should not be included + * in the hash. + * + * @param responder The actor + * @param messages The message type of interest + * @param mask How to mask out fields that should not be included in the + * hash + * @return this + */ + public MessageHash hashing( Actor responder, Include messages, Consumer mask ) { + return hashing( messages.name() + " " + messages.actorInfix + " " + responder.name(), + f -> true, + i -> i.responder() == responder, + messages, + m -> { + Message child = m.child(); + mask.accept( child ); + return child.content(); + } ); + } + /** * Computes the actual hashes and compares them against the supplied * expectations @@ -226,13 +249,15 @@ private static class Hash { public final Predicate flows; public final Predicate interaction; public final Function> messages; + public final Function content; public Hash( String name, Predicate flows, Predicate interaction, - Function> messages ) { + Function> messages, Function content ) { this.name = name; this.flows = flows; this.interaction = interaction; this.messages = messages; + this.content = content; } public void compute( Model model, @@ -248,7 +273,7 @@ public void compute( Model model, .flatMap( Flows::interactions ) .filter( interaction ) .flatMap( messages ) - .map( Message::content ) + .map( content ) .mapToInt( b -> { byte[] h = digest.digest( b ); for( int i = 0; i < h.length; i++ ) { diff --git a/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java b/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java index 73f33ce545..eff0f38c8d 100644 --- a/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java +++ b/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java @@ -1,12 +1,19 @@ package com.mastercard.test.flow.validation; +import static com.mastercard.test.flow.validation.MessageHash.Include.REQUESTS; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Map; +import java.util.TreeMap; import java.util.function.BiConsumer; import java.util.stream.Stream; @@ -18,6 +25,7 @@ import com.mastercard.test.flow.Interaction; import com.mastercard.test.flow.Message; import com.mastercard.test.flow.Model; +import com.mastercard.test.flow.util.Bytes; import com.mastercard.test.flow.validation.MessageHash.Include; /** @@ -127,6 +135,29 @@ void responses() { "8D777F385D3DFEC8815D20F7496026DC 0001 4 B" ); } + /** + * Showing that when masking operations are requested, they are applied to a + * child of the messages in the model + * + * @throws NoSuchAlgorithmException This would be surprising + */ + @Test + void masking() throws NoSuchAlgorithmException { + + String expectedHashedContent = "child of 'request' with updates {dynamic field=static value}"; + int expectedLength = expectedHashedContent.length(); + MessageDigest digest = MessageDigest.getInstance( "MD5" ); + String expectedHash = Bytes.toHex( digest.digest( expectedHashedContent.getBytes( UTF_8 ) ) ); + + MessageHash masking = new MessageHash( Assertions::assertEquals ) + .hashing( BEN, REQUESTS, m -> m.set( "dynamic field", "static value" ) ); + + masking.expect( model( + flow( ntr( AVA, "request", BEN, "response" ) ) ), + "REQUESTS --> BEN", + expectedHash + " 0001 " + expectedLength + " B" ); + } + /** * Demonstrates what happens when you have even numbers of identical messages * being hashed together @@ -270,6 +301,28 @@ private static Interaction ntr( Actor requester, String req, Actor responder, St private static Message msg( String content ) { Message msg = mock( Message.class ); when( msg.content() ).thenReturn( content.getBytes( UTF_8 ) ); + + Map childUpdates = new TreeMap<>(); + Message child = mock( Message.class ); + + doAnswer( inv -> { + childUpdates.put( inv.getArgument( 0 ), inv.getArgument( 1 ) ); + return null; + } ) + .when( child ) + .set( any(), any() ); + + when( child.content() ) + .thenAnswer( inv -> { + String s = String.format( + "child of '%s' with updates %s", + content, childUpdates ); + System.out.println( s ); + return s.getBytes( UTF_8 ); + } ); + + when( msg.child() ).thenReturn( child ); + return msg; } } From e316898e1dc69ee3c3f3c1eb9abd6e2fc028311a Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Thu, 4 Jan 2024 10:43:58 +0000 Subject: [PATCH 3/4] squashed mutant --- .../com/mastercard/test/flow/validation/MessageHashTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java b/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java index eff0f38c8d..71b8c665d6 100644 --- a/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java +++ b/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java @@ -144,7 +144,7 @@ void responses() { @Test void masking() throws NoSuchAlgorithmException { - String expectedHashedContent = "child of 'request' with updates {dynamic field=static value}"; + String expectedHashedContent = "child of 'hash this!' with updates {dynamic field=static value}"; int expectedLength = expectedHashedContent.length(); MessageDigest digest = MessageDigest.getInstance( "MD5" ); String expectedHash = Bytes.toHex( digest.digest( expectedHashedContent.getBytes( UTF_8 ) ) ); @@ -153,7 +153,8 @@ void masking() throws NoSuchAlgorithmException { .hashing( BEN, REQUESTS, m -> m.set( "dynamic field", "static value" ) ); masking.expect( model( - flow( ntr( AVA, "request", BEN, "response" ) ) ), + flow( ntr( AVA, "hash this!", BEN, "but not this" ) ), + flow( ntr( BEN, "or this", CHE, "and definitley not this" ) ) ), "REQUESTS --> BEN", expectedHash + " 0001 " + expectedLength + " B" ); } From 5ba9eb3e208446c7c4d65f99b1ec49bf8f443ac2 Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Thu, 4 Jan 2024 10:53:10 +0000 Subject: [PATCH 4/4] removing sysout noise --- .../com/mastercard/test/flow/validation/MessageHashTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java b/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java index 71b8c665d6..0a76a2becd 100644 --- a/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java +++ b/validation/validation-core/src/test/java/com/mastercard/test/flow/validation/MessageHashTest.java @@ -318,7 +318,6 @@ private static Message msg( String content ) { String s = String.format( "child of '%s' with updates %s", content, childUpdates ); - System.out.println( s ); return s.getBytes( UTF_8 ); } );