VSharp-team / VSharp

Symbolic execution engine for .NET Core
Apache License 2.0
50 stars 32 forks source link

Wrong namespace indents #203

Open viktoriia-fomina opened 1 year ago

viktoriia-fomina commented 1 year ago

Description

Test namespace indents are generated wrongly.

Environment

Docker, Ubuntu 20.04, .NET 6.0, Mono 6 VSharp console runner with special option --single-file

Steps to reproduce

  1. Run command such as (for the source code below): dotnet /usr/src/vsharp_runner/VSharp.Runner.dll --all-public-methods /usr/src/project/bin/Debug/net6.0/project.dll --render-tests --single-file
  2. See generated tests contain wrong namespace indents.

or

  1. Open https://www.utbot.org/demo
  2. Choose C# language
  3. Paste the source code from below
  4. See generated tests contain wrong namespace indents.

Source code

namespace Algorithms;

public static class Searches {
    public static int BinarySearch(int value, int[] a)
    {
        var l = a.GetLowerBound(0);
        var r = a.GetLength(0);
        while (l < r)
        {
            var mid = (l + r) / 2;
            int element = a[mid];
            if (element == value)
                return mid;
            if (element < value)
                r = mid - 1;
            l = mid + 1;
        }
        return -1;
    }
}

Generated test

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using NUnit.Framework;
using Algorithms;

namespace VSharp.TestExtensions
{

internal static class CartesianProductExtension
{
    internal static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
    {
        IEnumerable<IEnumerable<T>> emptyProduct =
            new[] { Enumerable.Empty<T>() };
        return sequences.Aggregate(
            emptyProduct,
            (accumulator, sequence) =>
                from accseq in accumulator
                from item in sequence
                select accseq.Concat(new[] {item}));
    }
}

public static class Allocator
{
    private static void FillFast<TElem>(Array? arr, TElem value)
    {
        if (arr != null)
        {
            ref var bytePtr = ref MemoryMarshal.GetArrayDataReference(arr);
            ref var ptr = ref Unsafe.As<byte, TElem>(ref bytePtr);
            var span = MemoryMarshal.CreateSpan(ref ptr, arr.Length);
            span.Fill(value);
        }
    }

    /// Fills zero-initialized array with value
    public static void Fill(Array? arr, object? value)
    {
        if (value == null)
        {
            // Do nothing because arr is already filled with nulls
            return;
        }

        var t = value.GetType();
        if (arr != null && (!t.IsValueType || Nullable.GetUnderlyingType(t) != null ||
                            value != FormatterServices.GetUninitializedObject(t)))
        {
            var elementType = arr.GetType().GetElementType();
            switch (value)
            {
                case int i when elementType == typeof(int):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(byte):
                    FillFast(arr, i);
                    break;
                case char i when elementType == typeof(char):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(uint):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(Int64):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(UInt64):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(double):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(float):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(Int16):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(UInt16):
                    FillFast(arr, i);
                    break;
                case byte i when elementType == typeof(sbyte):
                    FillFast(arr, i);
                    break;
                default:
                    var rank = arr.Rank;
                    var indices =
                        Enumerable.Range(0, rank)
                            .Select(i => Enumerable.Range(arr.GetLowerBound(i), arr.GetLength(i)))
                            .CartesianProduct();
                    foreach (var i in indices)
                    {
                        arr.SetValue(value, i.ToArray());
                    }

                    break;
            }
        }
    }
}

public class Allocator<T>
{
    private readonly Type _objectType = typeof(T);
    private readonly object _toAllocate;

    public Allocator()
    {
        _toAllocate = FormatterServices.GetUninitializedObject(_objectType);
    }

    public Allocator(string typeName)
    {
        Type? notPublicType = Type.GetType(typeName);
        _objectType = notPublicType ?? _objectType;
        _toAllocate = FormatterServices.GetUninitializedObject(_objectType);
    }

    public Allocator(object? defaultValue, params int[] lengths)
    {
        Debug.Assert(_objectType.IsArray);
        _toAllocate = Array.CreateInstance(_objectType.GetElementType()!, lengths);
        Allocator.Fill(_toAllocate as Array, defaultValue);
    }

    public Allocator(object? defaultValue, int[] lengths, int[] lowerBounds)
    {
        Debug.Assert(_objectType.IsArray);
        _toAllocate = Array.CreateInstance(_objectType.GetElementType()!, lengths, lowerBounds);
        Allocator.Fill(_toAllocate as Array, defaultValue);
    }

    public Allocator(object allocated)
    {
        _toAllocate = allocated;
    }

    public Allocator(object allocated, object defaultValue)
    {
        Debug.Assert(_objectType.IsArray);
        _toAllocate = allocated;
        Allocator.Fill(_toAllocate as Array, defaultValue);
    }

    public object this[string fieldName]
    {
        set
        {
            var allBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
            var field = _objectType.GetField(fieldName, allBindingFlags);
            var property = _objectType.GetField($"<{fieldName}>k__BackingField", allBindingFlags);
            Debug.Assert(field != null || property != null);
            field ??= property;
            if (field != null)
                field.SetValue(_toAllocate, value);
        }
    }

    public object this[params int[] index]
    {
        set
        {
            Debug.Assert(_objectType.IsArray);
            var array = _toAllocate as Array;
            array?.SetValue(value, index);
        }
    }

    public T Object => (T)_toAllocate;
}

public static class ObjectsComparer
{
    private static bool StructurallyEqual(object? expected, object? got)
    {
        Debug.Assert(expected != null && got != null && expected.GetType() == got.GetType());
        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
        var fields = expected.GetType().GetFields(flags);
        foreach (var field in fields)
        {
            if (!typeof(MulticastDelegate).IsAssignableFrom(field.FieldType) &&
                !field.Name.Contains("threadid", StringComparison.OrdinalIgnoreCase) &&
                !CompareObjects(field.GetValue(expected), field.GetValue(got)))
            {
                return false;
            }
        }

        return true;
    }

    private static bool ContentwiseEqual(global::System.Array? expected, global::System.Array? got)
    {
        Debug.Assert(expected != null && got != null && expected.GetType() == got.GetType());
        if (expected.Rank != got.Rank)
            return false;
        for (int i = 0; i < expected.Rank; ++i)
            if (expected.GetLength(i) != got.GetLength(i) || expected.GetLowerBound(i) != got.GetLowerBound(i))
                return false;
        var enum1 = expected.GetEnumerator();
        var enum2 = got.GetEnumerator();
        while (enum1.MoveNext() && enum2.MoveNext())
        {
            if (!CompareObjects(enum1.Current, enum2.Current))
                return false;
        }
        return true;
    }

    public static bool CompareObjects(object? expected, object? got)
    {
        if (expected == null)
            return got == null;
        if (got == null)
            return false;
        var type = expected.GetType();
        if (type != got.GetType())
            return false;

        if (Object.ReferenceEquals(expected, got))
            return true;

        if (type == typeof(Pointer) || type.IsPrimitive || expected is string || type.IsEnum)
        {
            // TODO: compare double with epsilon?
            return got.Equals(expected);
        }

        if (expected is global::System.Array array)
            return ContentwiseEqual(array, got as global::System.Array);
        return StructurallyEqual(expected, got);
    }
}
}

namespace project.Tests
{
[TestFixture]
class SearchesTests
{
    [Test, Category("Generated")]
    public void BinarySearchError()
    {
        // act
        Searches.BinarySearch(0, null!);
    }

    [Test, Category("Generated")]
    public void BinarySearchTest()
    {
        // arrange
        int[] a = new int[1];

        // act
        var result = Searches.BinarySearch(0, a);

        // assert
        Assert.AreEqual(0, result);
    }

    [Test, Category("Generated")]
    public void BinarySearchTest1()
    {
        // arrange
        int[] a = new int[0];

        // act
        var result = Searches.BinarySearch(0, a);

        // assert
        Assert.AreEqual(-1, result);
    }

    [Test, Category("Generated")]
    public void BinarySearchTest2()
    {
        // arrange
        int[] a = new int[1];

        // act
        var result = Searches.BinarySearch(1, a);

        // assert
        Assert.AreEqual(-1, result);
    }
}}