text:
/* global expect, it, PEG, describe, jasmine, beforeEach */
"use strict";

// WARNING: this is the OLD, OBSOLETED spec file; the new copy exists in ../../spec/behavior/generated-parser-behavior.spec.js

describe("generated parser behavior", function() {
  beforeEach(function() {
    this.addMatchers(require("./helpers.js"));
  });

  function varyOptimizationOptions(block) {
    function clone(object) {
      var result = {}, key;

      for (key in object) {
        if (object.hasOwnProperty(key)) {
          result[key] = object[key];
        }
      }

      return result;
    }

    var optionsVariants = [
          { cache: false, optimize: "speed" },
          { cache: false, optimize: "size"  },
          { cache: true,  optimize: "speed" },
          { cache: true,  optimize: "size"  },
        ],
        i;

    for (i = 0; i < optionsVariants.length; i++) {
      describe(
        "with options " + jasmine.pp(optionsVariants[i]),
        function() {
          block(clone(optionsVariants[i]));
        }
      );
    }
  }

  describe("parse", function() {
    var grammar = [
          'a = "x" { return "a"; }',
          'b = "x" { return "b"; }',
          'c = "x" { return "c"; }'
        ].join("\n"),
        parser = PEG.buildParser(grammar, { allowedStartRules: ["b", "c"] }),
        parserAll = PEG.buildParser(grammar, { allowedStartRules: "*" });

    describe("start rule", function() {
      describe("without the |startRule| option", function() {
        it("uses the first allowed rule", function() {
          expect(parser).toParse("x", "b");
        });
      });

      describe("when the |startRule| option specifies allowed rule", function() {
        it("uses the specified rule", function() {
          expect(parser).toParse("x", { startRule: "b" }, "b");
          expect(parser).toParse("x", { startRule: "c" }, "c");
        });
      });

      describe("when the |startRule| option specifies disallowed rule", function() {
        it("throws exception", function() {
          expect(parser).toFailToParse("x", { startRule: "a" }, {
            message: "Can't start parsing from rule \"a\"."
          });
        });
      });
    });

    describe("wildcard start rule", function() {
      it("uses any rule", function() {
        expect(parserAll).toParse("x", { startRule: "a" }, "a");
        expect(parserAll).toParse("x", { startRule: "b" }, "b");
        expect(parserAll).toParse("x", { startRule: "c" }, "c");
      });
    });
  });

  describe("parse", function() {
    var parser = PEG.buildParser([
          'a = "ab" { return "ab"; }',
          '  / "b" { return "b"; }'
        ].join("\n"));

    describe("start offset", function() {
      describe("without the |startOffset| option", function() {
        it("starts at the beginning", function() {
          expect(parser).toParse("ab", "ab");
        });
      });

      describe("when the |startOffset| option specifies a position", function() {
        it("starts at the offset", function() {
          expect(parser).toParse("ab", { startOffset: 1 }, "b");
        });
      });
    });
  });

  varyOptimizationOptions(function(options) {
    describe("initializer code", function() {
      it("runs before the parsing begins", function() {
        var parser = PEG.buildParser([
              '{ var result = 42; }',
              'start = "a" { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", 42);
      });

      it("can use the |text| function", function() {
        var parser = PEG.buildParser([
              '{ var result = text(); }',
              'start = "a" { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", "");
      });

      it("can use the |offset| function to get the current parse position", function() {
        var parser = PEG.buildParser([
              '{ var result = offset(); }',
              'start = "a" { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", 0);
      });

      it("can use the |line| and |column| functions to get the current line and column", function() {
        var parser = PEG.buildParser([
              '{ var result = [line(), column()]; }',
              'start = "a" { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", [1, 1]);
      });

      it("can use the |parser| variable to access the parser object", function() {
        var parser = PEG.buildParser([
              '{ var result = parser; }',
              'start = "a" { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", parser);
      });

      it("can use options passed to the parser", function() {
        var parser = PEG.buildParser([
              '{ var result = options; }',
              'start = "a" { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", { a: 42 }, { a: 42 });
      });
    });

    describe("rule matching", function() {
      var grammar = [
            '{ var n = 0; }',
            'start = (a "b") / (a "c") { return n; }',
            'a     = "a" { n++; }'
          ].join("\n");

      if (options.cache) {
        it("caches rule match results", function() {
          var parser = PEG.buildParser(grammar, options);

          expect(parser).toParse("ac", 1);
        });
      } else {
        it("does not cache rule match results", function() {
          var parser = PEG.buildParser(grammar, options);

          expect(parser).toParse("ac", 2);
        });
      }
    });

    describe("named matching", function() {
      var parser = PEG.buildParser('start "start" = "a" start2; start2 "start2" = "a"');

      it("delegates to the expression", function() {
        expect(parser).toParse("aa", ["a", "a"]);
        expect(parser).toFailToParse("b");
      });

      it("overwrites expected string on failure", function() {
        expect(parser).toFailToParse("b", {
          expected: [{ type: "other", description: "start" }]
        });
      });

      it("overwrites expected string on failure of a subrule", function() {
        expect(parser).toFailToParse("ab", {
          expected: [{ type: "other", description: "start2" }]
        });
      });
    });

    describe("choice matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = "a" / "b" / "c"', options);

        expect(parser).toParse("a", "a");
        expect(parser).toParse("b", "b");
        expect(parser).toParse("c", "c");
        expect(parser).toFailToParse("d");
      });
    });

    describe("action code", function() {
      it("tranforms the expression result by returnung a value", function() {
        var parser = PEG.buildParser('start = "a" { return 42; }', options);

        expect(parser).toParse("a", 42);
      });

      it("is not called when the expression does not match", function() {
        var parser = PEG.buildParser(
              'start = "a" { throw "Boom!"; } / "b"',
              options
            );

        expect(parser).toParse("b", "b");
      });

      it("can use label variables", function() {
        var parser = PEG.buildParser('start = a:"a" { return a; }', options);

        expect(parser).toParse("a", "a");
      });

      it("can use the |text| function to get the text matched by the expression", function() {
        var parser = PEG.buildParser(
              'start = "a" "b" "c" { return text(); }',
              options
            );

        expect(parser).toParse("abc", "abc");
      });

      it("can use the |offset| function to get the current parse position", function() {
        var parser = PEG.buildParser(
              'start = "a" ("b" { return offset(); })',
              options
            );

        expect(parser).toParse("ab", ["a", 1]);
      });

      it("can use the |line| and |column| functions to get the current line and column", function() {
        var parser = PEG.buildParser([
              '{ var result; }',
              'start  = line (nl+ line)* { return result; }',
              'line   = thing (" "+ thing)*',
              'thing  = digit / mark',
              'digit  = [0-9]',
              'mark   = "x" { result = [line(), column()]; }',
              'nl     = [\\r"\\n\\u2028\\u2029]'
            ].join("\n"), options);

        expect(parser).toParse("1\n2\n\n3\n\n\n4 5 x", [7, 5]);

        /* Non-Unix newlines */
        expect(parser).toParse("1\rx",   [2, 1]);   // Old Mac
        expect(parser).toParse("1\r\nx", [2, 1]);   // Windows
        expect(parser).toParse("1\n\rx", [3, 1]);   // mismatched

        /* Strange newlines */
        expect(parser).toParse("1\u2028x", [2, 1]);   // line separator
        expect(parser).toParse("1\u2029x", [2, 1]);   // paragraph separator
      });

      it("can use variables defined in the initializer", function() {
        var parser = PEG.buildParser([
              '{ var v = 42 }',
              'start = "a" { return v; }'
            ].join("\n"), options);

        expect(parser).toParse("a", 42);
      });

      it("can use the |expected| function to trigger an error", function() {
        var parser = PEG.buildParser(
              'start = "a" { expected("a"); }',
              options
            );

        expect(parser).toFailToParse("a", {
          message:  'Expected a but "a" found.',
          expected: [{ type: "other", description: "a" }],
          found:    "a",
          offset:   0,
          line:     1,
          column:   1
        });
      });

      it("can use the |error| function to trigger an error", function() {
        var parser = PEG.buildParser(
              'start = "a" { error("a"); }',
              options
            );

        expect(parser).toFailToParse("a", {
          message:  "a",
          expected: null,
          found:    "a",
          offset:   0,
          line:     1,
          column:   1
        });
      });

      it("can use functions defined in the initializer", function() {
        var parser = PEG.buildParser([
              '{ function f() { return 42; } }',
              'start = "a" { return f(); }'
            ].join("\n"), options);

        expect(parser).toParse("a", 42);
      });

      it("can use the |parser| variable to access the parser object", function() {
        var parser = PEG.buildParser(
              'start = "a" { return parser; }',
              options
            );

        expect(parser).toParse("a", parser);
      });

      it("can use options passed to the parser", function() {
        var parser = PEG.buildParser(
              'start = "a" { return options; }',
              options
            );

        expect(parser).toParse("a", { a: 42 }, { a: 42 });
      });
    });

    describe("sequence matching", function() {
      it("does not accept an empty rule", function() {
        expect(function () {
          var parser = PEG.buildParser('start = ', options);
        }).toThrow('Expected "!", "$", "&", "(", ".", character class, comment, end of line, identifier, literal or whitespace but end of input found.');
      });

      it("matches non-empty sequence correctly", function() {
        var parser = PEG.buildParser('start = "a" "b" "c"', options);

        expect(parser).toParse("abc", ["a", "b", "c"]);
      });

      it("does not advance position on failure", function() {
        var parser = PEG.buildParser('start = "a" "b" / "a"', options);

        expect(parser).toParse("a", "a");
      });
    });

    describe("labeled matching", function() {
      it("delegates to the expression", function() {
        var parser = PEG.buildParser('start = a:"a"', options);

        expect(parser).toParse("a", "a");
        expect(parser).toFailToParse("b");
      });
    });

    describe("text matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = $("a" "b" "c")', options);

        expect(parser).toParse("abc", "abc");
      });
    });

    describe("simple and matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = &"a" "a"', options);

        expect(parser).toParse("a", [undefined, "a"]);
        expect(parser).toFailToParse("b");
      });

      it("does not advance position on success", function() {
        var parser = PEG.buildParser('start = &"a" "a"', options);

        expect(parser).toParse("a", [undefined, "a"]);
      });

      it("does not influence expected strings on failure", function() {
        var parser = PEG.buildParser('start = &"a"', options);

        expect(parser).toFailToParse("b", { expected: [] });
      });
    });

    describe("simple not matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = !"a" "b"', options);

        expect(parser).toParse("b", [undefined, "b"]);
        expect(parser).toFailToParse("a");
      });

      it("does not advance position on failure", function() {
        var parser = PEG.buildParser('start = !"a" / "a"', options);

        expect(parser).toParse("a", "a");
      });

      it("does not influence expected strings on failure", function() {
        var parser = PEG.buildParser('start = !"a"', options);

        expect(parser).toFailToParse("a", { expected: [] });
      });
    });

    describe("semantic and code", function() {
      it("causes successful match by returning |true|", function() {
        var parser = PEG.buildParser('start = &{ return true; }', options);

        expect(parser).toParse("", undefined);
      });

      it("causes match failure by returning |false|", function() {
        var parser = PEG.buildParser('start = &{ return false; }', options);

        expect(parser).toFailToParse("");
      });

      it("can use label variables", function() {
        var parser = PEG.buildParser(
              'start = a:"a" &{ return a === "a"; }',
              options
            );

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |text| function", function() {
        var parser = PEG.buildParser(
              'start = "a" &{ return text() === ""; }',
              options
            );

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |offset| function to get the current parse position", function() {
        var parser = PEG.buildParser(
              'start = "a" &{ return offset() === 1; }',
              options
            );

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |line| and |column| functions to get the current line and column", function() {
        var parser = PEG.buildParser([
              '{ var result; }',
              'start  = line (nl+ line)* { return result; }',
              'line   = thing (" "+ thing)*',
              'thing  = digit / mark',
              'digit  = [0-9]',
              'mark   = &{ result = [line(), column()]; return true; } "x"',
              'nl     = ("\\r" / "\\n" / "\\u2028" / "\\u2029")'
            ].join("\n"), options);

        expect(parser).toParse("1\n2\n\n3\n\n\n4 5 x", [7, 5]);

        /* Non-Unix newlines */
        expect(parser).toParse("1\rx",   [2, 1]);   // Old Mac
        expect(parser).toParse("1\r\nx", [2, 1]);   // Windows
        expect(parser).toParse("1\n\rx", [3, 1]);   // mismatched

        /* Strange newlines */
        expect(parser).toParse("1\u2028x", [2, 1]);   // line separator
        expect(parser).toParse("1\u2029x", [2, 1]);   // paragraph separator
      });

      it("can use variables defined in the initializer", function() {
        var parser = PEG.buildParser([
              '{ var v = 42 }',
              'start = "a" &{ return v === 42; }'
            ].join("\n"), options);

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use functions defined in the initializer", function() {
        var parser = PEG.buildParser([
              '{ function f() { return 42; } }',
              'start = "a" &{ return f() === 42; }'
            ].join("\n"), options);

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |parser| variable to access the parser object", function() {
        var parser = PEG.buildParser([
              '{ var result; }',
              'start = "a" &{ result = parser; return true; } { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", parser);
      });

      it("can use options passed to the parser", function() {
        var parser = PEG.buildParser([
              '{ var result; }',
              'start = "a" &{ result = options; return true; } { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", { a: 42 }, { a: 42 });
      });
    });

    describe("semantic not code", function() {
      it("causes successful match by returning |false|", function() {
        var parser = PEG.buildParser('start = !{ return false; }', options);

        expect(parser).toParse("", undefined);
      });

      it("causes match failure by returning |true|", function() {
        var parser = PEG.buildParser('start = !{ return true; }', options);

        expect(parser).toFailToParse();
      });

      it("can use label variables", function() {
        var parser = PEG.buildParser(
              'start = a:"a" !{ return a !== "a"; }',
              options
            );

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |text| function", function() {
        var parser = PEG.buildParser(
              'start = "a" !{ return text() !== ""; }',
              options
            );

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |offset| function to get the current parse position", function() {
        var parser = PEG.buildParser(
              'start = "a" !{ return offset() !== 1; }',
              options
            );

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |line| and |column| functions to get the current line and column", function() {
        var parser = PEG.buildParser([
              '{ var result; }',
              'start  = line (nl+ line)* { return result; }',
              'line   = thing (" "+ thing)*',
              'thing  = digit / mark',
              'digit  = [0-9]',
              'mark   = !{ result = [line(), column()]; return false; } "x"',
              'nl     = ("\\r" / "\\n" / "\\u2028" / "\\u2029")'
            ].join("\n"), options);

        expect(parser).toParse("1\n2\n\n3\n\n\n4 5 x", [7, 5]);

        /* Non-Unix newlines */
        expect(parser).toParse("1\rx",   [2, 1]);   // Old Mac
        expect(parser).toParse("1\r\nx", [2, 1]);   // Windows
        expect(parser).toParse("1\n\rx", [3, 1]);   // mismatched

        /* Strange newlines */
        expect(parser).toParse("1\u2028x", [2, 1]);   // line separator
        expect(parser).toParse("1\u2029x", [2, 1]);   // paragraph separator
      });

      it("can use variables defined in the initializer", function() {
        var parser = PEG.buildParser([
              '{ var v = 42 }',
              'start = "a" !{ return v !== 42; }'
            ].join("\n"), options);

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use functions defined in the initializer", function() {
        var parser = PEG.buildParser([
              '{ function f() { return 42; } }',
              'start = "a" !{ return f() !== 42; }'
            ].join("\n"), options);

        expect(parser).toParse("a", ["a", undefined]);
      });

      it("can use the |parser| variable to access the parser object", function() {
        var parser = PEG.buildParser([
              '{ var result; }',
              'start = "a" !{ result = parser; return false; } { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", parser);
      });

      it("can use options passed to the parser", function() {
        var parser = PEG.buildParser([
              '{ var result; }',
              'start = "a" !{ result = options; return false; } { return result; }'
            ].join("\n"), options);

        expect(parser).toParse("a", { a: 42 }, { a: 42 });
      });
    });

    describe("optional matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = "a"?', options);

        expect(parser).toParse("",  null);
        expect(parser).toParse("a", "a");
      });
    });

    describe("zero or more matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = "a"*', options);

        expect(parser).toParse("",    []);
        expect(parser).toParse("a",   ["a"]);
        expect(parser).toParse("aaa", ["a", "a", "a"]);
      });
    });

    describe("one or more matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = "a"+', options);

        expect(parser).toFailToParse("");
        expect(parser).toParse("a",   ["a"]);
        expect(parser).toParse("aaa", ["a", "a", "a"]);
      });
    });

    describe("range matching", function() {
      describe("without delimiter", function() {
        it("| .. | matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|..|', options);

          expect(parser).toParse("",   []);
          expect(parser).toParse("a",   ["a"]);
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toParse("aaa", ["a", "a", "a"]);
        });

        it("|0.. | matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|0..|', options);

          expect(parser).toParse("",   []);
          expect(parser).toParse("a",   ["a"]);
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toParse("aaa", ["a", "a", "a"]);
        });

        it("|1.. | matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|1..|', options);

          expect(parser).toFailToParse("");
          expect(parser).toParse("a",   ["a"]);
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toParse("aaa", ["a", "a", "a"]);
        });

        it("|2.. | matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2..|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toParse("aaa", ["a", "a", "a"]);
        });

        it("| ..1| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|..1|', options);

          expect(parser).toParse("",    []);
          expect(parser).toParse("a",   ["a"]);
          expect(parser).toFailToParse("aa");
          expect(parser).toFailToParse("aaa");
        });

        it("| ..2| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|..2|', options);

          expect(parser).toParse("",    []);
          expect(parser).toParse("a",   ["a"]);
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toFailToParse("aaa");
        });

        it("|2..3| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2..3|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toParse("aaa", ["a", "a", "a"]);
          expect(parser).toFailToParse("aaaa");
        });

        it("|2..2| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2..2|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toFailToParse("aaa");
        });

        it("|2   | matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("aa",  ["a", "a"]);
          expect(parser).toFailToParse("aaa");
        });

        it("|3..2| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|3..2|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toFailToParse("aa");
          expect(parser).toFailToParse("aaa");
        });
      });

      describe("with delimiter", function() {
        it("| .. , delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|.., "~"|', options);

          expect(parser).toParse("",      []);
          expect(parser).toParse("a",     ["a"]);
          expect(parser).toParse("a~a",   ["a", "a"]);
          expect(parser).toParse("a~a~a", ["a", "a", "a"]);
        });

        it("|0.. , delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|0.., "~"|', options);

          expect(parser).toParse("",      []);
          expect(parser).toParse("a",     ["a"]);
          expect(parser).toParse("a~a",   ["a", "a"]);
          expect(parser).toParse("a~a~a", ["a", "a", "a"]);
        });

        it("|1.. , delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|1.., "~"|', options);

          expect(parser).toFailToParse("");
          expect(parser).toParse("a",     ["a"]);
          expect(parser).toParse("a~a",   ["a", "a"]);
          expect(parser).toParse("a~a~a", ["a", "a", "a"]);
        });

        it("|2.. , delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2.., "~"|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("a~a",   ["a", "a"]);
          expect(parser).toParse("a~a~a", ["a", "a", "a"]);
        });

        it("| ..1, delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|..1, "~"|', options);

          expect(parser).toParse("",    []);
          expect(parser).toParse("a",   ["a"]);
          expect(parser).toFailToParse("a~a");
          expect(parser).toFailToParse("a~a~a");
        });

        it("| ..2, delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|..2, "~"|', options);

          expect(parser).toParse("",     []);
          expect(parser).toParse("a",    ["a"]);
          expect(parser).toParse("a~a",  ["a", "a"]);
          expect(parser).toFailToParse("a~a~a");
        });

        it("|2..3, delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2..3, "~"|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("a~a",   ["a", "a"]);
          expect(parser).toParse("a~a~a", ["a", "a", "a"]);
          expect(parser).toFailToParse("a~a~a~a");
        });

        it("|2..2, delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2..2, "~"|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("a~a",  ["a", "a"]);
          expect(parser).toFailToParse("a~a~a");
        });

        it("|2   , delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|2, "~"|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toParse("a~a",  ["a", "a"]);
          expect(parser).toFailToParse("a~a~a");
        });

        it("|3..2, delimiter| matches correctly", function() {
          var parser = PEG.buildParser('start = "a"|3..2, "~"|', options);

          expect(parser).toFailToParse("");
          expect(parser).toFailToParse("a");
          expect(parser).toFailToParse("a~a");
          expect(parser).toFailToParse("a~a~a");
        });
      });

      it("handle delimiter correctly", function() {
        var parser = PEG.buildParser('start = "a"|2..3, "~"|', options);

        expect(parser).toFailToParse("");
        expect(parser).toFailToParse("a");
        expect(parser).toFailToParse("aa");
        expect(parser).toFailToParse("a~");
        expect(parser).toParse("a~a",   ["a", "a"]);
        expect(parser).toFailToParse("a~a~");
        expect(parser).toParse("a~a~a", ["a", "a", "a"]);
        expect(parser).toFailToParse("a~a~a~");
        expect(parser).toFailToParse("a~a~a~a");
      });
    });

    describe("rule reference matching", function() {
      it("follows rule references", function() {
        var parser = PEG.buildParser([
              'start   = static / dynamic',
              'static  = "C" / "C++" / "Java" / "C#"',
              'dynamic = "Ruby" / "Python" / "JavaScript"'
            ].join("\n"), options);

        expect(parser).toParse("Java",   "Java");
        expect(parser).toParse("Python", "Python");
      });
    });

    describe("literal matching", function() {
      it("matches empty literal correctly", function() {
        var parser = PEG.buildParser('start = ""', options);

        expect(parser).toParse("", "");
      });

      it("matches one-character literal correctly", function() {
        var parser = PEG.buildParser('start = "a"', options);

        expect(parser).toParse("a", "a");
        expect(parser).toFailToParse("b");
      });

      it("matches multi-character literal correctly", function() {
        var parser = PEG.buildParser('start = "abcd"', options);

        expect(parser).toParse("abcd", "abcd");
        expect(parser).toFailToParse("ebcd");
        expect(parser).toFailToParse("afcd");
        expect(parser).toFailToParse("abgd");
        expect(parser).toFailToParse("abch");
      });

      it("is case sensitive without the \"i\" flag", function() {
        var parser = PEG.buildParser('start = "a"', options);

        expect(parser).toParse("a", "a");
        expect(parser).toFailToParse("A");
      });

      it("is case insensitive with the \"i\" flag", function() {
        var parser = PEG.buildParser('start = "a"i', options);

        expect(parser).toParse("a", "a");
        expect(parser).toParse("A", "A");
      });

      it("advances position on success", function() {
        var parser = PEG.buildParser('start = "a" .', options);

        expect(parser).toParse("ab", ["a", "b"]);
      });

      it("sets expectation correctly on failure", function() {
        var parser = PEG.buildParser('start = "a"', options);

        expect(parser).toFailToParse("b", {
          expected: [{ type: "literal", value: "a", description: '"a"' }]
        });
      });
    });

    describe("class matching", function() {
      it("matches empty class correctly", function() {
        var parser = PEG.buildParser('start = []', options);

        expect(parser).toFailToParse("a");
      });

      it("matches class with a character list correctly", function() {
        var parser = PEG.buildParser('start = [abc]', options);

        expect(parser).toParse("a", "a");
        expect(parser).toParse("b", "b");
        expect(parser).toParse("c", "c");
        expect(parser).toFailToParse("d");
      });

      it("matches class with a range correctly", function() {
        var parser = PEG.buildParser('start = [a-c]', options);

        expect(parser).toParse("a", "a");
        expect(parser).toParse("b", "b");
        expect(parser).toParse("c", "c");
        expect(parser).toFailToParse("d");
      });

      it("matches inverted class correctly", function() {
        var parser = PEG.buildParser('start = [^a]', options);

        expect(parser).toFailToParse("a");
        expect(parser).toParse("b", "b");
      });

      it("is case sensitive without the \"i\" flag", function() {
        var parser = PEG.buildParser('start = [a]', options);

        expect(parser).toParse("a", "a");
        expect(parser).toFailToParse("A");
      });

      it("is case insensitive with the \"i\" flag", function() {
        var parser = PEG.buildParser('start = [a]i', options);

        expect(parser).toParse("a", "a");
        expect(parser).toParse("A", "A");
      });

      it("advances position on success", function() {
        var parser = PEG.buildParser('start = [a] .', options);

        expect(parser).toParse("ab", ["a", "b"]);
      });

      it("sets expectation correctly on failure", function() {
        var parser = PEG.buildParser('start = [a]', options);

        expect(parser).toFailToParse("b", {
          expected: [{ type: "class", value: "[a]", description: "[a]" }]
        });
      });
    });

    describe("any matching", function() {
      it("matches correctly", function() {
        var parser = PEG.buildParser('start = .', options);

        expect(parser).toParse("a", "a");
      });

      it("advances position on success", function() {
        var parser = PEG.buildParser('start = . .', options);

        expect(parser).toParse("ab", ["a", "b"]);
      });

      it("sets expectation correctly on failure", function() {
        var parser = PEG.buildParser('start = .', options);

        expect(parser).toFailToParse("", {
          expected: [{ type: "any", description: "any character" }]
        });
      });
    });

    describe("error reporting", function() {
      describe("behavior", function() {
        it("reports only the rightmost error", function() {
          var parser = PEG.buildParser('start = "a" "b" / "a" "c" "d"', options);

          expect(parser).toFailToParse("ace", {
            offset:   2,
            expected: [{ type: "literal", value: "d", description: '"d"' }]
          });
        });
      });

      describe("expectations reporting", function() {
        it("reports expectations correctly with no alternative", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("ab", {
            expected: [{ type: "end", description: "end of input" }]
          });
        });

        it("reports expectations correctly with one alternative", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("b", {
            expected: [{ type: "literal", value: "a", description: '"a"' }]
          });
        });

        it("reports expectations correctly with multiple alternatives", function() {
          var parser = PEG.buildParser('start = "a" / "b" / "c"', options);

          expect(parser).toFailToParse("d", {
            expected: [
              { type: "literal", value: "a", description: '"a"' },
              { type: "literal", value: "b", description: '"b"' },
              { type: "literal", value: "c", description: '"c"' }
            ]
          });
        });

        it("removes duplicates from expectations", function() {
          /*
           * There was a bug in the code that manifested only with three
           * duplicates. This is why the following test uses three choices
           * instead of seemingly sufficient two.
           *
           * See https://github.com/pegjs/pegjs/pull/146.
           */
          var parser = PEG.buildParser('start = "a" / "a" / "a"', options);

          expect(parser).toFailToParse("b", {
            expected: [{ type: "literal", value: "a", description: '"a"' }]
          });
        });

        it("sorts expectations", function() {
          var parser = PEG.buildParser('start = "c" / "b" / "a"', options);

          expect(parser).toFailToParse("d", {
            expected: [
              { type: "literal", value: "a", description: '"a"' },
              { type: "literal", value: "b", description: '"b"' },
              { type: "literal", value: "c", description: '"c"' }
            ]
          });
        });
      });

      describe("found string reporting", function() {
        it("reports found string correctly at the end of input", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("", { found: null });
        });

        it("reports found string correctly in the middle of input", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("b", { found: "b" });
        });
      });

      describe("message building", function() {
        it("builds message correctly with no alternative", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("ab", {
            message: 'Expected end of input but "b" found.'
          });
        });

        it("builds message correctly with one alternative", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("b", {
            message: 'Expected "a" but "b" found.'
          });
        });

        it("builds message correctly with multiple alternatives", function() {
          var parser = PEG.buildParser('start = "a" / "b" / "c"', options);

          expect(parser).toFailToParse("d", {
            message: 'Expected "a", "b" or "c" but "d" found.'
          });
        });

        it("builds message correctly at the end of input", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("", {
            message: 'Expected "a" but end of input found.'
          });
        });

        it("builds message correctly in the middle of input", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("b", {
            message: 'Expected "a" but "b" found.'
          });
        });
      });

      describe("position reporting", function() {
        it("reports position correctly with invalid input", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("b", {
            location: {
              start: { offset: 0, line: 1, column: 1 },
              end:   { offset: 1, line: 1, column: 2 }
            }
          });
        });

        it("reports position correctly with trailing input", function() {
          var parser = PEG.buildParser('start = "a"', options);

          expect(parser).toFailToParse("aa", {
            location: {
              start: { offset: 1, line: 1, column: 2 },
              end:   { offset: 2, line: 1, column: 3 }
            }
          });
        });

        it("reports position correctly in complex cases", function() {
          var parser = PEG.buildParser([
                'start  = line (nl+ line)*',
                'line   = digit (" "+ digit)*',
                'digit  = [0-9]',
                'nl     = [\\r\\n\\u2028\\u2029]'
              ].join("\n"), options);

          expect(parser).toFailToParse("1\n2\n\n3\n\n\n4 5 x", {
            location: {
              start: { offset: 13, line: 7, column: 5 },
              end:   { offset: 14, line: 7, column: 6 }
            }
          });

          /* Non-Unix newlines */
          expect(parser).toFailToParse("1\rx", {     // Old Mac
            location: {
              start: { offset: 2, line: 2, column: 1 },
              end:   { offset: 3, line: 2, column: 2 }
            }
          });
          expect(parser).toFailToParse("1\r\nx", {   // Windows
            location: {
              start: { offset: 3, line: 2, column: 1 },
              end:   { offset: 4, line: 2, column: 2 }
            }
          });
          expect(parser).toFailToParse("1\n\rx", {   // mismatched
            location: {
              start: { offset: 3, line: 3, column: 1 },
              end:   { offset: 4, line: 3, column: 2 }
            }
          });

          /* Strange newlines */
          expect(parser).toFailToParse("1\u2028x", {   // line separator
            location: {
              start: { offset: 2, line: 2, column: 1 },
              end:   { offset: 3, line: 2, column: 2 }
            }
          });
          expect(parser).toFailToParse("1\u2029x", {   // paragraph separator
            location: {
              start: { offset: 2, line: 2, column: 1 },
              end:   { offset: 3, line: 2, column: 2 }
            }
          });
        });
      });
    });

    describe("allowed start rules", function() {
      var grammar = [
            'a = "x"',
            'b = "x"',
            'c = "x"'
          ].join("\n");

      describe("without the |allowedStartRules| option", function() {
        var parser = PEG.buildParser(grammar);

        it("allows the first rule", function() {
          expect(parser).toParse("x", { startRule: "a" }, "x");
        });

        it("does not allow any other rules", function() {
          expect(parser).toFailToParse("x", { startRule: "b" }, { });
          expect(parser).toFailToParse("x", { startRule: "c" }, { });
        });
      });

      describe("with the |allowedStartRules| option", function() {
        var parser = PEG.buildParser(grammar, { allowedStartRules: ["b", "c"] });

        it("allows the specified rules", function() {
          expect(parser).toParse("x", { startRule: "b" }, "x");
          expect(parser).toParse("x", { startRule: "c" }, "x");
        });

        it("does not allow any other rules", function() {
          expect(parser).toFailToParse("x", { startRule: "a" }, { });
        });
      });
    });

    describe("output", function() {
      var grammar = 'start = "a"';

      describe("without the |output| option", function() {
        it("returns a parser object", function() {
          var parser = PEG.buildParser(grammar);

          expect(typeof parser).toBe("object");
          expect(parser).toParse("a", "a");
        });
      });

      describe("when the |output| option is set to \"parser\"", function() {
        it("returns a parser object", function() {
          var parser = PEG.buildParser(grammar, { output: "parser" });

          expect(typeof parser).toBe("object");
          expect(parser).toParse("a", "a");
        });
      });

      describe("when the |output| option is set to \"source\"", function() {
        it("returns a parser source code", function() {
          var source = PEG.buildParser(grammar, { output: "source" });

          expect(typeof source).toBe("string");
          expect(eval(source)).toParse("a", "a");
        });
      });
    });

    describe("exportVar", function() {
      var grammar = 'start = "a"';

      describe("without the |exportVar| option", function() {
        it("get a parser object", function() {
          var source = PEG.buildParser(grammar, { output: "source" });

          var root = {};
          (function() {
            eval(source);
          }).call(root);

          expect(typeof root.PEG).toBe("object");
          expect(root.PEG).toParse("a", "a");
        });
      });

      describe("when the |exportVar| option is set to \"parser\"", function() {
        it("returns a parser object", function() {
          var source = PEG.buildParser(grammar, { output: "source", exportVar: "parser" });

          var root = {};
          (function() {
            eval(source);
          }).call(root);

          expect(typeof root.parser).toBe("object");
          expect(root.parser).toParse("a", "a");
        });
      });
    });

    /*
     * Following examples are from Wikipedia, see
     * http://en.wikipedia.org/w/index.php?title=Parsing_expression_grammar&oldid=335106938.
     */
    describe("complex examples", function() {
      it("handles arithmetics example correctly", function() {
        /*
         * Value   ← [0-9]+ / '(' Expr ')'
         * Product ← Value (('*' / '/') Value)*
         * Sum     ← Product (('+' / '-') Product)*
         * Expr    ← Sum
         */
        var parser = PEG.buildParser([
              'Expr    = Sum',
              'Sum     = first:Product rest:(("+" / "-") Product)* {',
              '            var result = first, i;',
              '            for (i = 0; i < rest.length; i++) {',
              '              if (rest[i][0] == "+") { result += rest[i][1]; }',
              '              if (rest[i][0] == "-") { result -= rest[i][1]; }',
              '            }',
              '            return result;',
              '          }',
              'Product = first:Value rest:(("*" / "/") Value)* {',
              '            var result = first, i;',
              '            for (i = 0; i < rest.length; i++) {',
              '              if (rest[i][0] == "*") { result *= rest[i][1]; }',
              '              if (rest[i][0] == "/") { result /= rest[i][1]; }',
              '            }',
              '            return result;',
              '          }',
              'Value   = digits:[0-9]+     { return parseInt(digits.join(""), 10); }',
              '        / "(" expr:Expr ")" { return expr; }'
            ].join("\n"), options);

        /* The "value" rule */
        expect(parser).toParse("0",       0);
        expect(parser).toParse("123",     123);
        expect(parser).toParse("(42+43)", 42+43);

        /* The "product" rule */
        expect(parser).toParse("42",          42);
        expect(parser).toParse("42*43",       42*43);
        expect(parser).toParse("42*43*44*45", 42*43*44*45);
        expect(parser).toParse("42/43",       42/43);
        expect(parser).toParse("42/43/44/45", 42/43/44/45);

        /* The "sum" rule */
        expect(parser).toParse("42*43",                   42*43);
        expect(parser).toParse("42*43+44*45",             42*43+44*45);
        expect(parser).toParse("42*43+44*45+46*47+48*49", 42*43+44*45+46*47+48*49);
        expect(parser).toParse("42*43-44*45",             42*43-44*45);
        expect(parser).toParse("42*43-44*45-46*47-48*49", 42*43-44*45-46*47-48*49);

        /* The "expr" rule */
        expect(parser).toParse("42+43", 42+43);

        /* Complex test */
        expect(parser).toParse("(1+2)*(3+4)", (1+2)*(3+4));
      });

      it("handles non-context-free language correctly", function() {
        /* The following parsing expression grammar describes the classic
         * non-context-free language { a^n b^n c^n : n >= 1 }:
         *
         * S ← &(A c) a+ B !(a/b/c)
         * A ← a A? b
         * B ← b B? c
         */
        var parser = PEG.buildParser([
              'S = &(A "c") a:"a"+ B:B !("a" / "b" / "c") { return a.join("") + B; }',
              'A = a:"a" A:A? b:"b" { return [a, A, b].join(""); }',
              'B = b:"b" B:B? c:"c" { return [b, B, c].join(""); }'
            ].join("\n"), options);

        expect(parser).toParse("abc",       "abc");
        expect(parser).toParse("aaabbbccc", "aaabbbccc");
        expect(parser).toFailToParse("aabbbccc");
        expect(parser).toFailToParse("aaaabbbccc");
        expect(parser).toFailToParse("aaabbccc");
        expect(parser).toFailToParse("aaabbbbccc");
        expect(parser).toFailToParse("aaabbbcc");
        expect(parser).toFailToParse("aaabbbcccc");
      });

      it("handles nested comments example correctly", function() {
        /*
         * Begin ← "(*"
         * End ← "*)"
         * C ← Begin N* End
         * N ← C / (!Begin !End Z)
         * Z ← any single character
         */
        var parser = PEG.buildParser([
              'C     = begin:Begin ns:N* end:End { return begin + ns.join("") + end; }',
              'N     = C',
              '      / !Begin !End z:Z { return z; }',
              'Z     = .',
              'Begin = "(*"',
              'End   = "*)"'
            ].join("\n"), options);

        expect(parser).toParse("(**)",     "(**)");
        expect(parser).toParse("(*abc*)",  "(*abc*)");
        expect(parser).toParse("(*(**)*)", "(*(**)*)");
        expect(parser).toParse(
          "(*abc(*def*)ghi(*(*(*jkl*)*)*)mno*)",
          "(*abc(*def*)ghi(*(*(*jkl*)*)*)mno*)"
        );
      });
    });
  });

  var exports = false; // typeof exports !== "object" in eval context.
  describe("publish module", function() {
    var grammar = 'start = "a"';

    describe("AMD style", function() {
      it("get a parser object", function() {
        var source = PEG.buildParser(grammar, { output: "source" });

        var factory;
        function define (func) {
          factory = func;
        }
        define.amd = true;

        var root = {
          define: define
        };
        (function() {
          eval(source);
        }).call(root);

        var parser = factory();
        expect(typeof parser).toBe("object");
        expect(parser).toParse("a", "a");
      });
    });

    describe("CommonJS style", function() {
      it("get a parser object", function() {
        var source = PEG.buildParser(grammar, { output: "source" });

        var module = { exports: {} };
        var exports = {};
        eval(source);

        var parser = module.exports;
        expect(typeof parser).toBe("object");
        expect(parser).toParse("a", "a");
      });
    });

    describe("PEG.js style", function() {
      it("get a parser object", function() {
        var source = PEG.buildParser(grammar, { output: "source" });

        var modules = { define: function() {} };
        var module = {};
        eval(source);

        var parser = module.exports;
        expect(typeof parser).toBe("object");
        expect(parser).toParse("a", "a");
      });
    });

    describe("Web Browser style", function() {
      it("get a parser object", function() {
        var source = PEG.buildParser(grammar, { output: "source" });

        var root = {
        };
        (function() {
          eval(source);
        }).call(root);

        var parser = root.PEG;
        expect(typeof parser).toBe("object");
        expect(parser).toParse("a", "a");
      });
    });
  });
});


text:
import os
from unittest import mock

import ddt
from nova import block_device
from nova import exception
from nova.virt import driver
from os_win import exceptions as os_win_exc
from oslo_utils import units

from compute_hyperv.nova import constants
from compute_hyperv.nova import migrationops
from compute_hyperv.tests import fake_instance
from compute_hyperv.tests.unit import test_base

@ddt.ddt
class MigrationOpsTestCase(test_base.HyperVBaseTestCase):
    """Unit tests for the Hyper-V MigrationOps class."""

    _autospec_classes = [
        migrationops.pathutils.PathUtils,
        migrationops.volumeops.VolumeOps,
        migrationops.vmops.VMOps,
        migrationops.imagecache.ImageCache,
        migrationops.block_device_manager.BlockDeviceInfoManager,
    ]

    _FAKE_DISK = 'fake_disk'
    _FAKE_TIMEOUT = 10
    _FAKE_RETRY_INTERVAL = 5

    def setUp(self):
        super(MigrationOpsTestCase, self).setUp()
        self.context = 'fake-context'

        self._migrationops = migrationops.MigrationOps()
        self._vmops = self._migrationops._vmops
        self._vmutils = self._migrationops._vmutils
        self._pathutils = self._migrationops._pathutils
        self._vhdutils = self._migrationops._vhdutils
        self._volumeops = self._migrationops._volumeops
        self._imagecache = self._migrationops._imagecache
        self._block_dev_man = self._migrationops._block_dev_man

    def test_move_vm_files(self):
        mock_instance = fake_instance.fake_instance_obj(self.context)

        vm_files_path = self._migrationops._move_vm_files(mock_instance)

        mock_get_inst_dir = self._migrationops._pathutils.get_instance_dir
        mock_get_inst_dir.assert_called_once_with(mock_instance.name)
        mock_get_revert_dir = (
            self._migrationops._pathutils.get_instance_migr_revert_dir)
        mock_get_revert_dir.assert_called_once_with(
            mock_get_inst_dir.return_value, remove_dir=True, create_dir=True)
        mock_get_export_dir = self._migrationops._pathutils.get_export_dir
        mock_get_export_dir.assert_called_once_with(
            instance_dir=mock_get_revert_dir.return_value, create_dir=True)

        mock_move = self._migrationops._pathutils.move_folder_files
        mock_move.assert_called_once_with(mock_get_inst_dir.return_value,
                                          mock_get_revert_dir.return_value)
        copy_config_files = self._migrationops._pathutils.copy_vm_config_files
        copy_config_files.assert_called_once_with(
            mock_instance.name, mock_get_export_dir.return_value)
        self.assertEqual(mock_get_revert_dir.return_value, vm_files_path)

    @ddt.data({},
              {'ephemerals_size': 2},
              {'ephemerals_size': 3, 'flavor_eph_size': 0},
              {'ephemerals_size': 3, 'expect_invalid_flavor': True},
              {'current_root_gb': 3, 'expect_invalid_flavor': True},
              {'current_root_gb': 3, 'boot_from_vol': True})
    @ddt.unpack
    @mock.patch.object(driver, 'block_device_info_get_ephemerals')
    @mock.patch.object(block_device, 'get_bdm_ephemeral_disk_size')
    def test_check_target_flavor(self, mock_get_eph_size, mock_get_eph,
                                 ephemerals_size=0,
                                 flavor_eph_size=2,
                                 flavor_root_gb=2,
                                 current_root_gb=1,
                                 boot_from_vol=False,
                                 expect_invalid_flavor=False):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        mock_instance.flavor.root_gb = current_root_gb
        mock_flavor = mock.MagicMock(root_gb=flavor_root_gb,
                                     ephemeral_gb=flavor_eph_size)

        mock_get_eph_size.return_value = ephemerals_size
        self._block_dev_man.is_boot_from_volume.return_value = boot_from_vol

        if expect_invalid_flavor:
            self.assertRaises(exception.InstanceFaultRollback,
                              self._migrationops._check_target_flavor,
                              mock_instance, mock_flavor,
                              mock.sentinel.block_device_info)
        else:
            self._migrationops._check_target_flavor(
                mock_instance, mock_flavor, mock.sentinel.block_device_info)

        mock_get_eph.assert_called_once_with(mock.sentinel.block_device_info)
        mock_get_eph_size.assert_called_once_with(mock_get_eph.return_value)
        self._block_dev_man.is_boot_from_volume.assert_called_once_with(
            mock.sentinel.block_device_info)

    def test_check_and_attach_config_drive(self):
        mock_instance = fake_instance.fake_instance_obj(
            self.context, expected_attrs=['system_metadata'])
        mock_instance.config_drive = 'True'

        self._migrationops._check_and_attach_config_drive(
            mock_instance, mock.sentinel.vm_gen)

        self._migrationops._vmops.attach_config_drive.assert_called_once_with(
            mock_instance,
            self._migrationops._pathutils.lookup_configdrive_path.return_value,
            mock.sentinel.vm_gen)

    def test_check_and_attach_config_drive_unknown_path(self):
        instance = fake_instance.fake_instance_obj(
            self.context, expected_attrs=['system_metadata'])
        instance.config_drive = 'True'
        self._migrationops._pathutils.lookup_configdrive_path.return_value = (
            None)
        self.assertRaises(exception.ConfigDriveNotFound,
                          self._migrationops._check_and_attach_config_drive,
                          instance,
                          mock.sentinel.FAKE_VM_GEN)

    @mock.patch.object(migrationops.MigrationOps, '_move_vm_files')
    @mock.patch.object(migrationops.MigrationOps, '_check_target_flavor')
    def test_migrate_disk_and_power_off(self, mock_check_flavor,
                                        mock_move_vm_files):
        instance = mock.MagicMock()
        instance.system_metadata = {}
        flavor = mock.MagicMock()
        network_info = mock.MagicMock()

        disk_info = self._migrationops.migrate_disk_and_power_off(
            self.context, instance, mock.sentinel.FAKE_DEST, flavor,
            network_info, mock.sentinel.bdi,
            self._FAKE_TIMEOUT, self._FAKE_RETRY_INTERVAL)

        self.assertEqual(mock_move_vm_files.return_value, disk_info)
        mock_check_flavor.assert_called_once_with(
            instance, flavor, mock.sentinel.bdi)
        self._migrationops._vmops.power_off.assert_called_once_with(
            instance, self._FAKE_TIMEOUT, self._FAKE_RETRY_INTERVAL)
        mock_move_vm_files.assert_called_once_with(instance)
        self.assertEqual(mock_move_vm_files.return_value,
                         instance.system_metadata['backup_location'])
        instance.save.assert_called_once_with()
        self._migrationops._vmops.destroy.assert_called_once_with(
            instance, network_info, mock.sentinel.bdi, destroy_disks=True,
            cleanup_migration_files=False)

    def test_confirm_migration(self):
        mock_instance = fake_instance.fake_instance_obj(
            self.context, expected_attrs=['system_metadata'])
        fake_path_revert = 'fake_path_revert'
        mock_instance.system_metadata['backup_location'] = fake_path_revert

        self._migrationops.confirm_migration(
            context=self.context,
            migration=mock.sentinel.migration, instance=mock_instance,
            network_info=mock.sentinel.network_info)

        get_export_dir = self._migrationops._pathutils.get_export_dir
        get_export_dir.assert_called_once_with(instance_dir=fake_path_revert)
        self._migrationops._pathutils.check_dir.assert_has_calls([
            mock.call(get_export_dir.return_value, remove_dir=True),
            mock.call(fake_path_revert, remove_dir=True)])

    def test_revert_migration_files(self):
        mock_instance = fake_instance.fake_instance_obj(
            self.context, expected_attrs=['system_metadata'])
        fake_path_revert = 'fake_path_revert'
        mock_instance.system_metadata['backup_location'] = fake_path_revert

        instance_path = self._migrationops._revert_migration_files(
            mock_instance)

        expected_instance_path = fake_path_revert.rstrip('_revert')
        self.assertEqual(expected_instance_path, instance_path)
        self._migrationops._pathutils.rename.assert_called_once_with(
            fake_path_revert, expected_instance_path)

    @mock.patch.object(migrationops.MigrationOps, '_import_and_setup_vm')
    @mock.patch.object(migrationops.MigrationOps, '_revert_migration_files')
    def test_finish_revert_migration(self, mock_revert_migration_files,
                                     mock_import_and_setup_vm):
        mock_instance = fake_instance.fake_instance_obj(self.context)

        self._migrationops.finish_revert_migration(
            context=self.context, instance=mock_instance,
            network_info=mock.sentinel.network_info,
            block_device_info=mock.sentinel.block_device_info,
            power_on=True)

        mock_revert_migration_files.assert_called_once_with(
            mock_instance)
        image_meta = self._imagecache.get_image_details.return_value
        mock_import_and_setup_vm.assert_called_once_with(
            self.context, mock_instance,
            mock_revert_migration_files.return_value,
            image_meta, mock.sentinel.block_device_info)
        self._migrationops._vmops.power_on.assert_called_once_with(
            mock_instance, network_info=mock.sentinel.network_info)

    def test_merge_base_vhd(self):
        fake_diff_vhd_path = 'fake/diff/path'
        fake_base_vhd_path = 'fake/base/path'
        base_vhd_copy_path = os.path.join(
            os.path.dirname(fake_diff_vhd_path),
            os.path.basename(fake_base_vhd_path))

        self._migrationops._merge_base_vhd(diff_vhd_path=fake_diff_vhd_path,
                                           base_vhd_path=fake_base_vhd_path)

        self._migrationops._pathutils.copyfile.assert_called_once_with(
            fake_base_vhd_path, base_vhd_copy_path)
        recon_parent_vhd = self._migrationops._vhdutils.reconnect_parent_vhd
        recon_parent_vhd.assert_called_once_with(fake_diff_vhd_path,
                                                 base_vhd_copy_path)
        self._migrationops._vhdutils.merge_vhd.assert_called_once_with(
            fake_diff_vhd_path)
        self._migrationops._pathutils.rename.assert_called_once_with(
            base_vhd_copy_path, fake_diff_vhd_path)

    def test_merge_base_vhd_exception(self):
        fake_diff_vhd_path = 'fake/diff/path'
        fake_base_vhd_path = 'fake/base/path'
        base_vhd_copy_path = os.path.join(
            os.path.dirname(fake_diff_vhd_path),
            os.path.basename(fake_base_vhd_path))

        self._migrationops._vhdutils.reconnect_parent_vhd.side_effect = (
            os_win_exc.HyperVException)
        self._migrationops._pathutils.exists.return_value = True

        self.assertRaises(os_win_exc.HyperVException,
                          self._migrationops._merge_base_vhd,
                          fake_diff_vhd_path, fake_base_vhd_path)
        self._migrationops._pathutils.exists.assert_called_once_with(
            base_vhd_copy_path)
        self._migrationops._pathutils.remove.assert_called_once_with(
            base_vhd_copy_path)

    @mock.patch.object(migrationops.MigrationOps, '_resize_vhd')
    def test_check_resize_vhd(self, mock_resize_vhd):
        self._migrationops._check_resize_vhd(
            vhd_path=mock.sentinel.vhd_path, vhd_info={'VirtualSize': 1},
            new_size=2)
        mock_resize_vhd.assert_called_once_with(mock.sentinel.vhd_path, 2)

    def test_check_resize_vhd_exception(self):
        self.assertRaises(exception.CannotResizeDisk,
                          self._migrationops._check_resize_vhd,
                          mock.sentinel.vhd_path,
                          {'VirtualSize': 1}, 0)

    @mock.patch.object(migrationops.MigrationOps, '_merge_base_vhd')
    def test_resize_vhd(self, mock_merge_base_vhd):
        fake_vhd_path = 'fake/path.vhd'
        new_vhd_size = 2
        self._migrationops._resize_vhd(vhd_path=fake_vhd_path,
                                       new_size=new_vhd_size)

        get_vhd_parent_path = self._migrationops._vhdutils.get_vhd_parent_path
        get_vhd_parent_path.assert_called_once_with(fake_vhd_path)
        mock_merge_base_vhd.assert_called_once_with(
            fake_vhd_path,
            self._migrationops._vhdutils.get_vhd_parent_path.return_value)
        self._migrationops._vhdutils.resize_vhd.assert_called_once_with(
            fake_vhd_path, new_vhd_size)

    def test_check_base_disk(self):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        fake_src_vhd_path = 'fake/src/path'
        fake_base_vhd = 'fake/vhd'
        get_cached_image = self._migrationops._imagecache.get_cached_image
        get_cached_image.return_value = fake_base_vhd

        self._migrationops._check_base_disk(
            context=self.context, instance=mock_instance,
            diff_vhd_path=mock.sentinel.diff_vhd_path,
            src_base_disk_path=fake_src_vhd_path)

        get_cached_image.assert_called_once_with(self.context, mock_instance)
        recon_parent_vhd = self._migrationops._vhdutils.reconnect_parent_vhd
        recon_parent_vhd.assert_called_once_with(
            mock.sentinel.diff_vhd_path, fake_base_vhd)

    @ddt.data((False, '\\\\fake-srv\\C$\\inst_dir_0000000e_revert', True),
              (False, '\\\\fake-srv\\share_path\\inst_dir_0000000e_revert'),
              (True, 'C:\\fake_inst_dir_0000000e_revert'))
    @ddt.unpack
    def test_migrate_disks_from_source(self, move_disks_on_migration,
                                       source_inst_dir, is_remote_path=False):
        self.flags(move_disks_on_cold_migration=move_disks_on_migration,
                   group='hyperv')
        mock_migration = mock.MagicMock()
        mock_instance = fake_instance.fake_instance_obj(self.context)
        mock_get_remote_path = self._migrationops._pathutils.get_remote_path
        mock_get_remote_path.return_value = source_inst_dir

        mock_get_export_dir = self._migrationops._pathutils.get_export_dir
        mock_get_export_dir.side_effect = [mock.sentinel.source_export_dir,
                                           mock.sentinel.dest_export_dir]

        instance_dir = self._migrationops._migrate_disks_from_source(
            mock_migration, mock_instance, mock.sentinel.source_dir)

        mock_get_remote_path.assert_called_once_with(
            mock_migration.source_compute, mock.sentinel.source_dir)

        if move_disks_on_migration or is_remote_path:
            mock_get_inst_dir = self._migrationops._pathutils.get_instance_dir
            mock_get_inst_dir.assert_called_once_with(
                mock_instance.name, create_dir=True, remove_dir=True)
            expected_inst_dir = mock_get_inst_dir.return_value
        else:
            expected_inst_dir = source_inst_dir[0: - len('_revert')]
            self._migrationops._pathutils.check_dir.assert_called_once_with(
                expected_inst_dir, create_dir=True)

        mock_get_export_dir.assert_has_calls([
            mock.call(instance_dir=mock_get_remote_path.return_value),
            mock.call(instance_dir=expected_inst_dir)])

        mock_copy = self._migrationops._pathutils.copy_folder_files
        mock_copy.assert_called_once_with(mock_get_remote_path.return_value,
                                          expected_inst_dir)
        self._migrationops._pathutils.copy_dir.assert_called_once_with(
            mock.sentinel.source_export_dir, mock.sentinel.dest_export_dir)
        self.assertEqual(expected_inst_dir, instance_dir)

    @mock.patch.object(migrationops.MigrationOps, '_import_and_setup_vm')
    @mock.patch.object(migrationops.MigrationOps, '_migrate_disks_from_source')
    def test_finish_migration(self, mock_migrate_disks_from_source,
                              mock_import_and_setup_vm):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        mock_migration = mock.MagicMock()

        self._migrationops.finish_migration(
            context=self.context, migration=mock_migration,
            instance=mock_instance, disk_info=mock.sentinel.disk_info,
            network_info=mock.sentinel.network_info,
            image_meta=mock.sentinel.image_meta, resize_instance=False,
            block_device_info=mock.sentinel.block_device_info)

        mock_migrate_disks_from_source.assert_called_once_with(
            mock_migration, mock_instance, mock.sentinel.disk_info)
        mock_import_and_setup_vm.assert_called_once_with(
            self.context, mock_instance,
            mock_migrate_disks_from_source.return_value,
            mock.sentinel.image_meta, mock.sentinel.block_device_info, True)
        self._vmops.power_on.assert_called_once_with(
            mock_instance, network_info=mock.sentinel.network_info)

    @mock.patch.object(migrationops.MigrationOps, '_check_ephemeral_disks')
    @mock.patch.object(migrationops.MigrationOps, '_check_and_update_disks')
    @mock.patch.object(migrationops.MigrationOps, '_update_disk_image_paths')
    @mock.patch.object(migrationops.MigrationOps, '_import_vm')
    def test_import_and_setup_vm(self, mock_import_vm,
                                 mock_update_disk_image_paths,
                                 mock_check_and_update_disks,
                                 mock_check_eph_disks):
        block_device_info = {'ephemerals': mock.sentinel.ephemerals}
        mock_instance = fake_instance.fake_instance_obj(self.context)

        self._migrationops._import_and_setup_vm(
            self.context, mock_instance, mock.sentinel.instance_dir,
            mock.sentinel.image_meta, block_device_info,
            resize_instance=mock.sentinel.resize_instance)

        get_image_vm_gen = self._vmops.get_image_vm_generation
        get_image_vm_gen.assert_called_once_with(mock_instance.uuid,
                                                 mock.sentinel.image_meta)
        mock_import_vm.assert_called_once_with(mock.sentinel.instance_dir)
        self._migrationops._vmops.update_vm_resources.assert_called_once_with(
            mock_instance, get_image_vm_gen.return_value,
            mock.sentinel.image_meta, mock.sentinel.instance_dir,
            mock.sentinel.resize_instance)
        self._migrationops._volumeops.connect_volumes.assert_called_once_with(
            block_device_info)
        mock_update_disk_image_paths.assert_called_once_with(
            mock_instance, mock.sentinel.instance_dir)
        mock_check_and_update_disks.assert_called_once_with(
            self.context, mock_instance, get_image_vm_gen.return_value,
            mock.sentinel.image_meta, block_device_info,
            resize_instance=mock.sentinel.resize_instance)
        self._volumeops.fix_instance_volume_disk_paths.assert_called_once_with(
            mock_instance.name, block_device_info)
        self._migrationops._migrationutils.realize_vm.assert_called_once_with(
            mock_instance.name)
        mock_check_eph_disks.assert_called_once_with(
            mock_instance, mock.sentinel.ephemerals,
            mock.sentinel.resize_instance)
        self._migrationops._vmops.configure_remotefx.assert_called_once_with(
            mock_instance, get_image_vm_gen.return_value,
            mock.sentinel.resize_instance)
        self._vmops.configure_instance_metrics.assert_called_once_with(
            mock_instance.name)

    def test_import_vm(self):
        self._migrationops._import_vm(mock.sentinel.instance_dir)

        self._pathutils.get_instance_snapshot_dir.assert_called_once_with(
            instance_dir=mock.sentinel.instance_dir)
        self._pathutils.get_vm_config_file.assert_called_once_with(
            self._migrationops._pathutils.get_export_dir.return_value)
        mock_import_vm_definition = (
            self._migrationops._migrationutils.import_vm_definition)
        mock_import_vm_definition.assert_called_once_with(
            self._pathutils.get_vm_config_file.return_value,
            self._pathutils.get_instance_snapshot_dir.return_value)
        self._migrationops._pathutils.get_export_dir.assert_has_calls([
            mock.call(instance_dir=mock.sentinel.instance_dir),
            mock.call(instance_dir=mock.sentinel.instance_dir,
                      remove_dir=True)])

    @mock.patch('os.path.exists')
    def test_update_disk_image_paths(self, mock_exists):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        inst_dir = "instances"
        expected_inst_dir = "expected_instances"
        config_drive_iso = os.path.join(inst_dir, 'configdrive.iso')
        expected_config_drive_iso = os.path.join(expected_inst_dir,
                                                 'configdrive.iso')
        ephemeral_disk = os.path.join(inst_dir, 'eph1.vhdx')
        expected_ephemeral_disk = os.path.join(expected_inst_dir, 'eph1.vhdx')
        other_disk = '//some/path/to/vol-UUID.vhdx'
        disk_files = [config_drive_iso, ephemeral_disk, other_disk]

        self._vmutils.get_vm_storage_paths.return_value = (
            disk_files, mock.sentinel.volume_drives)
        mock_exists.return_value = True

        self._migrationops._update_disk_image_paths(mock_instance,
                                                    expected_inst_dir)

        self._vmutils.get_vm_storage_paths.assert_called_once_with(
            mock_instance.name)
        expected_calls = [
            mock.call(config_drive_iso, expected_config_drive_iso,
                      is_physical=False),
            mock.call(ephemeral_disk, expected_ephemeral_disk,
                      is_physical=False)]
        self._vmutils.update_vm_disk_path.assert_has_calls(expected_calls)

    @mock.patch('os.path.exists')
    def test_update_disk_image_paths_exception(self, mock_exists):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        inst_dir = "instances"
        disk_files = [os.path.join(inst_dir, "root.vhdx")]

        self._vmutils.get_vm_storage_paths.return_value = (
            disk_files, mock.sentinel.volume_drives)
        self._pathutils.get_instance_dir.return_value = inst_dir
        mock_exists.return_value = False

        self.assertRaises(exception.DiskNotFound,
                          self._migrationops._update_disk_image_paths,
                          mock_instance, inst_dir)

        self._vmutils.get_vm_storage_paths.assert_called_once_with(
            mock_instance.name)
        self.assertFalse(self._vmutils.update_vm_disk_path.called)

    @ddt.data(constants.DISK, mock.sentinel.root_type)
    @mock.patch.object(migrationops.MigrationOps, '_check_base_disk')
    @mock.patch.object(migrationops.MigrationOps, '_check_resize_vhd')
    def test_check_and_update_disks(self, root_type,
                                    mock_check_resize_vhd,
                                    mock_check_base_disk):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        mock_instance.flavor.root_gb = 1
        root_device = {'type': root_type}
        block_device_info = {'root_disk': root_device,
                             'ephemerals': mock.sentinel.ephemerals}
        expected_check_resize = []
        expected_get_info = []

        self._migrationops._check_and_update_disks(
            self.context, mock_instance, mock.sentinel.vm_gen,
            mock.sentinel.image_meta, block_device_info, resize_instance=True)

        mock_bdi = self._block_dev_man.validate_and_update_bdi
        mock_bdi.assert_called_once_with(
            mock_instance, mock.sentinel.image_meta, mock.sentinel.vm_gen,
            block_device_info)

        if root_device['type'] == constants.DISK:
            root_device_path = (
                self._pathutils.lookup_root_vhd_path.return_value)
            self._pathutils.lookup_root_vhd_path.assert_called_once_with(
                mock_instance.name)
            expected_get_info = [mock.call(root_device_path)]

            mock_vhd_info = self._vhdutils.get_vhd_info.return_value
            mock_vhd_info.get.assert_called_once_with("ParentPath")
            mock_check_base_disk.assert_called_once_with(
                self.context, mock_instance, root_device_path,
                mock_vhd_info.get.return_value)
            expected_check_resize.append(
                mock.call(root_device_path, mock_vhd_info,
                          mock_instance.flavor.root_gb * units.Gi))
        else:
            self.assertFalse(self._pathutils.lookup_root_vhd_path.called)

        mock_check_resize_vhd.assert_has_calls(expected_check_resize)
        self._vhdutils.get_vhd_info.assert_has_calls(
            expected_get_info)

    def test_check_and_update_disks_not_found(self):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        root_device = {'type': constants.DISK}
        block_device_info = {'root_disk': root_device}

        self._pathutils.lookup_root_vhd_path.return_value = None

        self.assertRaises(exception.DiskNotFound,
                          self._migrationops._check_and_update_disks,
                          self.context, mock_instance, mock.sentinel.vm_gen,
                          mock.sentinel.image_meta, block_device_info,
                          resize_instance=True)

        self._pathutils.get_instance_dir.assert_called_once_with(
            mock_instance.name)

    @mock.patch.object(migrationops.MigrationOps, '_check_resize_vhd')
    @mock.patch.object(migrationops.LOG, 'warning')
    def test_check_ephemeral_disks_multiple_eph_warn(self, mock_warn,
                                                     mock_check_resize_vhd):
        mock_instance = fake_instance.fake_instance_obj(self.context)
        mock_instance.ephemeral_gb = 3
        mock_ephemerals = [{'size': 1}, {'size': 1}]

        self._migrationops._check_ephemeral_disks(mock_instance,
                                                  mock_ephemerals,
                                                  True)

        mock_warn.assert_called_once_with(
            "Cannot resize multiple ephemeral disks for instance.",
            instance=mock_instance)

    def test_check_ephemeral_disks_exception(self):
        mock_instance = fake_instance.fake_instance_obj(self.context,
                                                        ephemeral_gb=1)
        mock_ephemerals = [dict(size=1)]

        lookup_eph_path = (
            self._migrationops._pathutils.lookup_ephemeral_vhd_path)
        lookup_eph_path.return_value = None

        self.assertRaises(exception.DiskNotFound,
                          self._migrationops._check_ephemeral_disks,
                          mock_instance, mock_ephemerals)

    @ddt.data({},
              {'existing_eph_path': mock.sentinel.eph_path},
              {'existing_eph_path': mock.sentinel.eph_path,
               'new_eph_size': 0},
              {'use_default_eph': True})
    @ddt.unpack
    @mock.patch.object(migrationops.MigrationOps, '_check_resize_vhd')
    def test_check_ephemeral_disks(self, mock_check_resize_vhd,
                                   existing_eph_path=None, new_eph_size=42,
                                   use_default_eph=False):
        mock_vmops = self._migrationops._vmops

        mock_instance = fake_instance.fake_instance_obj(self.context)
        mock_instance.ephemeral_gb = new_eph_size
        eph = {}
        mock_ephemerals = [eph] if not use_default_eph else []

        mock_pathutils = self._migrationops._pathutils
        lookup_eph_path = mock_pathutils.lookup_ephemeral_vhd_path
        lookup_eph_path.return_value = existing_eph_path
        mock_get_eph_vhd_path = mock_pathutils.get_ephemeral_vhd_path
        mock_get_eph_vhd_path.return_value = mock.sentinel.get_path

        mock_vhdutils = self._migrationops._vhdutils
        mock_get_vhd_format = mock_vhdutils.get_best_supported_vhd_format
        mock_get_vhd_format.return_value = mock.sentinel.vhd_format

        self._vmutils.get_free_controller_slot.return_value = (
            mock.sentinel.ctrl_slot)

        attached_eph_paths = [mock.sentinel.eph_path,
                              mock.sentinel.default_eph_path]
        mock_vmops.get_attached_ephemeral_disks.return_value = (
            attached_eph_paths)

        self._migrationops._check_ephemeral_disks(mock_instance,
                                                  mock_ephemerals,
                                                  True)

        if not use_default_eph:
            self.assertEqual(mock_instance.ephemeral_gb, eph['size'])
        if not existing_eph_path:
            mock_vmops.create_ephemeral_disk.assert_called_once_with(
                mock_instance.name, mock.ANY)
            self._vmutils.get_vm_scsi_controller.assert_called_once_with(
                mock_instance.name)
            self._vmutils.get_free_controller_slot.assert_called_once_with(
                self._vmutils.get_vm_scsi_controller.return_value)

            create_eph_args = mock_vmops.create_ephemeral_disk.call_args_list
            created_eph = create_eph_args[0][0][1]
            self.assertEqual(mock.sentinel.vhd_format, created_eph['format'])
            self.assertEqual(mock.sentinel.get_path, created_eph['path'])
            self.assertEqual(constants.CTRL_TYPE_SCSI,
                             created_eph['disk_bus'])
            self.assertEqual(mock.sentinel.ctrl_slot,
                             created_eph['ctrl_disk_addr'])
        elif new_eph_size:
            mock_check_resize_vhd.assert_called_once_with(
                existing_eph_path,
                self._migrationops._vhdutils.get_vhd_info.return_value,
                mock_instance.ephemeral_gb * units.Gi)
            self.assertEqual(existing_eph_path, eph['path'])
        else:
            self._vmutils.detach_vm_disk.assert_has_calls(
                [mock.call(mock_instance.name, eph_path,
                          is_physical=False)
                 for eph_path in attached_eph_paths],
                any_order=True)
            self._migrationops._pathutils.remove.assert_has_calls(
                [mock.call(eph_path) for eph_path in attached_eph_paths],
                any_order=True)

redpajama_set_name: RedPajamaGithub


text:
using System;
using System.Collections.Generic;
using System.Linq;
using Cake.Core;
using Cake.Core.Annotations;

namespace Cake.Docker
{
    // Contains functionality for working with docker buildx version command.
    partial class DockerAliases
    {
        /// <summary>
        /// List images given <paramref name="settings"/>.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="settings">The settings.</param>
        /// <returns>Output text.</returns>
        /// <remarks>Return value are the lines from stdout. This method will redirect stdout and it won't be available for capture.</remarks>
        [CakeMethodAlias]
        public static IEnumerable<string> DockerBuildXVersion(this ICakeContext context, DockerBuildXVersionSettings settings = null)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var runner = new GenericDockerRunner<DockerBuildXVersionSettings>(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools);
            return runner.RunWithResult("buildx version", settings ?? new DockerBuildXVersionSettings(), r => r.ToArray());
        }
    }
}


text:
django-autoslug-field
######################

AutoSlugField for Django based on django-extensions AutoSlugField, adds option to track foreignkey/parent field for slug.

Installation
=============

Install ``django-autoslug-field`` like you would install any other pypi package::

    pip install django-autoslug-field

Configuration and usage
========================

* add ``django_autoslug`` to the list of ``INSTALLED_APPS`` in your ``settings.py``
* use in ``models.py``::

    from django_autoslug.fields import AutoSlugField

    ...

    class MyModel(models.Model):
        lang = models.CharField(_('lang'), max_length=50, choices=settings.LANGUAGES)
        title = models.CharField(_('title'), max_length=255)
        parent = models.ForeignKey('MyModel', blank=True, null=True)
        slug = AutoSlugField(populate_from=('title',), recursive='parent', prefix_from=('lang',), unique=True, max_length=255, overwrite=True)

* install ``http://pypi.python.org/pypi/pytils`` if you need russian translit support


text:
using System;
using Pantheon.Client.PacketRouting;
using Pantheon.Client.Packets;

namespace Pantheon.Client.Extensions
{
    internal class DatagramCallback
    {
        private Datagram _datagram;
        private PacketRouter _router;
        private TimeSpan _timeout;

        public DatagramCallback(PacketRouter router, Datagram datagram, int timeout)
        {
            _router = router;
            _datagram = datagram;
            _timeout = new TimeSpan(0, 0, 0, 0, timeout);
        }

        public DatagramCallbackAwaiter GetAwaiter()
        {
            return new DatagramCallbackAwaiter(_router, _datagram, _timeout);
        }
    }
}


text:
package android.permission.cts;

import android.content.Context;
import android.net.ConnectivityManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

/**
* Test that protected android.net.ConnectivityManager methods cannot be called without
* permissions
*/
public class ConnectivityManagerPermissionTest extends AndroidTestCase {

    private ConnectivityManager mConnectivityManager = null;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mConnectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        assertNotNull(mConnectivityManager);
    }

    /**
     * Verify that calling {@link ConnectivityManager#getNetworkInfo(int))}
     * requires permissions.
     *
Tests Permission:
     *   {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
     */
    @SmallTest
    public void testGetNetworkInfo() {
        try {
            mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            fail("Was able to call getNetworkInfo");
        } catch (SecurityException e) {
            // expected
        }
    }

    /**
     * Verify that calling {@link ConnectivityManager#getNetworkPreference()}
     * requires permissions.
     *
Tests Permission:
     *   {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
     */
    @SmallTest
    public void testGetNetworkPreference() {
        try {
            mConnectivityManager.getNetworkPreference();
            fail("Was able to call getNetworkPreference");
        } catch (SecurityException e) {
            // expected
        }
    }

    /**
     * Verify that calling {@link ConnectivityManager#requestRouteToHost(int, int)}
     * requires permissions.
     *
Tests Permission:
     *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
     */
    @SmallTest
    public void testRequestRouteToHost() {
        try {
            mConnectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE, 1);
            fail("Was able to call requestRouteToHost");
        } catch (SecurityException e) {
            // expected
        }
    }

    /**
     * Verify that calling {@link ConnectivityManager#setNetworkPreference(int)}
     * requires permissions.
     *
Tests Permission:
     *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
     */
    @SmallTest
    public void testSetNetworkPreference() {
        try {
            mConnectivityManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
            fail("Was able to call setNetworkPreference");
        } catch (SecurityException e) {
            // expected
        }
    }

    /**
     * Verify that calling {@link ConnectivityManager#setNetworkPreference(int)}
     * requires permissions.
     *
Tests Permission:
     *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
     */
    @SmallTest
    public void testStartUsingNetworkPreference() {
        try {
            mConnectivityManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
            fail("Was able to call setNetworkPreference");
        } catch (SecurityException e) {
            // expected
        }
    }
}


text:
include(FetchContent)
set(FETCHCONTENT_QUIET ON)
set(FETCHCONTENT_UPDATES_DISCONNECTED ON)
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
find_package(Git REQUIRED)

set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE)
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
FetchContent_Declare(
        benchmark
        GIT_REPOSITORY "https://github.com/google/benchmark.git"
        GIT_TAG 090faecb454fbd6e6e17a75ef8146acb037118d4
        PATCH_COMMAND ""
)
FetchContent_MakeAvailable(benchmark)
FetchContent_GetProperties(benchmark SOURCE_DIR BENCHMARK_INCLUDE_DIR)
include_directories(${BENCHMARK_INCLUDE_DIR})


text:
@interface JSQMessagesKeyboardControllerTests : XCTestCase
@end

@implementation JSQMessagesKeyboardControllerTests

- (void)setUp
{
    [super setUp];
}

- (void)tearDown
{
    [super tearDown];
}

- (void)testKeyboardControllerInit
{
    JSQMessagesKeyboardController *keyboardController = [[JSQMessagesKeyboardController alloc] initWithTextView:[UITextView new]
                                                                                contextView:[UIView new]
                                                                                panGestureRecognizer:[UIPanGestureRecognizer new]
                                                                                delegate:nil];
    XCTAssertNotNil(keyboardController, @"Keyboard controller should not be nil");

    XCTAssertThrows([[JSQMessagesKeyboardController alloc] initWithTextView:nil
                                                                contextView:nil
                                                       panGestureRecognizer:nil
                                                                   delegate:nil], @"Invalid init should throw");
}

@end