#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fLL;
const double PI = acos(-1.0);
const double EPS = 1e-9;
const int MOD = 1000000007;
struct Scanner {
  bool hasNext = 1;
  bool hasRead = 1;
  int nextInt() {
    hasRead = 0;
    int res = 0;
    char flag = 1, ch = getchar();
    while (ch != EOF && !isdigit(ch)) {
      hasRead = 1;
      flag = (ch == '-') ? -flag : flag;
      ch = getchar();
    }
    while (ch != EOF && isdigit(ch)) {
      hasRead = 1;
      res = res * 10 + (ch - '0');
      ch = getchar();
    }
    if (ch == EOF) hasNext = 0;
    return res * flag;
  }
  long long nextLL() {
    hasRead = 0;
    long long res = 0;
    char flag = 1, ch = getchar();
    while (ch != EOF && !isdigit(ch)) {
      hasRead = 1;
      flag = (ch == '-') ? -flag : flag;
      ch = getchar();
    }
    while (ch != EOF && isdigit(ch)) {
      hasRead = 1;
      res = res * 10 + (ch - '0');
      ch = getchar();
    }
    if (ch == EOF) hasNext = 0;
    return res * flag;
  }
  char nextChar() {
    hasRead = 0;
    char ch = getchar();
    while (ch != EOF && isspace(ch)) {
      hasRead = 1;
      ch = getchar();
    }
    if (ch == EOF) hasNext = 0;
    return ch;
  }
  int nextString(char *str) {
    hasRead = 0;
    int len = 0;
    char ch = getchar();
    while (ch != EOF && isspace(ch)) {
      hasRead = 1;
      ch = getchar();
    }
    while (ch != EOF && !isspace(ch)) {
      hasRead = 1;
      str[++len] = ch;
      ch = getchar();
    }
    str[len + 1] = 0;
    if (ch == EOF) hasNext = 0;
    return len;
  }
} sc;
long long rd() {
  long long x = sc.nextLL();
  return x;
}
void rd(int &x) { x = sc.nextInt(); }
void rd(long long &x) { x = sc.nextLL(); }
void rd(char &x) { x = sc.nextChar(); }
void rd(char *x) { sc.nextString(x); }
template <typename T1, typename T2>
void rd(pair<T1, T2> &x) {
  rd(x.first);
  rd(x.second);
}
template <typename T>
void rd(T *x, int n) {
  for (int i = 1; i <= n; ++i) rd(x[i]);
}
void printInt(int x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x >= 10) printInt(x / 10);
  putchar('0' + x % 10);
}
void printLL(long long x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x >= 10) printLL(x / 10);
  putchar('0' + x % 10);
}
void pr(int x, char ch = '\n') {
  printInt(x);
  putchar(ch);
}
void pr(long long x, char ch = '\n') {
  printLL(x);
  putchar(ch);
}
template <typename T1, typename T2>
void pr(pair<T1, T2> x, char ch = '\n') {
  pr(x.first, ' ');
  pr(x.second, ch);
}
template <typename T>
void pr(T *x, int n) {
  for (int i = 1; i <= n; ++i) pr(x[i], " \n"[i == n]);
}
template <typename T>
void pr(vector<T> &x) {
  int n = x.size();
  for (int i = 1; i <= n; ++i) pr(x[i - 1], " \n"[i == n]);
}
template <typename T>
void cmin(T &x, T y) {
  if (y < x) x = y;
}
template <typename T>
void cmax(T &x, T y) {
  if (y > x) x = y;
}
int n;
int a[500005];
struct SegmentTree {
  static const int MAXN = 5e5 + 10;
  static const long long LINF = 1e18 + 10;
  long long mx[MAXN << 2];
  void PushUp(int u) { mx[u] = max(mx[(u << 1)], mx[(u << 1 | 1)]); }
  void Build(int u, int l, int r) {
    if (l == r) {
      mx[u] = a[l];
      return;
    }
    Build((u << 1), l, ((l + r) >> 1));
    Build((u << 1 | 1), ((l + r) >> 1) + 1, r);
    PushUp(u);
  }
  int QueryMax(int u, int l, int r, int L, int R, int k) {
    if (l == r) {
      if (l < L || r > R) return n + 1;
      if (mx[u] >= k)
        return l;
      else
        return n + 1;
    }
    int res = n + 1;
    if (L <= ((l + r) >> 1)) {
      if (mx[(u << 1)] >= k) {
        cmin(res, QueryMax((u << 1), l, ((l + r) >> 1), L, R, k));
        if (res != n + 1) return res;
      }
    }
    if (mx[(u << 1 | 1)] >= k) {
      cmin(res, QueryMax((u << 1 | 1), ((l + r) >> 1) + 1, r, L, R, k));
      if (res != n + 1) return res;
    }
    return res;
  }
} st;
struct Graph {
  static const int MAXN = 5e5 + 10;
  int n;
  vector<int> eout[MAXN];
  int din[MAXN];
  int topo[MAXN];
  void init(int n) {
    this->n = n;
    for (int i = 1; i <= n; ++i) {
      eout[i].clear();
      din[i] = 0;
    }
  }
  void addEdge(int u, int v) {
    eout[u].emplace_back(v);
    ++din[v];
  }
  bool topoSort() {
    int ft = 1, bk = 0;
    for (int i = 1; i <= n; ++i) {
      if (din[i] == 0) topo[++bk] = i;
    }
    while (ft <= bk) {
      int u = topo[ft++];
      for (int &v : eout[u]) {
        --din[v];
        if (din[v] == 0) topo[++bk] = v;
      }
    }
    return bk == n;
  }
} G;
stack<int> Q;
struct Solver {
  void InitOnce() {}
  void Read() {
    rd(n);
    rd(a, n);
  }
  void Solve() {
    a[n + 1] = n + 1;
    for (int i = 1; i <= n; ++i) {
      if (a[i] == -1) a[i] = i + 1;
    }
    while (!Q.empty()) Q.pop();
    Q.push(INF);
    for (int i = 1; i <= n; ++i) {
      while (i >= Q.top()) Q.pop();
      if (a[i] > Q.top()) {
        puts("-1");
        return;
      }
      if (a[i] < Q.top()) {
        Q.push(a[i]);
        continue;
      }
    }
    st.Build(1, 1, n + 1);
    G.init(n + 1);
    for (int i = 1; i <= n; ++i) {
      G.addEdge(a[i], i);
      if (a[i] != i + 1) {
        int L = i + 1, R = a[i] - 1;
        if (R >= L) {
          int maxpos = st.QueryMax(1, 1, n + 1, L, R, a[i]);
          G.addEdge(i, maxpos);
        }
      }
    }
    if (G.topoSort() == 0)
      puts("-1");
    else {
      int cur = n;
      int *b = G.topo + 1;
      for (int i = 1; i <= n; ++i) a[b[i]] = cur--;
      pr(a, n);
    }
  }
} solver;
int main() {
  solver.InitOnce();
  int t = 1;
  t = sc.nextInt();
  t = INF;
  while (t--) {
    solver.Read();
    if (!sc.hasRead) break;
    solver.Solve();
    if (!sc.hasNext) break;
  }
  return 0;
}
