1

I'm facing problems related to string comparison using Assert.equals() provided by remix_tests.sol.

I made a toy contract and a related test to show what the problem is:

https://gist.github.com/brunoarruda/0cf813ee5aefe60427b5788e0489782e

When I run that test on Remix IDE with Solidity v0.5.1+commit.c8a2cb62, the last Assert comparing a string and another one built from its bytes32 counterpart does not pass. I put both strings inside assert message to see what was compared and the output is:

browser/test1_test.sol
1 failing

test_1 - Test user adding
Alice and Alice are not the same.

So, someone knows what is happening and how to make the string comparison work??

I tried to look for remix_tests.sol source code to study what was going on but I couldn't find it anywhere.

1 Answer 1

1

The issue with your code is the 000000000000000000000000000000000000000000000000000000 in 0x416c696365000000000000000000000000000000000000000000000000000000 are also decoded with the character \u0000.

To fix that, you can use this function bytes32ToString to decode correctly without the zeros:

import "remix_tests.sol"; // this import is automatically injected by Remix.
import "./ContainerContract.sol";

contract test_1 {

    ContainerContract container;

    function beforeAll () public {
       container = new ContainerContract();
    }

    function testUserAdding() public returns (string memory) {
        // setup
        string memory name = "Alice";

        bytes32 nameBytes = 0x416c696365000000000000000000000000000000000000000000000000000000;

        // processing
        container.addData(name);
        bytes32 recoveredNameBytes = container.data(0);
        string memory recoveredName = bytes32ToString(recoveredNameBytes);

        // asserting
        Assert.equal(nameBytes, recoveredNameBytes, "byte representations should be the same.");
        Assert.equal(name, name, "They should be literally the same.");
        string memory assertMsg = string(abi.encodePacked(name, " and ", recoveredName, " are not the same."));
        Assert.equal(name, recoveredName, assertMsg);
    }

    function bytes32ToString(bytes32 x) public returns (string memory value) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (uint j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        value = string(bytesStringTrimmed);
    }
}
1
  • Just for clarification, byte(bytes32(uint(x) * 2 ** (8 * j))) takes the jth byte starting from the left, right? so with x=nameBytes and j=0 it would pick 41, correct?? Commented Jul 22, 2019 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.