예제 #1
0
        async Task RunCallAsync(TableCall originalCall, MirrorTableCall referenceCall)
        {
            // TODO: All assertions should show what the call was.
            // XXX: We currently have no way to detect incorrect interleaving of
            // backend calls and AnnotateLastOutgoingCall here.  Most incorrect
            // interleavings will cause an error on the TablesMachine, but some
            // may go undetected.
            // For now, we're not doing streaming queries at all, so we don't have
            // to worry about how to handle them.

            currentReferenceCall = referenceCall;
            object actualOutcome = await Catching <StorageException> .Task(originalCall(migratingTable));

            // Verify that successfulBatchResult was correct if specified.
            // (Ideally, we'd also catch if it isn't specified when it should
            // be, but that's less of a risk as it will likely cause ETag
            // mismatches anyway.)
            if (successfulBatchResult != null)
            {
                var successfulBatchOutcome = new Outcome <object, StorageException>(successfulBatchResult);
                PSharpRuntime.Assert(BetterComparer.Instance.Equals(successfulBatchOutcome, actualOutcome),
                                     "{0} incorrect successfulBatchResult:\n{1}\nExpected:\n{2}\n", machineId,
                                     BetterComparer.ToString(successfulBatchOutcome), BetterComparer.ToString(actualOutcome));
            }

            PSharpRuntime.Assert(currentReferenceOutcome != null, "The call completed without reporting a linearization point.");
            PSharpRuntime.Assert(BetterComparer.Instance.Equals(actualOutcome, currentReferenceOutcome),
                                 "{0} call outcome:\n{1}\nExpected:\n{2}\n", machineId,
                                 BetterComparer.ToString(actualOutcome), BetterComparer.ToString(currentReferenceOutcome));

            // Reset fields
            currentReferenceCall    = null;
            successfulBatchResult   = null;
            currentReferenceOutcome = null;
        }
예제 #2
0
        internal async Task RunQueryAtomicAsync(TableQuery <DynamicTableEntity> query)
        {
            // async/await pair needed to upcast the return value to object.
            TableCall originalCall = async table => await table.ExecuteQueryAtomicAsync(query);

            MirrorTableCall referenceCall = async referenceTable => await referenceTable.ExecuteQueryAtomicAsync(query);

            Console.WriteLine("{0} starting atomic query: {1}", machineId, query);
            await RunCallAsync(originalCall, referenceCall);
        }
예제 #3
0
        internal async Task RunBatchAsync(TableBatchOperation batch)
        {
            TableBatchOperation batchCopy    = ChainTableUtils.CopyBatch <DynamicTableEntity>(batch);
            TableCall           originalCall = async table => await table.ExecuteBatchAsync(batch);

            MirrorTableCall referenceCall = async referenceTable => await referenceTable.ExecuteMirrorBatchAsync(batchCopy, successfulBatchResult);

            Console.WriteLine("{0} starting batch: {1}", machineId, BetterComparer.ToString(batch));
            await RunCallAsync(originalCall, referenceCall);
        }
예제 #4
0
        // This method does not log what the call is, since there's no way to
        // know what's inside the delegates.  Use RunBatchAsync or RunQueryAtomicAsync.
        async Task RunCallAsync(TableCall originalCall, MirrorTableCall referenceCall)
        {
            // TODO: All assertions should show what the call was.
            // XXX: We currently have no way to detect incorrect interleaving of
            // backend calls and AnnotateLastOutgoingCall here.  Most incorrect
            // interleavings will cause an error on the TablesMachine, but some
            // may go undetected.
            // - FIXME: A missing annotation will cause all machines to become blocked, and
            //   P# considers that a success!  To fix that, we need to enable liveness checking.

            currentReferenceCall = referenceCall;
            object actualOutcome = await Catching <StorageException> .RunAsync(() => originalCall(migratingTable));

            // Verify that successfulBatchResult was correct if specified.
            // (Ideally, we'd also catch if it isn't specified when it should
            // be, but that's less of a risk as it will likely cause ETag
            // mismatches anyway.)
            if (successfulBatchResult != null)
            {
                var successfulBatchOutcome = new Outcome <object, StorageException>(successfulBatchResult);
                PSharpRuntime.Assert(BetterComparer.Instance.Equals(successfulBatchOutcome, actualOutcome),
                                     "{0} incorrect successfulBatchResult:\n{1}\nExpected:\n{2}\n", machineId,
                                     BetterComparer.ToString(successfulBatchOutcome), BetterComparer.ToString(actualOutcome));
            }

            PSharpRuntime.Assert(currentReferenceOutcome != null,
                                 "{0}: The call completed without reporting a linearization point.", machineId);
            PSharpRuntime.Assert(BetterComparer.Instance.Equals(actualOutcome, currentReferenceOutcome),
                                 "{0} table call outcome is incorrect:\n{1}\nExpected:\n{2}\n", machineId,
                                 BetterComparer.ToString(actualOutcome), BetterComparer.ToString(currentReferenceOutcome));

            Console.WriteLine("{0} table call outcome is correct:\n{1}", machineId, BetterComparer.ToString(actualOutcome));

            // Reset fields
            currentReferenceCall    = null;
            successfulBatchResult   = null;
            currentReferenceOutcome = null;
        }
예제 #5
0
        internal static IValue ParseOperand(string code, Program mainProg, IExecutable currentBlock, Parenthesis p, bool constLock)
        {
            code = code.Trim();
            if (code.Length == 0)
            {
                //fct/tab call
                if (p.FunctionName != null)
                {
                    if (constLock)
                    {
                        throw new ILAException("Erreur impossible de donner une valeur non constante");
                    }
                    var call = new FunctionCall();
                    call.CalledFunction = null;
                    call.Args           = new List <IValue>();
                    foreach (var item in mainProg.Methods)
                    {
                        if (item.Name == p.FunctionName && item is Function f)
                        {
                            call.CalledFunction = f;
                            break;
                        }
                    }
                    if (call.CalledFunction == null)
                    {
                        throw new ILAException("Aucune fonction nommée '" + p.FunctionName + "' trouvée");
                    }
                    foreach (var item in p.FctIndexes)
                    {
                        call.Args.Add(ParseParenthesis(item, mainProg, currentBlock, constLock));
                    }
                    return(call);
                }
                else if (p.TabName != null)
                {
                    if (constLock)
                    {
                        throw new ILAException("Erreur impossible de donner une valeur non constante");
                    }
                    var call = new TableCall();
                    call.Table           = null;
                    call.DimensionsIndex = new List <IValue>();
                    foreach (var item in currentBlock.Declarations)
                    {
                        if (item is VariableDeclaration vd && vd.CreatedVariable.Name == p.TabName)
                        {
                            call.Table = vd.CreatedVariable;
                            break;
                        }
                    }
                    if (call.Table == null)
                    {
                        throw new ILAException("Aucune variable nommée '" + p.TabName + "' trouvée");
                    }
                    foreach (var item in p.TabIndexes)
                    {
                        call.DimensionsIndex.Add(ParseParenthesis(item, mainProg, currentBlock, constLock));
                    }
                    return(call);
                }
                else
                {
                    return(null);
                }
            }
            int index = Max(
                code.LastIndexOf('='),
                code.LastIndexOf('☻'),
                code.LastIndexOf('♥'),
                code.LastIndexOf('♦'),
                code.LastIndexOf('<'),
                code.LastIndexOf('>')
                );

            if (index == -1)
            {
                index = code.LastIndexOf('•');
                if (index == -1)
                {
                    index = code.LastIndexOf('◘');
                    if (index == -1)
                    {
                        index = Max(
                            code.LastIndexOf('+'),
                            code.LastIndexOf('-')
                            );
                        if (index == -1)
                        {
                            index = Max(
                                code.LastIndexOf('♣'),
                                code.LastIndexOf('♠'),
                                code.LastIndexOf('*'),
                                code.LastIndexOf('/')
                                );
                            if (index == -1)
                            {
                                //non <val>, ?####, variable, constant, enum, unary minus
                                if (code.First() == '○') //non
                                {
                                    var op = new Operator();
                                    op.Left         = null;
                                    op.OperatorType = Operator.Tag.NOT;
                                    op.Right        = ParseOperand(code.Substring(1), mainProg, currentBlock, p, constLock);
                                    return(op);
                                }
                                else if (code.First() == '◙') //unary minus
                                {
                                    var op = new Operator();
                                    op.Left         = null;
                                    op.OperatorType = Operator.Tag.MINUS;
                                    op.Right        = ParseOperand(code.Substring(1), mainProg, currentBlock, p, constLock);
                                    return(op);
                                }
                                else if (code.First() == '?')//parenthesis group
                                {
                                    int pNumber = int.Parse(code.Substring(1, 4));
                                    return(ParseParenthesis(p.RecursiveParenthesis[pNumber], mainProg, currentBlock, constLock));
                                }
                                else
                                {
                                    //variable, constant, enum
                                    if (IsLetter(code.First()))
                                    {
                                        //variable, enum, bool constant
                                        string n = "";
                                        int    i = 0;
                                        while (IsLetterOrDigit(code[i]))
                                        {
                                            n += code[i++];
                                            if (i == code.Length)
                                            {
                                                break;
                                            }
                                        }
                                        if (n == "vrai")
                                        {
                                            return new ConstantBool()
                                                   {
                                                       Value = true
                                                   }
                                        }
                                        ;
                                        if (n == "faux")
                                        {
                                            return new ConstantBool()
                                                   {
                                                       Value = false
                                                   }
                                        }
                                        ;
                                        //variable, enum
                                        foreach (var decl in mainProg.Declarations)
                                        {
                                            if (decl is TypeDeclaration td && td.CreatedType is EnumType en)
                                            {
                                                for (int j = 0; j < en.Values.Count; j++)
                                                {
                                                    if (en.Values[j] == n)
                                                    {
                                                        //enum call
                                                        return(new EnumCall()
                                                        {
                                                            Enum = en,
                                                            Index = j
                                                        });
                                                    }
                                                }
                                            }
                                        }
                                        //variable
                                        index = -1;
                                        {
                                            int opened = 0;

                                            for (int j = 0; j < code.Length; j++)
                                            {
                                                if ((code[j] == '[' || code[j] == '.') && opened == 0)
                                                {
                                                    index = j;
                                                }
                                                if (code[j] == '[')
                                                {
                                                    opened++;
                                                }
                                                if (code[j] == ']')
                                                {
                                                    opened--;
                                                }
                                            }
                                        }
                                        if (index == -1)
                                        {
                                            //simple variable
                                            foreach (var decl in mainProg.Declarations)
                                            {
                                                if (decl is VariableDeclaration vd && vd.CreatedVariable.Name == n)
                                                {
                                                    if (constLock && !vd.CreatedVariable.Constant)
                                                    {
                                                        throw new ILAException("Erreur impossible de donner une valeur non constante");
                                                    }
                                                    return(vd.CreatedVariable);
                                                }
                                            }
                                            foreach (var decl in currentBlock.Declarations)
                                            {
                                                if (decl is VariableDeclaration vd && vd.CreatedVariable.Name == n)
                                                {
                                                    if (constLock && !vd.CreatedVariable.Constant)
                                                    {
                                                        throw new ILAException("Erreur impossible de donner une valeur non constante");
                                                    }
                                                    return(vd.CreatedVariable);
                                                }
                                            }
                                            if (currentBlock is Module m)
                                            {
                                                foreach (var par in m.Parameters)
                                                {
                                                    if (par.ImportedVariable.Name == n)
                                                    {
                                                        return(par.ImportedVariable);
                                                    }
                                                }
                                            }
                                            throw new ILAException("Aucune variable nommée '" + n + "' trouvée");
                                        }
                                        else if (code[index] == '.')
                                        {
                                            //struct call
                                            if (constLock)
                                            {
                                                throw new ILAException("Erreur impossible de donner une valeur non constante");
                                            }
                                            var left    = code.Substring(0, index);
                                            var right   = code.Substring(index + 1);
                                            var leftVar = ParseValue(left, mainProg, currentBlock, constLock) as Variable;
                                            return(new StructCall()
                                            {
                                                Constant = false,
                                                Name = right,
                                                Struct = leftVar
                                            });

                                            throw new ILAException("Erreur : variable '" + n + "' introuvable dans cette portée");
                                        }
                                        else
                                        {
                                            //table call
                                            if (constLock)
                                            {
                                                throw new ILAException("Erreur impossible de donner une valeur non constante");
                                            }
                                            var left       = code.Substring(0, index);
                                            var right      = code.Substring(index + 1);
                                            var leftVar    = ParseValue(left, mainProg, currentBlock, constLock) as Variable;
                                            var opened     = 0;
                                            var args       = new List <string>();
                                            var currentArg = "";
                                            int j          = 0;
                                            while (right[j] != ']' || opened > 0)
                                            {
                                                if (right[j] == '[')
                                                {
                                                    opened++;
                                                }
                                                if (right[j] == ']')
                                                {
                                                    opened--;
                                                }
                                                if (opened == 0 && right[j] == ',')
                                                {
                                                    args.Add(currentArg);
                                                    currentArg = "";
                                                }
                                                else
                                                {
                                                    currentArg += right[j];
                                                }
                                                j++;
                                            }
                                            args.Add(currentArg);
                                            return(new TableCall()
                                            {
                                                Constant = false,
                                                Table = leftVar,
                                                DimensionsIndex = args.Select(a => ParseValue(a, mainProg, currentBlock, constLock)).ToList()
                                            });

                                            throw new ILAException("Erreur : variable '" + n + "' introuvable dans cette portée");
                                        }
                                    }
                                    else
                                    {
                                        //constant
                                        if (char.IsDigit(code.First()))
                                        {
                                            if (code.Contains('.'))
                                            {
                                                //float
                                                try
                                                {
                                                    return(new ConstantFloat()
                                                    {
                                                        Value = float.Parse(code, new CultureInfo("en"))
                                                    });
                                                }
                                                catch (Exception)
                                                {
                                                    throw new ILAException("Erreur, format de nombre incorrect");
                                                }
                                            }
                                            else
                                            {
                                                //int
                                                try
                                                {
                                                    return(new ConstantInt()
                                                    {
                                                        Value = int.Parse(code, new CultureInfo("en"))
                                                    });
                                                }
                                                catch (Exception)
                                                {
                                                    throw new ILAException("Erreur, format de nombre incorrect");
                                                }
                                            }
                                        }
                                        else if (code.First() == '\'')
                                        {
                                            //char
                                            if (code[1] == '\\')
                                            {
                                                if (code[3] != '\'')
                                                {
                                                    throw new ILAException("Erreur, format de caractere incorrect");
                                                }
                                                return((code[2]) switch
                                                {
                                                    '\'' => new ConstantChar()
                                                    {
                                                        Value = '\''
                                                    },
                                                    '"' => new ConstantChar()
                                                    {
                                                        Value = '"'
                                                    },
                                                    '\\' => new ConstantChar()
                                                    {
                                                        Value = '\\'
                                                    },
                                                    'n' => new ConstantChar()
                                                    {
                                                        Value = '\n'
                                                    },
                                                    'r' => new ConstantChar()
                                                    {
                                                        Value = '\r'
                                                    },
                                                    't' => new ConstantChar()
                                                    {
                                                        Value = '\t'
                                                    },
                                                    'b' => new ConstantChar()
                                                    {
                                                        Value = '\b'
                                                    },
                                                    'f' => new ConstantChar()
                                                    {
                                                        Value = '\f'
                                                    },
                                                    _ => throw new ILAException("Erreur : caractère échapé inconnu '\\" + code[2] + "'"),
                                                });