#include <iostream>
#include <vector>

using namespace std;

const int N = 3005;

//逻辑和完全背包基本一样,注意对于w = 0的特殊处理,然后就是使用二维状态会oom,需要使用dp[j]滚动数组优化
int main() {
	int t;
	cin >> t;
	int n, m;
	vector<int> w;
	vector<int> v;
	long long* dp = new long long[N + 1];
	while (t--) {
		cin >> n >> m;
		long long tmp_w, tmp_v, s, free_val = 0;
		w.clear();
		v.clear();
		w.push_back(-1);
		v.push_back(-1);
		for (int i = 0; i < n; i++) {
			cin >> tmp_w >> tmp_v >> s;
			//二进制拆分
			if (tmp_w) {
				int base = 1, cnt = min(m / tmp_w, s);
				while (cnt > 0) {
					int num = min(cnt, base);
					w.push_back(num * tmp_w);
					v.push_back(num * tmp_v);
					cnt -= num;
					base <<= 1;
				}
			} else {
				free_val += s * tmp_v;
			}
		}
		//0 - 1背包, 有num个物品 
		int num = w.size() - 1;
		for (int i = 0; i <= N; i++) {
			dp[i] = 0;
		}
		for (int i = 1; i <= num; i++) {
			for (int j = m; j >= w[i]; j--) {
				dp[j] = max(dp[j - w[i]] + v[i], dp[j]);
			}
		}
		cout << dp[m] + free_val << endl; 
	}
}