Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  test_l10nCache.js

  Sprache: JAVA
 

/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */


// Tests L10nCache in UrlbarUtils.sys.mjs.

"use strict";

ChromeUtils.defineESModuleGetters(this, {
  L10nCache: "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs",
});

add_task(async function comprehensive() {
  // Set up a mock localization.
  let l10n = initL10n({
    args0a: "Zero args value",
    args0b: "Another zero args value",
    args1a: "One arg value is { $arg1 }",
    args1b: "Another one arg value is { $arg1 }",
    args2a: "Two arg values are { $arg1 } and { $arg2 }",
    args2b: "More two arg values are { $arg1 } and { $arg2 }",
    args3a: "Three arg values are { $arg1 }, { $arg2 }, and { $arg3 }",
    args3b: "More three arg values are { $arg1 }, { $arg2 }, and { $arg3 }",
    attrs1: [".label = attrs1 label has zero args"],
    attrs2: [
      ".label = attrs2 label has zero args",
      ".tooltiptext = attrs2 tooltiptext arg value is { $arg1 }",
    ],
    attrs3: [
      ".label = attrs3 label has zero args",
      ".tooltiptext = attrs3 tooltiptext arg value is { $arg1 }",
      ".alt = attrs3 alt arg values are { $arg1 } and { $arg2 }",
    ],
  });

  let tests = [
    // different strings with the same number of args and also the same strings
    // with different args
    {
      obj: {
        id: "args0a",
      },
      expected: {
        value: "Zero args value",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args0b",
      },
      expected: {
        value: "Another zero args value",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args1a",
        args: { arg1: "foo1" },
      },
      expected: {
        value: "One arg value is foo1",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args1a",
        args: { arg1: "foo2" },
      },
      expected: {
        value: "One arg value is foo2",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args1b",
        args: { arg1: "foo1" },
      },
      expected: {
        value: "Another one arg value is foo1",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args1b",
        args: { arg1: "foo2" },
      },
      expected: {
        value: "Another one arg value is foo2",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args2a",
        args: { arg1: "foo1", arg2: "bar1" },
      },
      expected: {
        value: "Two arg values are foo1 and bar1",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args2a",
        args: { arg1: "foo2", arg2: "bar2" },
      },
      expected: {
        value: "Two arg values are foo2 and bar2",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args2b",
        args: { arg1: "foo1", arg2: "bar1" },
      },
      expected: {
        value: "More two arg values are foo1 and bar1",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args2b",
        args: { arg1: "foo2", arg2: "bar2" },
      },
      expected: {
        value: "More two arg values are foo2 and bar2",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args3a",
        args: { arg1: "foo1", arg2: "bar1", arg3: "baz1" },
      },
      expected: {
        value: "Three arg values are foo1, bar1, and baz1",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args3a",
        args: { arg1: "foo2", arg2: "bar2", arg3: "baz2" },
      },
      expected: {
        value: "Three arg values are foo2, bar2, and baz2",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args3b",
        args: { arg1: "foo1", arg2: "bar1", arg3: "baz1" },
      },
      expected: {
        value: "More three arg values are foo1, bar1, and baz1",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args3b",
        args: { arg1: "foo2", arg2: "bar2", arg3: "baz2" },
      },
      expected: {
        value: "More three arg values are foo2, bar2, and baz2",
        attributes: null,
      },
    },

    // two instances of the same string with their args swapped
    {
      obj: {
        id: "args2a",
        args: { arg1: "arg A", arg2: "arg B" },
      },
      expected: {
        value: "Two arg values are arg A and arg B",
        attributes: null,
      },
    },
    {
      obj: {
        id: "args2a",
        args: { arg1: "arg B", arg2: "arg A" },
      },
      expected: {
        value: "Two arg values are arg B and arg A",
        attributes: null,
      },
    },

    // strings with attributes
    {
      obj: {
        id: "attrs1",
      },
      expected: {
        value: null,
        attributes: {
          label: "attrs1 label has zero args",
        },
      },
    },
    {
      obj: {
        id: "attrs2",
        args: {
          arg1: "arg A",
        },
      },
      expected: {
        value: null,
        attributes: {
          label: "attrs2 label has zero args",
          tooltiptext: "attrs2 tooltiptext arg value is arg A",
        },
      },
    },
    {
      obj: {
        id: "attrs3",
        args: {
          arg1: "arg A",
          arg2: "arg B",
        },
      },
      expected: {
        value: null,
        attributes: {
          label: "attrs3 label has zero args",
          tooltiptext: "attrs3 tooltiptext arg value is arg A",
          alt: "attrs3 alt arg values are arg A and arg B",
        },
      },
    },
  ];

  let cache = new L10nCache(l10n);

  // Get some non-cached strings.
  Assert.ok(!cache.get({ id: "uncached1" }), "Uncached string 1");
  Assert.ok(!cache.get({ id: "uncached2", args: "foo" }), "Uncached string 2");

  // Add each test string and get it back.
  for (let { obj, expected } of tests) {
    await cache.add(obj);
    let message = cache.get(obj);
    Assert.deepEqual(
      message,
      expected,
      "Expected message for obj: " + JSON.stringify(obj)
    );
  }

  // Get each string again to make sure each add didn't somehow mess up the
  // previously added strings.
  for (let { obj, expected } of tests) {
    Assert.deepEqual(
      cache.get(obj),
      expected,
      "Expected message for obj: " + JSON.stringify(obj)
    );
  }

  // Delete some of the strings. We'll delete every other one to mix it up.
  for (let i = 0; i < tests.length; i++) {
    if (i % 2 == 0) {
      let { obj } = tests[i];
      cache.delete(obj);
      Assert.ok(!cache.get(obj), "Deleted from cache: " + JSON.stringify(obj));
    }
  }

  // Get each remaining string.
  for (let i = 0; i < tests.length; i++) {
    if (i % 2 != 0) {
      let { obj, expected } = tests[i];
      Assert.deepEqual(
        cache.get(obj),
        expected,
        "Expected message for obj: " + JSON.stringify(obj)
      );
    }
  }

  // Clear the cache.
  cache.clear();
  for (let { obj } of tests) {
    Assert.ok(!cache.get(obj), "After cache clear: " + JSON.stringify(obj));
  }

  // `ensure` each test string and get it back.
  for (let { obj, expected } of tests) {
    await cache.ensure(obj);
    let message = cache.get(obj);
    Assert.deepEqual(
      message,
      expected,
      "Expected message for obj: " + JSON.stringify(obj)
    );

    // Call `ensure` again. This time, `add` should not be called.
    let originalAdd = cache.add;
    cache.add = () => Assert.ok(false"add erroneously called");
    await cache.ensure(obj);
    cache.add = originalAdd;
  }

  // Clear the cache again.
  cache.clear();
  for (let { obj } of tests) {
    Assert.ok(!cache.get(obj), "After cache clear: " + JSON.stringify(obj));
  }

  // `ensureAll` the test strings and get them back.
  let objects = tests.map(({ obj }) => obj);
  await cache.ensureAll(objects);
  for (let { obj, expected } of tests) {
    let message = cache.get(obj);
    Assert.deepEqual(
      message,
      expected,
      "Expected message for obj: " + JSON.stringify(obj)
    );
  }

  // Ensure the cache is cleared after the app locale changes
  Assert.greater(cache.size(), 0"The cache has messages in it.");
  Services.obs.notifyObservers(null"intl:app-locales-changed");
  Assert.equal(cache.size(), 0"The cache is empty on app locale change");
});

// Tests cache eviction.
add_task(async function eviction() {
  // Set up a mock localization.
  let l10n = initL10n({
    args0: "Zero args value",
    args1: "One arg value is { $arg1 }",
    args2: "Two arg values are { $arg1 } and { $arg2 }",
    args3: "Three arg values are { $arg1 }, { $arg2 }, and { $arg3 }",

    attrs0: [".label = attrs0 label has zero args"],
    attrs1: [
      ".label = attrs1 label has zero args",
      ".tooltiptext = attrs1 tooltiptext arg value is { $arg1 }",
    ],
    attrs2: [
      ".label = attrs2 label has zero args",
      ".tooltiptext = attrs2 tooltiptext arg value is { $arg1 }",
      ".alt = attrs2 alt arg values are { $arg1 } and { $arg2 }",
    ],
  });

  let cache = new L10nCache(l10n);

  // Get the max cache entries per l10n ID.
  let maxEntriesPerId = L10nCache.MAX_ENTRIES_PER_ID;
  Assert.equal(
    typeof maxEntriesPerId,
    "number",
    "MAX_ENTRIES_PER_ID should be a number"
  );
  Assert.greater(maxEntriesPerId, 0"MAX_ENTRIES_PER_ID should be > 0");

  // Cache enough l10n objects with the same ID but different args to fill up
  // the ID's cache entries. The args will be "aaa-0", "aaa-1", etc.
  for (let i = 0; i < maxEntriesPerId; i++) {
    let arg1 = "aaa-" + i;
    let l10nObj = {
      id: "args1",
      args: { arg1 },
    };
    await cache.add(l10nObj);

    // The message should be cached.
    Assert.deepEqual(
      cache.get(l10nObj),
      {
        value: `One arg value is ${arg1}`,
        attributes: null,
      },
      "Message should be cached: " + JSON.stringify(l10nObj)
    );

    // The cache size should be incremented.
    Assert.equal(
      cache.size(),
      i + 1,
      "Expected cache size after adding l10n obj: " + JSON.stringify(l10nObj)
    );
  }

  // Check some l10n objects we did not cache.
  for (let arg1 of [`aaa-${maxEntriesPerId}`, "some other value"]) {
    let l10nObj = {
      id: "args1",
      args: { arg1 },
    };
    Assert.ok(
      !cache.get(l10nObj),
      "Message should not be cached since it wasn't added: " +
        JSON.stringify(l10nObj)
    );
  }

  // Now cache more l10n objects with the same ID as before but with new args:
  // "bbb-0", "bbb-1", etc. Each time we cache a new object, the oldest "aaa"
  // entry should be evicted since the ID's cache entries are filled up.
  for (let i = 0; i < maxEntriesPerId; i++) {
    let arg1 = "bbb-" + i;
    let l10nObj = {
      id: "args1",
      args: { arg1 },
    };
    await cache.add(l10nObj);

    // The message should be cached.
    Assert.deepEqual(
      cache.get(l10nObj),
      {
        value: `One arg value is ${arg1}`,
        attributes: null,
      },
      "Message should be cached: " + JSON.stringify(l10nObj)
    );

    // The cache size should remain maxed out.
    Assert.equal(
      cache.size(),
      maxEntriesPerId,
      "Cache size should remain maxed out after caching l10n obj: " +
        JSON.stringify(l10nObj)
    );

    // The oldest "aaa" entry should have been evicted, and all previous oldest
    // entries in prior iterations of this loop should remain evicted.
    for (let j = 0; j < maxEntriesPerId; j++) {
      let oldArg1 = "aaa-" + j;
      let oldL10nObj = {
        id: "args1",
        args: { arg1: oldArg1 },
      };
      if (j <= i) {
        Assert.deepEqual(
          cache.get(oldL10nObj),
          null,
          "Message should be evicted for old l10n obj: " +
            JSON.stringify(oldL10nObj)
        );
      } else {
        Assert.deepEqual(
          cache.get(oldL10nObj),
          {
            value: `One arg value is ${oldArg1}`,
            attributes: null,
          },
          "Message should not yet be evicted for old l10n obj: " +
            JSON.stringify(oldL10nObj)
        );
      }
    }
  }

  // Now cache more l10n objects just like before but with a different ID. Since
  // the ID is new, we should be able to fill up its cache entries.
  for (let i = 0; i < maxEntriesPerId; i++) {
    let arg1 = "yyy-" + i;
    let arg2 = "zzz-" + i;
    let l10nObj = {
      id: "args2",
      args: { arg1, arg2 },
    };
    await cache.add(l10nObj);

    // The message should be cached.
    Assert.deepEqual(
      cache.get(l10nObj),
      {
        value: `Two arg values are ${arg1} and ${arg2}`,
        attributes: null,
      },
      "Message should be cached: " + JSON.stringify(l10nObj)
    );

    // The cache size should start increasing again since we're caching l10n
    // objects with a different ID from before.
    Assert.equal(
      cache.size(),
      maxEntriesPerId + i + 1,
      "Cache size should start increasing again: " + JSON.stringify(l10nObj)
    );

    // All the messages with the "args1" ID from above should remain cached.
    for (let j = 0; j < maxEntriesPerId; j++) {
      let prevArg1 = "bbb-" + j;
      let prevL10nObj = {
        id: "args1",
        args: { arg1: prevArg1 },
      };
      Assert.deepEqual(
        cache.get(prevL10nObj),
        {
          value: `One arg value is ${prevArg1}`,
          attributes: null,
        },
        "Previous message should remain cached: " + JSON.stringify(prevL10nObj)
      );
    }
  }

  // Now re-cache some of the previously cached "args1" messages. This should
  // reorder the "args1" cache entries so that these re-cached messages are most
  // recently used. We'll re-cache messages with even-numbered args values.
  for (let i = 0; i < maxEntriesPerId; i++) {
    if (i % 2 == 0) {
      let arg1 = "bbb-" + i;
      let l10nObj = {
        id: "args1",
        args: { arg1 },
      };
      Assert.ok(
        await cache.get(l10nObj),
        "Sanity check: Message should still be cached: " +
          JSON.stringify(l10nObj)
      );
      await cache.add(l10nObj);

      // The cache size should remain maxed out.
      Assert.equal(
        cache.size(),
        2 * maxEntriesPerId,
        "Cache size should remain maxed out after caching l10n obj: " +
          JSON.stringify(l10nObj)
      );
    }
  }

  // Build a list of args in the expected cached "args1" entries sorted from
  // least recently used to most recently used. Since we just re-cached messages
  // with even-numbered args, they should be at the end of this list, and
  // messages with odd-numbered args should be at the front.
  let expected = [];
  for (let i = 0; i < maxEntriesPerId; i++) {
    if (i % 2) {
      // odd
      expected.push("bbb-" + i);
    }
  }
  for (let i = 0; i < maxEntriesPerId; i++) {
    if (i % 2 == 0) {
      // even
      expected.push("bbb-" + i);
    }
  }

  // Now cache more l10n objects with the same "args1" ID but with new args.
  // The old "bbb" entries should be evicted in the expected order.
  for (let i = 0; i < maxEntriesPerId; i++) {
    let arg1 = "ccc-" + i;
    let l10nObj = {
      id: "args1",
      args: { arg1 },
    };
    await cache.add(l10nObj);

    // The message should be cached.
    Assert.deepEqual(
      cache.get(l10nObj),
      {
        value: `One arg value is ${arg1}`,
        attributes: null,
      },
      "Message should be cached: " + JSON.stringify(l10nObj)
    );

    // The cache size should remain maxed out.
    Assert.equal(
      cache.size(),
      2 * maxEntriesPerId,
      "Cache size should remain maxed out after caching l10n obj: " +
        JSON.stringify(l10nObj)
    );

    // The oldest entry should have been evicted, and all previous oldest
    // entries in prior iterations of this loop should remain evicted.
    for (let j = 0; j < expected.length; j++) {
      let oldArg1 = expected[j];
      let oldL10nObj = {
        id: "args1",
        args: { arg1: oldArg1 },
      };
      if (j <= i) {
        Assert.deepEqual(
          cache.get(oldL10nObj),
          null,
          "Message should be evicted for old l10n obj: " +
            JSON.stringify(oldL10nObj)
        );
      } else {
        Assert.deepEqual(
          cache.get(oldL10nObj),
          {
            value: `One arg value is ${oldArg1}`,
            attributes: null,
          },
          "Message should not yet be evicted for old l10n obj: " +
            JSON.stringify(oldL10nObj)
        );
      }
    }
  }
});

/**
 * Sets up a mock localization.
 *
 * @param {object} pairs
 *   Fluent strings as key-value pairs.
 * @returns {Localization}
 *   The mock Localization object.
 */

function initL10n(pairs) {
  let source = Object.entries(pairs)
    .map(([key, value]) => {
      if (Array.isArray(value)) {
        value = value.map(s => "  \n" + s).join("");
      }
      return `${key} = ${value}`;
    })
    .join("\n");
  let registry = new L10nRegistry();
  registry.registerSources([
    L10nFileSource.createMock(
      "test",
      "app",
      ["en-US"],
      "/localization/{locale}",
      [{ source, path: "/localization/en-US/test.ftl" }]
    ),
  ]);
  return new Localization(["/test.ftl"], true, registry, ["en-US"]);
}

Messung V0.5 in Prozent
C=89 H=90 G=89

¤ Dauer der Verarbeitung: 0.10 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=655579