Mam to. I tak, to błąd.
Problem w tym, że string.Format
dzieje się tutaj na dwóch poziomach .
Pierwszy poziom formatowania jest coś takiego:
string template = string.Format("Expected: {0}; Actual: {1}; Message: {2}",
expected, actual, message);
Następnie używamy string.Format
z podanymi parametrami:
string finalMessage = string.Format(template, parameters);
(Oczywiście zapewniane są kultury i jakiś rodzaj sanityzacji ... ale to za mało).
Wygląda to dobrze - chyba że oczekiwane i rzeczywiste wartości same kończą się nawiasami klamrowymi po konwersji na ciąg - co robią Size
. Na przykład Twój pierwszy rozmiar kończy się konwersją na:
{Width=0, Height=0}
Więc drugi poziom formatowania to coś takiego:
string.Format("Expected: {Width=0, Height=0}; Actual: {Width=1, Height=1 }; " +
"Message = Failed expected {0} actually is {1}", struct1, struct2);
... i to właśnie zawodzi. Auć.
Rzeczywiście, możemy to naprawdę łatwo udowodnić, oszukując formatowanie, aby użyć naszych parametrów dla oczekiwanych i rzeczywistych części:
var x = "{0}";
var y = "{1}";
Assert.AreEqual<object>(x, y, "What a surprise!", "foo", "bar");
Wynik to:
Assert.AreEqual failed. Expected:<foo>. Actual:<bar>. What a surprise!
Wyraźnie zepsuty, czego się nie spodziewaliśmy, foo
ani rzeczywista wartość bar
!
Zasadniczo przypomina to atak polegający na wstrzyknięciu kodu SQL, ale w raczej mniej przerażającym kontekście string.Format
.
Aby obejść ten problem, możesz użyć tego, string.Format
co sugeruje StriplingWarrior. Pozwala to uniknąć drugiego poziomu formatowania wykonywanego na wyniku formatowania z wartościami rzeczywistymi / oczekiwanymi.
Assert.AreEqual(struct1, struct2, string.Format("Failed expected {0} actually is {1}
struct1.ToString (), struct2.ToString ())) `?