Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong namespace indents #203

Open
viktoriia-fomina opened this issue Dec 18, 2022 · 0 comments
Open

Wrong namespace indents #203

viktoriia-fomina opened this issue Dec 18, 2022 · 0 comments

Comments

@viktoriia-fomina
Copy link
Collaborator

viktoriia-fomina commented Dec 18, 2022

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);
    }
}}
@viktoriia-fomina viktoriia-fomina changed the title Incorrect namespace generation Wrong namespace indents Dec 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant