diff --git a/build_runner_core/CHANGELOG.md b/build_runner_core/CHANGELOG.md index 5efd73d38..cf38714f0 100644 --- a/build_runner_core/CHANGELOG.md +++ b/build_runner_core/CHANGELOG.md @@ -1,6 +1,7 @@ ## 7.2.4-dev - Fix some new lints. +- Fix a bug in the LRU cache. ## 7.2.3 diff --git a/build_runner_core/lib/src/asset/lru_cache.dart b/build_runner_core/lib/src/asset/lru_cache.dart index b5ff2d2f9..dae0c6f86 100644 --- a/build_runner_core/lib/src/asset/lru_cache.dart +++ b/build_runner_core/lib/src/asset/lru_cache.dart @@ -27,6 +27,7 @@ class LruCache { } void operator []=(K key, V value) { + remove(key); var entry = _Link(key, value, _computeWeight(value)); // Don't cache at all if above the individual weight max. if (entry.weight > _individualWeightMax) { diff --git a/build_runner_core/test/asset/lru_cache_test.dart b/build_runner_core/test/asset/lru_cache_test.dart index e7af987e5..8ca9d34b3 100644 --- a/build_runner_core/test/asset/lru_cache_test.dart +++ b/build_runner_core/test/asset/lru_cache_test.dart @@ -1,6 +1,7 @@ // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +@Timeout(Duration(seconds: 10)) import 'package:build_runner_core/src/asset/lru_cache.dart'; import 'package:test/test.dart'; @@ -66,4 +67,56 @@ void main() { expect(cache['3'], null); expect(cache['4'], null); }); + + test('can update values', () { + cache['a'] = 1; + cache['b'] = 2; + expect(cache['a'], 1); + expect(cache['b'], 2); + + cache['a'] = 3; + cache['b'] = 4; + expect(cache['a'], 3); + expect(cache['b'], 4); + }); + + test('removes least recently used or updated items when full', () { + // Populate the cache until full. + var total = 0; + var n = 0; + while (total + maxIndividualWeight <= maxTotalWeight) { + total += maxIndividualWeight; + cache['$n'] = maxIndividualWeight; + n++; + } + // Read all the items in order, the first is now the least recently used. + for (var i = 0; i < n; i++) { + expect(cache['$i'], maxIndividualWeight); + } + + // Update the first item, then the second is now the least recently used. + cache['0'] = maxIndividualWeight; + // Add another item, the second item should now be removed. + cache['${n + 1}'] = maxIndividualWeight; + expect(cache['1'], null); + + // Read the first n-1 items, then the latest added item is now the least + // recently used. + for (var i = 0; i < n; i++) { + if (i != 1) { + expect(cache['$i'], maxIndividualWeight); + } + } + + // Update all the items in order, the last added item should be removed + for (var i = 0; i < n; i++) { + cache['$i'] = maxIndividualWeight; + } + expect(cache['$n'], null); + + // Check the first n entries shouldn't be removed + for (var i = 0; i < n; i++) { + expect(cache['$i'], maxIndividualWeight); + } + }); }